CFNetwork

RSS for tag

Access network services and handle changes in network configurations using CFNetwork.

CFNetwork Documentation

Pinned Posts

Posts under CFNetwork tag

153 Posts
Sort by:
Post not yet marked as solved
12 Replies
1.9k Views
Hi, The article https://developer.apple.com/news/?id=g9ejcf8y "Identity Pinning: How to configure server certificates for your app" from 2021-01-14 looks really promising. However, I cannot get the settings to have any effect on iOS 14.3 (Xcode 12.3). I tested with NSPinnedCAIdentities and Charles Proxy as well as an incorrect RootCA key. In both cases the requests were successful, Charles was able to decrypt the traffic. Questions that come to my mind: Where is the detailed documentation of the keys? Which platforms/versions are supported? Thanks and kind regards, Lars
Posted
by lpe.
Last updated
.
Post not yet marked as solved
1 Replies
284 Views
For a GET request which is consistently the same, I'm returning in the response this response header. Cache-Control: max-age=3600, private I'm creating a URLSession with this configuration. Basically, ensuring my cache is large. The URLSession persists throughout the life of the app and all requests go through it.  var configuration = URLSessionConfiguration.default           let cache = URLCache(memoryCapacity: 500_000_000,                                diskCapacity: 1_000_000_000)         configuration.urlCache = cache         configuration.requestCachePolicy = .useProtocolCachePolicy I create a data task with the completion handler: let task = session.dataTask(with: request) { data, response, error in //... my response handling code here } task.resume() There isn't anything complicated or unusual I'm doing. I've used this code for years, and I'm now trying to optimise some calls with a caching policy. So I have 2 issues: Requests that have no-cache policy are still being saved into the URLCache. Which I've confirmed by looking into URLCache.shared.cachedResponse . Why is it caching them when the response explicitly states no-cache policy and I've told the session to use the protocol policy. On the request where I do want to use the cache, when I call session.dataTask on subsequent times, it never fetches from the cache. It always hits the server again - which I can confirm from the server logs. What piece of this am I missing here?
Posted Last updated
.
Post not yet marked as solved
1 Replies
354 Views
Hi there, I'm currently initializing a cookie that is supposed to be http only for the security purposes. However, I can't find a way to set the cookie to be http only. Could anyone point me to the right direciton? let cookie = HTTPCookie(properties: [         .domain: "aaa.bbbb.ccc",         .path: "/",         .name: "token",         .value: "aaa.bbb.ccc",         .version: 1,         .secure: true,         .expires: NSDate(timeIntervalSinceNow: 12345)     ])!
Posted
by GefeiShen.
Last updated
.
Post marked as solved
2 Replies
350 Views
Hi team. Like the title, I'm figure out how to create my app so that I don't explicitly display local network privacy alerts. https://developer.apple.com/forums/thread/664116 This thread was a little helpful, but I couldn't find a clear way. Is there a way to automatically reject without explicitly displaying an alert, even if permission is required, such as plist settings? Thanks.
Posted Last updated
.
Post not yet marked as solved
0 Replies
207 Views
I often get questions about disabling the HTTPS default server trust evaluation done by NSURLSession. My general advice is “Don’t do that!” However, there is one case where you have to do that, namely when dealing with a hardware accessory on the local network. This post contains my advice on how to deal with that situation. IMPORTANT If you found your way here and you’re not developing a network-based accessory, I have two suggestions for you: If you’re trying to override HTTPS server trust evaluation for testing purposes, see QA1948 HTTPS and Test Servers. If not, post a question here on DevForums and we’ll try to get you heading in the right direction. Tag it with Security, and either CFNetwork or Network depending on which API you’re using. Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com" TLS For Accessory Developers Communicating securely with a network-based accessory is tricky because the standard network security protocol, TLS, was designed for the wider Internet, where servers have a stable DNS name. A devices on your local network doesn’t have a stable DNS name. The DNS name my-waffle-maker.local. might resolve to your waffle maker today, but tomorrow it might resolve to a different waffle maker or, worse yet, a malicious waffle varnisher. I guarantee that you won’t like them waffles! Note If you’re unfamiliar with TLS in general, I encourage you to read TLS for App Developers first. TLS puts the S into HTTPS. This post focuses on URLSession and HTTPS, because that’s where this most commonly crops up, but similar logic applies to other networking APIs. Doing the Minimum: The SSH Approach Many accessory firmware developers support TLS by generating a self-signed digital identity on the accessory and using that for their HTTPS server. IMO they should do better — the subject of later sections in this post — but sometimes you have to work with what you’ve got. If you’re working with an accessory like this, and you can’t convince the firmware developer to do better, I recommend that you adopt the SSH approach. In this approach you accept the certificate offered by the accessory the first time and then, when you connect again in the future, check the accessory still has the same certificate. Note I call this the SSH approach because that’s how many folks use SSH. To implement the SSH approach, first disable App Transport Security for local networking by setting the NSAllowsLocalNetworking property. On modern systems this isn’t strictly necessary but, as it says in the docs, this is a good “declaration of intent”. Next, override HTTPS server trust evaluation as shown below: var expectedCertificate: SecCertificate? = nil func shouldAllowHTTPSConnection(trust: SecTrust) async -> Bool { guard let chain = SecTrustCopyCertificateChain(trust) as? [SecCertificate], let actual = chain.first else { return false } guard let expected = self.expectedCertificate else { // A. First connection self.expectedCertificate = actual return true } // B. Subsequent connections return CFEqual(expected, actual) } func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge) async -> (URLSession.AuthChallengeDisposition, URLCredential?) { switch challenge.protectionSpace.authenticationMethod { case NSURLAuthenticationMethodServerTrust: let trust = challenge.protectionSpace.serverTrust! guard await self.shouldAllowHTTPSConnection(trust: trust) else { return (.cancelAuthenticationChallenge, nil) } let credential = URLCredential(trust: trust) return (.useCredential, credential) default: return (.performDefaultHandling, nil) } } There are a few things to note here: The snippet uses the new Swift async/await syntax. That simplifies the code and it also avoids a gotcha with the old completion-handler approach, where it was easy to forget to call the completion handler. Having said that, you can achieve the same result without using Swift async/await, or indeed, in Objective-C. The authentication challenge handler only deals with HTTPS server trust challenges (NSURLAuthenticationMethodServerTrust). Critically, if it finds a challenge it doesn’t recognise, it resolves that in the default way (.performDefaultHandling). The shouldAllowHTTPSConnection(trust:) method checks to see if it’s connected to the server before. If not, it defaults to allowing the connection (case A). If so, it checks that the certificate hasn’t changed (case B). In a real app you would persist expectedCertificate so that this logic continues to apply the next time your app is launched. When you do that, store the certificate using a key that uniquely identifies the accessory. Do not use the DNS name or IP address because that can change. The first time you connect (case A) you might take other steps to confirm the identity of the accessory. This is something I’ll cover below. The thing to note here is that this function is async, so you can take your time doing that confirmation. For example, you could bounce over to the main actor and display a UI. Doing Better: Add a Side Channel The above represents the absolute minimum you should do; anything less is doing the user a disservice. Aim to do better! Doing better requires some sort of side channel so that the user can confirm the identity of the accessory. For example: If the accessory has a display, you might present a UI asking the user to confirm that the code in your UI matches the one on the accessory’s display. If the accessory has a LED, it might blink that during this initial setup process. If the accessory has a serial number, you might ask the user to confirm that. Or scan that via a barcode. Note For an example of the barcode approach, see Matt’s Configuring a Wi-Fi Accessory to Join the User’s Network sample. This sample uses a different technique for TLS, namely TLS-PSK. This has some advantages — most notably, it avoids messing around with certificates — but I’m not discussing it here because it’s not supported by URLSession. If you adopt this approach make sure that you present a UI that the user can understand. If your UI contains raw certificate details, most users will just say “Sure, whatever.” and click OK, at which point you might as well have saved everyone’s time by accepting the connection on their behalf. Take care not to blindly trust any information you get from the accessory. After all, the goal here is to check the identity of the accessory, and so you mustn’t trust it before completing that check. Sometimes this can be quite subtle. Consider the accessory-with-a-display example above. In that case the accessory’s self-signed certificate might contain a common name of Acme Waffle Maker CCC, where CCC is the code showing on its display. Don’t display the entire string to the user. The presence of Acme Waffle Maker might lead the user to believe that the accessory is valid, even when it isn’t. After all, a malicious waffle varnisher can just as easily create a self-signed certificate with that common name. Rather, extract the code (CCC) and display just that. That way the user will focus on what’s important. Doing Even Better: Proper Security If the accessory’s firmware and hardware developers are on board, there are steps you can take to properly secure your communication with the accessory: Create a custom certificate authority (CA) for your accessories. At the factory, have that CA issue a certificate to each accessory as its produced, embedding identifying details, like the serial number, in that certificate. Then install that certificate and its associated private key (thus forming a digital identity) on the accessory as it comes off the line. Embed the CA’s certificate in your app. When you connect the accessory, verify that its certificate was issued by your CA. If it was, you can trust the identifying information, like the serial number, embedded in that certificate. With this setup your app will never connect to a malicious accessory. The worst that can happen is that you accidentally connect to the wrong instance of your accessory. IMPORTANT This is just an outline of one approach that I believe offers specific advantages. If you plan to deploy this in practice, hire a security profession to design your process. They can advise you on the details of creating a system that’s secure in practice. For example, they can help you: Create a mechanism that prevents your factory from leaking valid digital identities. Design your hardware to prevent an attacker from extracting an accessory’s digital identity from the accessory itself. To implement the URLSession side of this, change the shouldAllowHTTPSConnection(trust:) method like so: let waffleVarnisherCA: SecCertificate = { let u = Bundle.main.url(forResource: "WaffleVarnisherCA", withExtension: "cer")! let d = try! Data(contentsOf: u) let c = SecCertificateCreateWithData(nil, d as NSData)! return c }() func shouldAllowHTTPSConnection(trust: SecTrust) async -> Bool { var err = SecTrustSetPolicies(trust, SecPolicyCreateBasicX509()) guard err == errSecSuccess else { return false } err = SecTrustSetAnchorCertificates(trust, [self.waffleVarnisherCA] as NSArray) guard err == errSecSuccess else { return false } err = SecTrustSetAnchorCertificatesOnly(trust, true) guard err == errSecSuccess else { return false } let wasIssuedByOurCA = SecTrustEvaluateWithError(trust, nil) guard wasIssuedByOurCA else { return false } guard let chain = SecTrustCopyCertificateChain(trust) as? [SecCertificate], let trustedLeaf = chain.first else { return false } // C. Check the now-trusted leaf certificate return true } There are a few things to note about this code: It changes the trust policy (SecTrustSetPolicies) to the basic X.509 policy (SecPolicyCreateBasicX509) because the standard policy for TLS connections checks the DNS name, and that’s not appropriate for an accessory on the local network. It applies a custom anchor (SecTrustSetAnchorCertificates) and then disables all the other anchors (SecTrustSetAnchorCertificatesOnly) [1]. That prevents someone from impersonating your accessory by getting some other CA to issue a certificate that looks like the accessory’s certificate. It evaluates trust to confirm that the certificate was issued by the accessory’s CA. At point C you can trust the details in the accessory’s certificate (trustedLeaf). Here you might add code to confirm the identity of the accessory, to prevent you from accidentally connecting to the wrong accessory. [1] This is not strictly necessary because calling SecTrustSetAnchorCertificates disables other anchors. However, I’m applying both belt and braces [2] here. [2] I’m using the British idiom because belt and suspenders is so wrong (-:
Posted
by eskimo.
Last updated
.
Post marked as solved
2 Replies
259 Views
Hi, I'm writing code to get a remote image via URL and I get the following error each time. I converted the URL to https as recommended. This is the error I get. URL is Optional(https://img.recipepuppy.com/627470.jpg) 2022-03-29 16:27:41.892870+1100 QantasTest[13489:314159] ATS failed system trust 2022-03-29 16:27:41.892949+1100 QantasTest[13489:314159] Connection 3: system TLS Trust evaluation failed(-9802) 2022-03-29 16:27:41.893119+1100 QantasTest[13489:314159] Connection 3: TLS Trust encountered error 3:-9802 2022-03-29 16:27:41.893212+1100 QantasTest[13489:314159] Connection 3: encountered error(3:-9802) 2022-03-29 16:27:41.894548+1100 QantasTest[13489:314159] Task <526F7B9B-ADC8-4D14-8EA6-DEAD629E7C5A>.<0> HTTP load failed, 0/0 bytes (error code: -1200 [3:-9802]) 2022-03-29 16:27:41.894666+1100 QantasTest[13489:314182] NSURLConnection finished with error - code -1200 The code I use is: print("URL is \(String(describing: self.thumbNailUrl))") DispatchQueue.global().async { [weak self] in if let data = try? Data(contentsOf: self!.thumbNailUrl!) {             if let image = UIImage(data: data) {                                 DispatchQueue.main.async {                                     self?.imageView.image = image                                 }                             }                         }               } Any suggestions? Cheers Richard
Posted
by KiddoLamo.
Last updated
.
Post not yet marked as solved
8 Replies
563 Views
I am trying to set up an HTTP proxy that can be used system-wide from an app. After some research, it looks like the CoreFoundation library's CFNetworkExecuteProxyAutoConfigurationScript() function can be used to configure the proxy. (1) Is it possible to set the HTTP proxy available system-wide with CFNetworkExecuteProxyAutoConfigurationScript()? (2) I tried the following source code but "EXC_BAD_ACCESS" occurs and the callback block is not called. Do you know what is the problem? (void)startNextRequest { Request *request = _requests.firstObject; if (request == nil) { return; } CFStreamClientContext context; memset(&context, 0, sizeof(CFStreamClientContext)); context.info = (__bridge void * _Null_unspecified)(self); CFRunLoopSourceRef rls = CFNetworkExecuteProxyAutoConfigurationScript( (__bridge CFStringRef _Nonnull)(_script), (__bridge CFURLRef _Nonnull)(request.targetURL), (__bridge void *)^(PACResolver *client, CFArrayRef proxies, CFErrorRef error) { [client resolveDidFinishWithProxies:proxies error:error]; }, &context); assert(_runLoopSource == nil); _runLoopSource = rls; CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode); } Environment: Xcode 13.1 iPad 8th gen. iOS 14.0.1
Posted Last updated
.
Post not yet marked as solved
1 Replies
312 Views
Hi all I am experiencing some odd behavior when I use CFNetworkCopyProxiesForURL. Namely, it works perfectly for unauthenticated http/https and auto configure (proxy.pac) files, but it seems to assume that credentialed proxies are not valid for the the given URL, returning a result of kCFProxyTypeNone whenever I attempt to use a credentialed proxy. If it instead use SCDynamicStoreCopyProxies to get the system proxies and use the first one found, it works correctly to proxy my connection to the destination, but I would rather use CFNetworkCopyProxiesForURL if possible as that would be more specific. (lldb) n Process 2789 stopped * thread #61, queue = 'com.apple.root.default-qos', stop reason = step over   frame #0: 0x00000002f858e868 myprocess.dylib`get_proxy_settings_for_url(uri=0x0000600000c40010) at my_proxy.mm:315:33    312   // We have to use a unique ptr type here because of the COPY in the function name, which tells us we take ownership    313   auto proxies = apple::cf_ptr<CFArrayRef>{ CFNetworkCopyProxiesForURL(target_uri_ref.get(),    314                                      system_proxies.get()) }; -> 315   if (CFArrayGetCount(proxies.get()) == 0 )    316   {    317     LOG_INFO("No proxy configuration found"_ts);    318     return std::nullopt; Target 0: (myprocess) stopped. (lldb) po proxies.get() <__NSArrayM 0x600000c16130>( {   kCFProxyTypeKey = kCFProxyTypeNone; } ) (lldb) po system_proxies.get() {   ExceptionsList =   (     "192.168.1.61"   );   HTTPEnable = 1;   HTTPPort = 3128;   HTTPProxy = "192.168.1.61";   HTTPUser = mike;   "__SCOPED__" =   {     en0 =     {       ExceptionsList =       (         "192.168.1.61"       );       HTTPEnable = 1;       HTTPPort = 3128;       HTTPProxy = "192.168.1.61";       HTTPUser = mike;     };   }; } (lldb) po target_uri_ref.get() https://mycompany.com/mac Thanks! Alex
Posted
by afschuld.
Last updated
.
Post not yet marked as solved
1 Replies
290 Views
When I try to use instruments most of the time I can't identify the threads. I'm assuming these are "internal" threads? One of the threads was causing the CPU to go up to 100% usage. I didn't change anything in the code, how do I identify what is causing these issues.
Posted Last updated
.
Post marked as solved
1 Replies
274 Views
Hi, I have an app on the AppStore, but a few times, I get reports from users that he gets -1003 "Could not find a server with the specified hostname" on a 4G network. I tested on my iphone app and the problem is normal. Knowing that -1003 doesn't happen to all users, maybe there is some setting on the phone that is causing this? Or is there a way to help the user to fix it (reboot or Wifi)? If anyone knows the problem please let me know, thanks.
Posted
by alvin313.
Last updated
.
Post not yet marked as solved
5 Replies
588 Views
My app crashed when launch. The crash report: OS Version: iPhone OS 15.4 (19E5209h) Release Type: Beta Report Version: 104 Exception Type: EXC_CRASH (SIGABRT) Exception Codes: 0x0000000000000000, 0x0000000000000000 Exception Note: EXC_CORPSE_NOTIFY Termination Reason: DYLD 4 Symbol missing Symbol not found: _$sSo25NSURLSessionWebSocketTaskC10FoundationE4sendyyAbCE7MessageOYaKF Referenced from: /private/var/containers/Bundle/Application/43FB5827-DE90-4FCF-A716-11A7FD5BE11E/Kingbox.app/Kingbox Expected in: /usr/lib/swift/libswiftFoundation.dylib (terminated at launch; ignore backtrace) Triggered by Thread: 0 Thread 0 Crashed: 0 dyld 0x00000001056506d0 __abort_with_payload + 8 1 dyld 0x00000001056562c8 abort_with_payload_wrapper_internal + 104 (terminate_with_reason.c:102) 2 dyld 0x00000001056562fc abort_with_payload + 16 (terminate_with_reason.c:124) 3 dyld 0x00000001056267e8 dyld4::halt(char const*) + 328 (DyldProcessConfig.cpp:2067) 4 dyld 0x0000000105623920 dyld4::prepare(dyld4::APIs&amp;, dyld3::MachOAnalyzer const*) + 3560 (dyldMain.cpp:0) 5 dyld 0x0000000105621c84 start + 488 (dyldMain.cpp:864) Demangle the symbol: _$sSo25NSURLSessionWebSocketTaskC10FoundationE4sendyyAbCE7MessageOYaKF (extension in Foundation):__C.NSURLSessionWebSocketTask.send((extension in Foundation):__C.NSURLSessionWebSocketTask.Message) async throws -&gt; ()
Posted
by orighost.
Last updated
.
Post not yet marked as solved
3 Replies
426 Views
We have been seeing a NSURLError cannot parse error with error code -1017 for 0.01% of all the requests fired from our native app. We double checked the request headers and cookies but found no difference from the API calls that succeeded for the same path. For most of these requests, we found (through our analytics tools) that 99% of the times, there was no response received from the server(response object is nil); trying to understand why would a no response cause a cannot parse error. We do not get much information from error received as to what really went wrong, did the request even reach the server or was killed or modified by the OS? Any help or further detail will be very helpful. Error in detail: Foundation.URLError(_nsError: Error Domain=NSURLErrorDomain Code=-1017 "cannot parse response" UserInfo={NSUnderlyingError=0x280eddc50 {Error Domain=kCFErrorDomainCFNetwork Code=-1017 "(null)" UserInfo={_kCFStreamErrorCodeKey=-1, _kCFStreamErrorDomainKey=4}}, NSErrorFailingURLStringKey=https://mydomain.com/path, NSErrorFailingURLKey=https://mydomain.com/path, _kCFStreamErrorDomainKey=4, _kCFStreamErrorCodeKey=-1, NSLocalizedDescription=cannot parse response})
Posted Last updated
.
Post not yet marked as solved
6 Replies
385 Views
Hello! The documentation on ATS refers to "apps and app extensions" as scope. https://developer.apple.com/documentation/security/preventing_insecure_network_connections Does this limit its availability to apps that are running in the user context? The question is: do we get ATS protection in case of a launchd job? Let's say there is a launchd job (running in uid 1 context). It initiates network requests using URLSession API. Does it get ATS by default? Is there a way to validate that? Is it correct to assume that high level network API such as URLSession use ATS by default? Thanks. Best regards, Arthur
Posted Last updated
.
Post not yet marked as solved
4 Replies
1k Views
According to the documentation https://developer.apple.com/documentation/foundation/nsurlrequest.cachepolicy if I'm using the NSURLRequestUseProtocolCachePolicy option and the response stale, system issues a HEAD request. But if there is no internet connection, this request could not be completed so NSURLRequest cannot determine whether the HEAD changed and decide should it return the cached response.Is there a way to force NSURLRequest to use the cached response if there is no connection and cache policy is NSURLRequestUseProtocolCachePolicy?
Posted
by cdcomdev.
Last updated
.
Post marked as solved
3 Replies
1.4k Views
As I am preparing for the latest iOS 15.4 rollout, I downloaded the latest Xcode 13.3 beta 2 update. To my surprise a previous standard REST call made in my app is now failing with the following network issue when running on an iPhone 13 Pro with iOS 15.4 (beta2). 2022-02-10 11:11:00.944 [Info] [main] [AlamofireNetworkService.swift:24] fetch(route:) &gt; post: https://site.serverdev.net:18100/Users?action=login 2022-02-10 11:11:01.087121-0500 MyApp[50029:13165667] [connection] nw_socket_handle_socket_event [C8.1:3] Socket SO_ERROR [54: Connection reset by peer] 2022-02-10 11:11:01.091555-0500 MyApp[50029:13165884] [boringssl] boringssl_metrics_log_metric_block_invoke(153) Failed to log metrics 2022-02-10 11:11:01.104522-0500 MyApp[50029:13165667] Connection 8: received failure notification 2022-02-10 11:11:01.104715-0500 MyApp[50029:13165667] Connection 8: received ECONNRESET with incomplete TLS handshake - generating errSSLClosedNoNotify 2022-02-10 11:11:01.105049-0500 MyApp[50029:13165667] Connection 8: failed to connect 3:-9816, reason -1 2022-02-10 11:11:01.105174-0500 MyApp[50029:13165667] Connection 8: encountered error(3:-9816) 2022-02-10 11:11:01.106574-0500 MyApp[50029:13165667] Task &lt;F53C7A17-7297-4566-9746-1D39807E8356&gt;.&lt;5&gt; HTTP load failed, 0/0 bytes (error code: -1200 [3:-9816]) 2022-02-10 11:11:01.118796-0500 MyApp[50029:13165920] Task &lt;F53C7A17-7297-4566-9746-1D39807E8356&gt;.&lt;5&gt; finished with error [-1200] Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made." UserInfo={NSErrorFailingURLStringKey=https://site.serverdev.net:18100/Users%3Faction=login, NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, _kCFStreamErrorDomainKey=3, _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask &lt;F53C7A17-7297-4566-9746-1D39807E8356&gt;.&lt;5&gt;, _NSURLErrorRelatedURLSessionTaskErrorKey=(   "LocalDataTask &lt;F53C7A17-7297-4566-9746-1D39807E8356&gt;.&lt;5&gt;" ), NSLocalizedDescription=An SSL error has occurred and a secure connection to the server cannot be made., NSErrorFailingURLKey=https://site.serverdev.net:18100/Users%3Faction=login, NSUnderlyingError=0x6000016e6850 {Error Domain=kCFErrorDomainCFNetwork Code=-1200 "(null)" UserInfo={_kCFStreamPropertySSLClientCertificateState=0, _kCFNetworkCFStreamSSLErrorOriginalValue=-9816, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9816, _NSURLErrorNWPathKey=satisfied (Path is satisfied), interface: utun3}}, _kCFStreamErrorCodeKey=-9816} I see there is an error related to the TLS handshake and following that a generic error saying "a secure connection to the server cannot be made". I ran the same call against the iPhone 13 Pro with iOS 15.0 on the same Xcode 13.3 beta2 version and the call succeeds as expected. This leaves me to believe the issue is tied to the iOS 15.4 beta layer. The release notes don't state any particular mention of SSL requirement changes and am wondering how else I can go about to investigate this issue. (The server I am communicating with enforces TLS 1.2)
Posted
by MattChan.
Last updated
.
Post marked as solved
5 Replies
593 Views
Hi, I'm working in a iOS app using the UIImagePickerController to get files and videos from the photo library and upload to Azure Blob storage. For images, everything is working fine, but for videos, it fails with the following error: Error Domain=NSPOSIXErrorDomain Code=1 "Operation not permitted" UserInfo={_kCFStreamErrorCodeKey=1, _kCFStreamErrorDomainKey=1} Basically, what I'm doing is: 1.to get the file URL from the UIImagePickerController:                 if mediaType == "public.movie" {                     let mediaURL = info[UIImagePickerController.InfoKey.mediaURL] as! NSURL                                          uploadFileAsync(fileURL: mediaURL.filePathURL)                 } the upload to Azure method:  func uploadFileAsync(fileURL: URL) { ... do { let isSecureAccess = fileURL.startAccessingSecurityScopedResource() defer{fileURL.stopAccessingSecurityScopedResource()} let resourceValues = try fileURL.resourceValues(forKeys: [.fileSizeKey]) // Gets the Mime Type let extUTI = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, fileURL.pathExtension as CFString, nil)?.takeUnretainedValue() let mimeType:String = extUTI != nil ? (UTTypeCopyPreferredTagWithClass(extUTI!, kUTTagClassMIMEType)?.takeUnretainedValue() as String?) ?? defaultMimeType : defaultMimeType let fileSize: Int = resourceValues.fileSize! blockBlob?.properties.length = NSNumber(value: fileSize) blockBlob?.properties.contentType = mimeType blockBlob?.uploadFromFile(with: fileURL) } The error is generating from the blockBlob?.uploadFromFile(with: fileURL) Any help is really appreciated.
Posted
by hrobles55.
Last updated
.
Post marked as solved
5 Replies
1.7k Views
Is there a recommended approach for detecting WebSocket connectivity issues? More specifically, does URLSessionWebSocketTask have a way to access errors within CFNetwork? My app maintains a WebSocket connection with a remote server, and I would like to notify the user that their connection has dropped when the phone loses network connectivity. I'm simulating a dropped network connection in my test environment by placing my phone in Airplane mode and deactivating WiFi. None of URLSessionWebSocketTask's delegates or callbacks pass back an error, and I only get the following log message: Connection 1: encountered error(1:53) I'm using a URLSessionWebSocketDelegate and the urlSession(session:, webSocketTask:, didCloseWith:) does not get triggered, neither does webSocketTask.receive(completionHandler:) I believe the log messages comes from CFNetwork since I can find the log within the Console app and the log references CFNetwork. I found that webSocketTask.sendPing(pongReceiveHandler:) does eventually discover that connectivity is lost, but after a really long time. As far as I know, sendPing should probably run in a background task that runs every 30 seconds or so, and the error isn't discovered until about another 30+ seconds when the ping request times out. So, it could take 1+ minute(s) before the user is notified of the issue. I don't really like this approach since it requires extra code, extra network requests, and a very delayed response. So, do errors within CFNetwork propagate to URLSessionWebSocketTask in any way? If not, I would really like if errors within CFNetwork propagated to webSocketTask.receive(completionHandler:) as a .warning URLSessionWebSocketTask.Message along with an error code. Ultimately, I would like to handle connection errors when they are encountered. I noticed in another forum post that Apple changed iOS WebSockets in a beta release, so I tried to update my software without any luck. I updating macOS to 10.15.6 Beta (19G60d), iOS to 13.6 (17G5059c), and XCode to Version 12.0 beta 2 (12A6163b). However, XCode couldn't connect to my phone, and webSocketTask.send(message:) had intermittent string encoding issues. System Details: macOS 10.15.5 (1 June 2020 update) iOS 13.5.1 (1 June 2020 update) XCode Version 11.5 (11E608c)
Posted Last updated
.
Post not yet marked as solved
14 Replies
6.7k Views
I read here that when using `URLSessionConfiguration.background(withIdentifier:)`, it shouldn't timeout and should try again 'till there is an available internet connection or 'till `timeoutIntervalForResource` reached out (which is set to 7 days), but in this case, I'm getting the timeout after less than 15 seconds and after that it doesn't seems to try again, also when there is an internet connection (e.g. turning off Network Link Conditioner).I haven't set anything to that time so I really don't know why this is happening, all I've done is to set `100% Loss` in Network Link Conditioner to check offline usage (which shouldn’t matter to URLSession since it using background configuration).In short:My goal is to start the session whenever there is or there isn't an internet connection and let it fetch as soon as it can, when there is an available internet connection.What happens right now is that the session is timed out and not performing the session also when there is an internet connection (e.g. turning off Network Link Conditioner).*It's important to note that when there is an available internet connection while the session is resumed, it does fetching successfully, so the issue is not with the server I'm sending the task to for sure.Here is my code:Defining session configuration:static let urlSessionConfiguration: URLSessionConfiguration = { let configuration = URLSessionConfiguration.background(withIdentifier: FilesManager.urlSessionIdentifier) configuration.sessionSendsLaunchEvents = false configuration.sharedContainerIdentifier = "myApp" return configuration }()Starting the session:let url = URL(string: "https://url.com/path")! var urlRequest = URLRequest(url: url) urlRequest.httpMethod = "POST" urlRequest.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type") urlRequest.httpBody = body URLSession(configuration: FilesManager.urlSessionConfiguration, delegate: self, delegateQueue: nil).dataTask(with: urlRequest).resume()Delegate:extension FilesManager: URLSessionDataDelegate, URLSessionDelegate { func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) { print("\(#function) \(error)") } }Print in console:urlSession(_:task:didCompleteWithError:) Optional(Error Domain=NSURLErrorDomain Code=-1001 "The request timed out." UserInfo={_kCFStreamErrorCodeKey=-2104, _NSURLErrorFailingURLSessionTaskErrorKey=BackgroundDataTask .&amp;lt;1&amp;gt;, _NSURLErrorRelatedURLSessionTaskErrorKey=( "BackgroundDataTask .&amp;lt;1&amp;gt;", "LocalDataTask .&amp;lt;1&amp;gt;" ), NSLocalizedDescription=The request timed out., _kCFStreamErrorDomainKey=4, NSErrorFailingURLStringKey=https://url.com/path, NSErrorFailingURLKey=https://url.com/path})If you know a better way to achieve my goal or you’re think there is something wrong in this code, please, let me know.Thanks,Ido.
Posted
by idomo.
Last updated
.
Post not yet marked as solved
1 Replies
251 Views
I was going through the documentation of dataTaskWithRequest:completionHandler: method of NSURLSession https://developer.apple.com/documentation/foundation/nsurlsession/1407613-datataskwithrequest The completion handler has the third param as NSError. But I could not find the domain name for these errors. Is it expected to be NSURLErrorDomain if the error is related to the network request? Or is it kCFErrorDomainCFNetwork. Is there any exhaustive list of error domain names that one can encounter for the above method? Thanks!
Posted
by VC2.
Last updated
.
Post marked as solved
2 Replies
247 Views
I am updating an old app, and my old code which uploads POST messages to a PHP script is not working. It seems like the POST array is simply empty. I've looked online and my code looks just like all the examples I see. just tried the answer given here, a simple example, and I get nothing in the POST array: https://stackoverflow.com/questions/28654603/php-post-script-works-with-other-sites-but-not-with-ios-nsurlconnection Here is the code from that example that does not work for me: @implementation Test : NSObject -(void)userLogin { NSString *user = @"test"; NSString *pass = @"pass"; NSString *post = [NSString stringWithFormat: @"user=%@&amp;pass=%@", user, pass]; NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES]; NSString *postLength = [NSString stringWithFormat:@"%lu", [postData length]]; NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init] ; [request setURL:[NSURL URLWithString:@"www.example.com/login.php"]]; [request setHTTPMethod:@"POST"]; [request setValue:postLength forHTTPHeaderField:@"Content-Length"]; [request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"]; [request setHTTPBody:postData]; NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self]; sleep(50); NSLog(@"%@", conn); } @end --------------- PHP file ----------------------- &lt;?php file_put_contents('/tmp/test', print_r($_POST, true)); ?&gt; On the other hand, if I go to a site like this and send a message with a simple 'user=me' and 'pass=whatever', then my php script does show that it received the variables. https://reqbin.com/post-online Furthermore, if I go to a site that will receive POSTs, like this one, then the example code above works fine. http://ptsv2.com Anyone know what could be the issue?
Posted
by bsabiston.
Last updated
.