Networking

RSS for tag

Explore the networking protocols and technologies used by the device to connect to Wi-Fi networks, Bluetooth devices, and cellular data services.

Networking Documentation

Posts under Networking subtopic

Post

Replies

Boosts

Views

Activity

macOS 15.6 network failure with VPNs?
I filed FB19631435 about this just now. Basically: starting with 15.6, we've had reports (internally and outternally) that after some period of time, networking fails so badly that it can't even acquire a DHCP lease, and the system needs to be rebooted to fix this. The systems in question all have at least 2 VPN applications installed; ours is a transparent proxy provider, and the affected system also had Crowdstrike's Falcon installed. A customer system reported seemingly identical failures on their systems; they don't have Crowdstrike, but they do have Cyberhaven's. Has anyone else seen somethng like this? Since it seems to involve three different networking extensions, I'm assuming it's due to an interaction between them, not a bug in any individual one. But what do I know? 😄
0
0
73
Aug ’25
How do I make a network call that is longer than 30 seconds?
I have a network call that can sometimes take longer than 30 seconds and user might sometimes background the app after waiting a bit (think like a image generation done on a server which takes a while). I want to make sure that I have exhausted all the options available to provide the best possible solution for the user (1) Use beginBackgroundTask. The downside to this is that I'm only given about 30 seconds or so, and if it takes longer, the call just get killed. (2) Use URLSessionConfiguration.background. The upside is that this can take as long as it needs but it seems to be delegated to the system, and you never know when it will run? What if the user stays in the foreground and now the user will not know when the call will even begin (determined by the OS) (3) Use BGProcessingTask. Again problem is that we cant control when the task is run (which in this case we want it to be immediately). So really none of the options really is ideal. Are there other options? What I would like ideally is The call should start immediately upon user request The call should go on indefinitely when the app stays in foreground The call should go on for an extended period (like 2 minutes) if the user puts the app in background If the call is completed in the background, have a way for the app to retrieve the result when the user brings the app back in the foreground
1
0
357
Oct ’24
Prioritizing QUIC streams?
When creating multiple QUIC streams (NWConnections) sharing one QUIC tunnel (using NWMultiplexGroup), is it possible to assign different priorities to the streams? And if yes, how? The only prioritization option I found so far is NWConnection.ContentContext.relativePriority, but I assume that is for prioritizing messages within a single NWConnection?
5
0
605
Oct ’24
How to detect the SIM card status?
Before iOS16, we can use https://developer.apple.com/documentation/coretelephony/ctcarrier But after iOS this is deprecated and has no replacement. There are some discussions on it, eg. https://developer.apple.com/forums/thread/714876 https://developer.apple.com/forums/thread/770400 Now I asked AI, then it provided this solution, to check the serviceCurrentRadioAccessTechnology, so it this ok to check the SIM card status? var hasSIMCard = false let info = CTTelephonyNetworkInfo() if let rat = info.serviceCurrentRadioAccessTechnology, rat.values.contains(where: { !$0.isEmpty }) { hasSIMCard = true. // has RAT } BTW, I can see a lot of changes in the Core Telephony framework. https://developer.apple.com/documentation/coretelephony 1.isSIMInserted https://developer.apple.com/documentation/coretelephony/ctsubscriber/issiminserted A Boolean property that indicates whether a SIM is present. iOS 18.0+ iPadOS 18.0+ This value property is true if the system finds a SIM matching the Info.plist carrier information (MCC / MNC / GID1 / GID2). Is this ok to check SIM insert status, this seems must preconfig some info in the info.plist. 2.iOS26 provide CTCellularPlanStatus https://developer.apple.com/documentation/coretelephony/ctcellularplanstatus Can I use this to check SIM status?
2
0
102
Jun ’25
CallKit and PushToTalk related changes in iOS 26
Starting in iOS 26, two notable changes have been made to CallKit, LiveCommunicationKit, and the PushToTalk framework: As a diagnostic aid, we're introducing new dialogs to warn apps of voip push related issue, for example when they fail to report a call or when when voip push delivery stops. The specific details of that behavior are still being determined and are likely to change over time, however, the critical point here is that these alerts are only intended to help developers debug and improve their app. Because of that, they're specifically tied to development and TestFlight signed builds, so the alert dialogs will not appear for customers running app store builds. The existing termination/crashes will still occur, but the new warning alerts will not appear. As PushToTalk developers have previously been warned, the last unrestricted PushKit entitlement ("com.apple.developer.pushkit.unrestricted-voip.ptt") has been disabled in the iOS 26 SDK. ALL apps that link against the iOS 26 SDK which receive a voip push through PushKit and which fail to report a call to CallKit will be now be terminated by the system, as the API contract has long specified. __ Kevin Elliott DTS Engineer, CoreOS/Hardware
0
0
383
Jun ’25
Securely transmit UIImage to app running on desktop website
Hello everyone, I'm trying to figure out how to transmit a UIImage (png or tiff) securely to an application running in my desktop browser (Mac or PC). The desktop application and iOS app would potentially be running on the same local network (iOS hotspot or something) or have no internet connection at all. I'm trying to securely send over an image that the running desktop app could ingest. I was thinking something like a local server securely accepting image data from an iPhone. Any suggestions ideas or where to look for more info would be greatly appreciated! Thank you for your help.
1
0
82
May ’25
CoreWLAN scanForNetworks does not expose SSIDs even when Location permission is authorized (Sequoia 15.1)
Hi, I've read a bunch of threads regarding the changes in Sonoma and later requiring Location permission for receiving SSIDs. However, as far as I can see, in Sequoia 15.1 SSIDs and BSSIDs are empty regardless. In particular, this makes it not possible to use associate(withName:) and associate(withSSID:) because the network object returned by scanForNetwork(withSSID: "...") has its .ssid and .bssid set to nil. Here is an example: First we have a wrapper to call the code after the location permission is authorized: import Foundation import CoreLocation class LocationDelegate: NSObject, CLLocationManagerDelegate { var onAuthorized: (() -> Void)? var onDenied: (() -> Void)? func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) { let authStatus = manager.authorizationStatus print("Location authorization status changed: \(authStatusToString(authStatus))") if authStatus == .authorizedAlways { onAuthorized?() } else if authStatus == .denied || authStatus == .restricted { onDenied?() } } } let locationManager = CLLocationManager() let locationDelegate = LocationDelegate() func authorizeLocation(onAuthorized: @escaping () -> Void, onDenied: @escaping () -> Void) { let authStatus = locationManager.authorizationStatus print("Location authorization status: \(authStatusToString(authStatus))") if authStatus == .notDetermined { print("Waiting for location authorization...") locationDelegate.onAuthorized = onAuthorized locationDelegate.onDenied = onDenied locationManager.delegate = locationDelegate locationManager.requestAlwaysAuthorization() } else if authStatus == .authorizedAlways { onAuthorized() } else if authStatus == .denied || authStatus == .restricted { onDenied() } RunLoop.main.run() } func authStatusToString(_ status: CLAuthorizationStatus) -> String { switch status { case .notDetermined: return "Not Determined" case .restricted: return "Restricted" case .denied: return "Denied" case .authorizedAlways: return "Always Authorized" case .authorizedWhenInUse: return "Authorized When In Use" @unknown default: return "Unknown" } } Then, a demo program itself: import Foundation import CoreWLAN import Network let client = CWWiFiClient.shared() guard let interface = client.interface() else { print("No wifi interface") exit(1) } authorizeLocation( onAuthorized: { do { print("Scanning for wifi networks...") let scanResults = try interface.scanForNetworks(withSSID: nil) let networks = scanResults.compactMap { network -> [String: Any]? in return [ "ssid": network.ssid ?? "unknown", "bssid": network.bssid ?? "unknown" ] } let jsonData = try JSONSerialization.data(withJSONObject: networks, options: .prettyPrinted) if let jsonString = String(data: jsonData, encoding: .utf8) { print(jsonString) } exit(0) } catch { print("Error: \(error)") exit(1) } }, onDenied: { print("Location access denied") exit(1) } ) When launched, the program asks for permission, and after that, is shown as enabled in Privacy & Security Settings panel. Here is the output where it can be seen that the scan is performed after location access was authorized, and regardless of that, all ssids are empty: Location authorization status: Not Determined Waiting for location authorization... Location authorization status changed: Always Authorized Scanning for wifi networks... [ { "ssid" : "unknown", "bssid" : "unknown" }, { "ssid" : "unknown", "bssid" : "unknown" }, .... further omitted Calling scanForNetworks() with explicitly specified network name does this as well, returns a CWNetwork object with .ssid / .bssid = nil.
5
0
724
Dec ’24
Network Relay errors out with "Privacy proxy failed with error 53"
I'm using NERelayManager to set Relay configuration which all works perfectly fine. I then do a curl with the included domain and while I see QUIC connection succeeds with relay server and H3 request goes to the server, the connection gets abruptly closed by the client with "Software caused connection abort". Console has this information: default 09:43:04.459517-0700 curl nw_flow_connected [C1.1.1 192.168.4.197:4433 in_progress socket-flow (satisfied (Path is satisfied), viable, interface: en0[802.11], ipv4, ipv6, dns, uses wifi)] Transport protocol connected (quic) default 09:43:04.459901-0700 curl [C1.1.1 192.168.4.197:4433 in_progress socket-flow (satisfied (Path is satisfied), viable, interface: en0[802.11], ipv4, ipv6, dns, uses wifi)] event: flow:finish_transport @0.131s default 09:43:04.460745-0700 curl nw_flow_connected [C1.1.1 192.168.4.197:4433 in_progress socket-flow (satisfied (Path is satisfied), viable, interface: en0[802.11], ipv4, ipv6, dns, uses wifi)] Joined protocol connected (http3) default 09:43:04.461049-0700 curl [C1.1.1 192.168.4.197:4433 in_progress socket-flow (satisfied (Path is satisfied), viable, interface: en0[802.11], ipv4, ipv6, dns, uses wifi)] event: flow:finish_transport @0.133s default 09:43:04.465115-0700 curl [C2 E47A3A0C-7275-4F6B-AEDF-59077ABAE34B 192.168.4.197:4433 quic, multipath service: 1, tls, definite, attribution: developer] cancel default 09:43:04.465238-0700 curl [C2 E47A3A0C-7275-4F6B-AEDF-59077ABAE34B 192.168.4.197:4433 quic, multipath service: 1, tls, definite, attribution: developer] cancelled [C2 FCB1CFD1-4BF9-4E37-810E-81265D141087 192.168.4.139:53898<->192.168.4.197:4433] Connected Path: satisfied (Path is satisfied), viable, interface: en0[802.11], ipv4, ipv6, dns, uses wifi Duration: 0.121s, QUIC @0.000s took 0.000s, TLS 1.3 took 0.111s bytes in/out: 2880/4322, packets in/out: 4/8, rtt: 0.074s, retransmitted bytes: 0, out-of-order bytes: 0 ecn packets sent/acked/marked/lost: 3/1/0/0 default 09:43:04.465975-0700 curl nw_flow_disconnected [C2 192.168.4.197:4433 cancelled multipath-socket-flow ((null))] Output protocol disconnected default 09:43:04.469189-0700 curl nw_endpoint_proxy_receive_report [C1.1 IPv4#124bdc4d:80 in_progress proxy (satisfied (Path is satisfied), interface: en0[802.11], ipv4, ipv6, dns, proxy, uses wifi)] Privacy proxy failed with error 53 ([C1.1.1] masque Proxy: http://192.168.4.197:4433) default 09:43:04.469289-0700 curl [C1.1.1 192.168.4.197:4433 failed socket-flow (satisfied (Path is satisfied), viable, interface: en0[802.11], ipv4, ipv6, dns, uses wifi)] event: flow:failed_connect @0.141s, error Software caused connection abort Relay server otherwise works fine with our QUIC MASQUE clients but not with built-in macOS MASQUE client. Anything I'm missing?
0
0
67
May ’25
CoreBluetooth and BLE AdvertisementData
Hi, We're receiving data via centralManager.centralManager.scanForPeripherals, with no options or filtering (for now), and in the func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) callback, we get advertisementData for each bluetooth device found. But, I know one of my BLE devices is sending an Eddystone TLM payload, which generally is received into the kCBAdvDataServiceData part of the advertisementData dictionary, but, it doesn't show up. What is happening however (when comparing to other devices that do show that payload), is I've noticed the "isConnectable" part is false, and others have it true. Technically we're not "connecting" as such as we're simply reading passive advertisement data, but does that have any bearing on how CoreBluetooth decides to build up it's AdvertisementData response? Example (with serviceData; and I know this has Eddystone TLM) ["kCBAdvDataLocalName": FSC-BP105N, "kCBAdvDataRxPrimaryPHY": 1, "kCBAdvDataServiceUUIDs": <__NSArrayM 0x300b71f80>( FEAA, FEF5 ) , "kCBAdvDataTimestamp": 773270526.26279, "kCBAdvDataServiceData": { FFF0 = {length = 11, bytes = 0x36021892dc0d3015aeb164}; FEAA = {length = 14, bytes = 0x20000be680000339ffa229bbce8a}; }, "kCBAdvDataRxSecondaryPHY": 0, "kCBAdvDataIsConnectable": 1] Vs This also has Eddystone TLM configured ["kCBAdvDataLocalName": 100FA9FD-7000-1000, "kCBAdvDataIsConnectable": 0, "kCBAdvDataRxPrimaryPHY": 1, "kCBAdvDataRxSecondaryPHY": 0, "kCBAdvDataTimestamp": 773270918.97273] Any insight would be great to understand if the presence of other flags drive the exposure of ServiceData or not...
0
0
79
Jul ’25
Launching Network System Extension from automated installation
We have network system extension which is fundamental part of our application and needs to be installed before the application can run. In many cases we need the installation to be automated, i.e. without logged-in user (with the help of MDM solution like JAMF). Is there a way to activate the extension fully automated without logged-in users? I tried to call 'open -W -a /Application/' from the package's post install script. But seems launch fails if no user is logged in.
1
0
364
Oct ’24
NWConnectionGroup w/QUIC Best Practices
Hello. Wanted to ask about the right way, or the intended way to leverage NWConnectionGroup for a QUIC based streaming solution. The use case is, we are making a request from the client in order to play a movie, and we want to send as much video frames as possible (and as fast as possible) from the streaming server, which also uses the Network framework. Our understanding is, NWConnectionGroup will open a QUIC tunnel between both parties so we can multiplex different streams to the client and we are already doing that. We see a throughput of approx. 20-35MB/s (client device is an iPad and server is an M2 macbook pro running a server app) and we would like to understand if we can improve these results way more. For example: 1.- Is it a good practice to create a second tunnel (NWConnectionGroup), or is not needed here?. We tried that, but the second one is also coming with id 0 on the metadata object, just as the first group we instantiated, not sure why this is the case. 2.- We are using a pool of several NWConnection (initialized with the group object) already instantiated, that way we send a video buffer in chunks as a stream on each connection. We use one connection for a buffer and when we need to send another buffer we use a different NWConnection pulled from the pool. We maybe just want a confirmation/validation of what we are doing, or to see if we are missing something on our implementation... Thanks in advance.
2
0
1.1k
Oct ’24
About the Relay payload
ios構成プロファイルの制限のallowCloudPrivateRelayのプライベートリレーの制御とRelayペイロードの機能は関係がありますか? それとも別々の機能でしょうか? ↓ s there a relationship between the private relay control in the iOS configuration profile restriction allowCloudPrivateRelay and the functionality of the Relay payload? Or are they separate features?
0
0
13
Apr ’25
Bonjour Connectivity Optimization
Hi folks, I'm building an iOS companion app to a local hosted server app (hosted on 0.0.0.0). The MacOS app locally connects to this server hosted, and I took the approach of advertising the server using a Daemon and BonjourwithTXT(for port) and then net service to resolve a local name. Unfortunately if there's not enough time given after the iPhone/iPad is plugged in (usb or ethernet), the app will cycle through attempts and disconnects many times before connecting and I'm trying to find a way to only connect when a viable en interface is available. I've run into a weird thing in which the en interface only becomes seen on the NWMonitor after multiple connection attempts have been made and failed. If I screen for en before connecting it simply never appears. Is there any way to handle this such that my app can intelligently wait for an en connection before trying to connect? Attaching my code although I have tried a few other setups but none has been perfect. func startMonitoringAndBrowse() { DebugLogger.shared.append("Starting Bonjour + Ethernet monitoring") if !browserStarted { let params = NWParameters.tcp params.includePeerToPeer = false params.requiredInterfaceType = .wiredEthernet browser = NWBrowser(for: .bonjourWithTXTRecord(type: "_mytcpapp._tcp", domain: nil), using: params) browser?.stateUpdateHandler = { state in if case .ready = state { DebugLogger.shared.append("Bonjour browser ready.") } } browser?.browseResultsChangedHandler = { results, _ in self.handleBrowseResults(results) } browser?.start(queue: .main) browserStarted = true } // Start monitoring for wired ethernet monitor = NWPathMonitor() monitor?.pathUpdateHandler = { path in let hasEthernet = path.availableInterfaces.contains { $0.type == .wiredEthernet } let ethernetInUse = path.usesInterfaceType(.wiredEthernet) DebugLogger.shared.append(""" NWPathMonitor: - Status: \(path.status) - Interfaces: \(path.availableInterfaces.map { "\($0.name)[\($0.type)]" }.joined(separator: ", ")) - Wired Ethernet: \(hasEthernet), In Use: \(ethernetInUse) """) self.tryToConnectIfReady() self.stopMonitoring() } monitor?.start(queue: monitorQueue) } // MARK: - Internal Logic private func handleBrowseResults(_ results: Set&lt;NWBrowser.Result&gt;) { guard !self.isResolving, !self.hasResolvedService else { return } for result in results { guard case let .bonjour(txtRecord) = result.metadata, let portString = txtRecord["actual_port"], let actualPort = Int(portString), case let .service(name, type, domain, _) = result.endpoint else { continue } DebugLogger.shared.append("Bonjour result — port: \(actualPort)") self.resolvedPort = actualPort self.isResolving = true self.resolveWithNetService(name: name, type: type, domain: domain) break } } private func resolveWithNetService(name: String, type: String, domain: String) { let netService = NetService(domain: domain, type: type, name: name) netService.delegate = self netService.includesPeerToPeer = false netService.resolve(withTimeout: 5.0) resolvingNetService = netService DebugLogger.shared.append("Resolving NetService: \(name).\(type)\(domain)") } private func tryToConnectIfReady() { guard hasResolvedService, let host = resolvedHost, let port = resolvedPort else { return } DebugLogger.shared.append("Attempting to connect: \(host):\(port)") discoveredIP = host discoveredPort = port connectionPublisher.send(.connecting(ip: host, port: port)) stopBrowsing() socketManager.connectToServer(ip: host, port: port) hasResolvedService = false } } // MARK: - NetServiceDelegate extension BonjourManager: NetServiceDelegate { func netServiceDidResolveAddress(_ sender: NetService) { guard let hostname = sender.hostName else { DebugLogger.shared.append("Resolved service with no hostname") return } DebugLogger.shared.append("Resolved NetService hostname: \(hostname)") resolvedHost = hostname isResolving = false hasResolvedService = true tryToConnectIfReady() } func netService(_ sender: NetService, didNotResolve errorDict: [String : NSNumber]) { DebugLogger.shared.append("NetService failed to resolve: \(errorDict)") } }
10
0
182
May ’25
Combining Bonjour and QUIC multiplex group using Network.framework
In my iOS app I am currently using Bonjour (via Network.framework) to have two local devices find each other and then establish a single bidirectional QUIC connection between them. I am now trying to transition from a single QUIC connection to a QUIC multiplex group (NWMultiplexGroup) with multiple QUIC streams sharing a single tunnel. However I am hitting an error when trying to establish the NWConnectionGroup tunnel to the endpoint discovered via Bonjour. I am using the same "_aircam._udp" Bonjour service name I used before (for the single connection) and am getting the following error: nw_group_descriptor_allows_endpoint Endpoint iPhone15Pro._aircam._udp.local. is of invalid type for multiplex group Does NWConnectionGroup not support connecting to Bonjour endpoints? Or do I need a different service name string? Or is there something else I could be doing wrong? If connecting to Bonjour endpoints isn't supported, I assume I'll have to work around this by first resolving the discovered endpoint using Quinn's code from this thread? And I guess I would then have to have two NWListeners, one just for Bonjour discovery and one listening on a port of my choice for the multiplex tunnel connection?
12
0
742
Nov ’24
Fixed Private Wi-Fi Address Changes after Update
I had noticed that my slaac address changed between one beta and the other, but wasn't sure. Now with the RC 15.4 RC (24E247) I made point of preserving the info before updating from the previous beta. What I noticed is that not only the slaac address changes, but also the my ether address, even though I have it on Fixed in the settings. Is it expected that the ether, and the slaac, not be rotated after a OS update?
4
0
48
Mar ’25
How to configure Hotspot2/Passpoint ?
I see that the iOS API includes the following NEHotspotConfigurationManager NEHotspotEAPSettings NEHotspotHS20Settings and NEHotspotTTLSInnerAuthenticationMSCHAPv2 But.. I need to access the cloud server from the app to obtain the Passpoint configuration, and then set it to the user's phone. Authentication requires EAP2 & MSCHAPv2, and of course, leaf certificates need to be loaded to the user. I cannot find a simple code example to do this... HELP! THKS..
1
0
190
Nov ’24