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

PolicyDenied on Simulator with Xcode 16 and Network Framework NWBrowser
I'm using Network framework for communication between devices. The first time I instantiate an NWBrowser, it will prompt the user with a popup that says: Allow <app name> to find devices on local networks? The problem is, once I upgraded from Xcode 15.4 to Xcode 16.4, the popup doesn't appear; it says in the debug window: nw_browser_fail_on_dns_error_locked [B1] nw_browser_dns_service_browse_callback failed: PolicyDenied(18,446,744,073,709,486,046) I do have the info.plist keys Privacy-Local Network Usage Description (NSLocalNetworkUsageDescription) and Bonjour Services (NSBonjourServices) so it's not that. Also, It still works on a real device. I think something changed with Xcode 16 that tightened the security on a simulator, or maybe disabled Network framework entirely. It's not the firewall on my computer because that is turned off. I'm using an M1 MacBook Pro.
1
0
133
Jun ’25
NSProcessInfo hostName holds the process for 30+ seconds
We have used ::gethostname to retrieve hostname in our tunnel provider extension and found it returns "localhost" on iOS 17+. So we changed to use [[NSProcessInfo processInfo] hostName]. However it often caused 30+ delay in the extension process on a few devices and always returns "localhost". The sysdiagnose shows a lot of DNS query logs as below: default mDNSResponder 2025-03-19 17:15:12.453769 +0800 75281: 0x11ad501 [R80937] DNSServiceCreateConnection START PID[79767](ACExtension) default mDNSResponder 2025-03-19 17:15:12.453892 +0800 75281: 0x11ad501 [R80938] DNSServiceQueryRecord START -- qname: <mask.hash: 'fNnSAdyuhKXqCny8+neXvw=='>, qtype: PTR, flags: 0x15000, interface index: -1, client pid: 79767 (ACExtension), name hash: 84de01e1 default mDNSResponder 2025-03-19 17:15:12.458395 +0800 75281: 0x11ad501 [R80939] DNSServiceQueryRecord START -- qname: <mask.hash: '2X6qN/YT0yh2psKwrGWokg=='>, qtype: PTR, flags: 0x15000, interface index: 0, client pid: 79767 (ACExtension), name hash: f25c923e default mDNSResponder 2025-03-19 17:15:12.462924 +0800 75281: 0x11ad501 [R80940] DNSServiceQueryRecord START -- qname: <mask.hash: 'peyRWEblLKbNvcOXPjSeMQ=='>, qtype: PTR, flags: 0x15000, interface index: 0, client pid: 79767 (ACExtension), name hash: 83323cc4
1
0
103
Mar ’25
MainActor in Network Extension
I am adopting Swift Concurrency in my network extension app to use Swift 6 protections. In the UI app I ended up with most of the app marked as MainActor, so that pieces of my app can keep seamless access to each other and at the same time have thread safe access. When it comes to my network extension, does it make sense to also mark most of the code as MainActor for the purposes of thread safety and seamless access of most classes to each other? I have doubts, because MainActor sounds like it should be a UI think, but network extension has no UI Of course any long or blocking operations would not be MainActor
1
0
460
Feb ’25
NEFilterManager saveToPreferences fails with "permission denied" on TestFlight build
I'm working on enabling a content filter in my iOS app using NEFilterManager and NEFilterProviderConfiguration. The setup works perfectly in debug builds when running via Xcode, but fails on TestFlight builds with the following error: **Failed to save filter settings: permission denied ** **Here is my current implementation: ** (void)startContentFilter { NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; [userDefaults synchronize]; [[NEFilterManager sharedManager] loadFromPreferencesWithCompletionHandler:^(NSError * _Nullable error) { dispatch_async(dispatch_get_main_queue(), ^{ if (error) { NSLog(@"Failed to load filter: %@", error.localizedDescription); [self showAlertWithTitle:@"Error" message:[NSString stringWithFormat:@"Failed to load content filter: %@", error.localizedDescription]]; return; } NEFilterProviderConfiguration *filterConfig = [[NEFilterProviderConfiguration alloc] init]; filterConfig.filterSockets = YES; filterConfig.filterBrowsers = YES; NEFilterManager *manager = [NEFilterManager sharedManager]; manager.providerConfiguration = filterConfig; manager.enabled = YES; [manager saveToPreferencesWithCompletionHandler:^(NSError * _Nullable error) { dispatch_async(dispatch_get_main_queue(), ^{ if (error) { NSLog(@"Failed to save filter settings: %@", error.localizedDescription); [self showAlertWithTitle:@"Error" message:[NSString stringWithFormat:@"Failed to save filter settings: %@", error.localizedDescription]]; } else { NSLog(@"Content filter enabled successfully!"); [self showAlertWithTitle:@"Success" message:@"Content filter enabled successfully!"]; } }); }]; }); }]; } **What I've tried: ** Ensured the com.apple.developer.networking.networkextension entitlement is set in both the app and system extension. The Network extension target includes content-filter-provider. Tested only on physical devices. App works in development build, but not from TestFlight. **My questions: ** Why does saveToPreferencesWithCompletionHandler fail with “permission denied” on TestFlight? Are there special entitlements required for using NEFilterManager in production/TestFlight builds? Is MDM (Mobile Device Management) required to deploy apps using content filters? Has anyone successfully implemented NEFilterProviderConfiguration in production, and if so, how?
1
0
217
Jun ’25
Clarification on content filter limitation
I am seeking clarification regarding the capabilities and limitations of deploying content filter profiles, such as web content filters, on unsupervised iOS devices through MDM solutions. Specifically, is per-app content filtering supported on unsupervised devices, or is it restricted to supervised devices only? If such restrictions exist, are there recognized workarounds? Additionally, I would like to understand if there are specific permissions or entitlements that enable apps to perform advanced filtering or monitoring functions on unsupervised devices. Any guidance or references to official documentation would be greatly appreciated.
1
0
65
Aug ’25
CentralManager won't connect to device for watchOS, but will for iOS?
Hi there, I'm having an issue hoping someone could help. We have an iOS app that uses CoreBluetooth to connect to peripherals using the central manager. The app works great - However, when using the same exact central manager for our watchos app, it will attempt to connect, but I never get a callback for either didConnect or didFailToConnect. The watch can connect successfully to other BLE devices, so the watch itself is capable of BLE connectivity. Here's a list of thing's I've tried (unsuccessfully): 1) Added every bluetooth-related entitlement to info.plist Privacy - Bluetooth Always Usage Description Privacy - Bluetooth Peripheral Usage Description Background Modes: App communicates using CoreBluetooth, App shares data using CoreBluetooth 2) Checked for Single-Connection Limits Verified that the iPhone was fully disconnected from the peripheral to ensure the device wasn’t limited to one connection. Attempted to connect on watchOS alone (with iPhone turned off) 3) Tried various options for CBCentralManager, scanForPeripherals, and connect I went through all the keys for various options and tried just setting them, they had no effect CBCentralManagerOptionShowPowerAlertKey, CBConnectPeripheralOptionEnableTransportBridgingKey Item 2 4) Tried .registerForConnectionEvents() 5) Set peripheral's delegate to the central in the didDiscover, stored it in a variable to ensure a strong reference to it I get no warnings either. The last time I ran into something like this, I found out the watchOS blocks TCP sockets. If I print out the CBPeripheralState a few seconds after trying to connect, it shows its stuck on CBPeripheralStateConnecting. Any advice or direction is greatly appreciated Below is the code and various print outs (day 2 into debugging, so it's not pretty) class WatchBLEManager:NSObject,CBCentralManagerDelegate, ObservableObject{ var centralManager: CBCentralManager? @Published var devices : [String:AtomBLEDevice] = [:] private var scanningDevice:AtomBLEDevice? var bleStatus:WatchBLEStatus = .blePoweredOff func startBLE() { centralManager = CBCentralManager(delegate: self, queue: nil,options: [CBCentralManagerOptionShowPowerAlertKey: true]) self.centralManager?.delegate = self } func startScan() { self.centralManager?.scanForPeripherals(withServices: [],options: [CBCentralManagerScanOptionAllowDuplicatesKey : true]) self.centralManager?.delegate = self } func stopScan() { print("stopping scan") self.centralManager?.stopScan() filterName = "" scanningDevice = nil } func centralManagerDidUpdateState(_ central: CBCentralManager) { switch (central.state) { //... other states omitted case .poweredOff: bleStatus = .blePoweredOff // bleStateDelegate?.didBlePoweredOff() for device in devices.values{ device.isConnected = false } print("BLE is Powered Off") case .poweredOn: bleStatus = .blePoweredOn // bleStateDelegate?.didBlePoweredOn() startScan() centralManager?.registerForConnectionEvents() print("Central supports extended scan and connect: ", CBCentralManager.supports(.extendedScanAndConnect)) print("powered on") @unknown default: print("BLE is Unknown") } } private let connectionQueue = DispatchQueue(label: "com.atom.connectionQueue") var connectingTo: String? = nil var peripheral: CBPeripheral? = nil func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) { guard let localName = advertisementData[CBAdvertisementDataLocalNameKey] as? String else { return} if localName.contains("Atom") { print("\nConnecting to \(localName)") print("\tAdvertising data: \(advertisementData)") print("\tANCS Authorized: ",peripheral.ancsAuthorized) print("\tServices", peripheral.services, "\n") self.peripheral = peripheral self.peripheral?.delegate = self // central.registerForConnectionEvents() // central.delegate = self peripheral.delegate = self DispatchQueue.main.async { // central.connect(peripheral) self.centralManager?.connect(peripheral, options: [ CBConnectPeripheralOptionEnableTransportBridgingKey: true]) } DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) { print("\tState", String(describing: peripheral.state)) print("Connected Peripherals: \(self.centralManager?.retrieveConnectedPeripherals(withServices: []))") } } } // Never gets called for watchos func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) { print("Connected to peripheral: \(peripheral.identifier)") if let atomDevice = getAtomBLEDevice(peripheral: peripheral) { //atomDevice.setPeripheral(perpipheral: <#T##CBPeripheral?#>) atomDevice.isConnected = true atomDevice.isConnecting = false //delegate?.didConnected(atomBLE: atomDevice!) atomDevice.startDiscoveringService() //atomDevice?.delegate?.didConnected(atomBLE: atomDevice!) print("Connected: \(peripheral.name)") } else { print("no matching atom device found for didConnect") print("connected peripheral :",peripheral.identifier.uuidString) } } func centralManager(_ central: CBCentralManager, connectionEventDidOccur event: CBConnectionEvent, for peripheral: CBPeripheral) { print("Connection event: \(event)") } func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: (any Error)?) { print("Failed to connect: \(error?.localizedDescription)") } func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) { let atomDevice = getAtomBLEDevice(peripheral: peripheral) atomDevice?.isConnected = false print("Peripheral disconnected:\(peripheral.name)") } func clearData() { filterName = "" for device in devices.values{ disconnect(atomBLEDevice: device) device.perpipheral?.delegate = nil } devices = [:] scanningDevice = nil // delegate = nil centralManager = nil } } extension WatchBLEManager: CBPeripheralDelegate { }```
1
0
316
Feb ’25
Iphone 16 is not connecting to WiFi7 AP with MLO Suiteb encryption
Issue summary: Iphone 16 is not connecting to WiFi7 AP with MLO Suiteb encryption. Furuno AP(EW750) is sending EAPOL M1 message, but Iphone16 is not responding with EAPOL M2 message, Hence Iphone16 is unable to connect to Qualcomm based AP with MLO suiteb encryption. Issue impact: All the Iphone16 users cannot connect to WiFi7 AP with MLO suiteb encryption globally. Predominantly, Iphone users tend to connect to more secured wifi networks using WPA3 suiteb encryption, hence many of the iphone users will experience the connectivity issue significantly. Topology: AP Hardware: Furuno WiFi7 AP(EW770) The Furuno WiFi7 AP uses Miami IPQ5332 with waikiki radio QCN9274 AP software: SPF12.2 CSU3 IPhone16 software: (18.3.1 or 18.5 ) Iphone16 wifi capabilities: 802.11 b/a/g/n/ac/ax/be Radius server details: Radius server: Laptop running with Ubuntu Radius package: 3.0.26dfsggit20220223.1.00ed0241fa-0ubuntu3.4 Version: 3.0.26 Steps: Power on the Wi-Fi 7 Access Point with the Miami chipset, and flash it with the SPF 12.2 CSU3 image. Enable both 5 GHz and 6 GHz radios on the AP. Enable MLO (Multi-Link Operation) in 6Ghz &amp; 5Ghz, set MLD address different from radio address and configure Suite-B (192-bit) encryption On the Linux laptop, set up the RADIUS server with EAP-TLS authentication method. Once the above steps are completed, take the iPhone 16 and follow the steps below to install the RADIUS client certificates on the device. On the sniffer laptop, switch the Wi-Fi adapter to monitor mode, configure the required channel, and begin packet capture. Check SSID is broadcasting, then connect the iPhone 16 to . Verify if the client (iPhone 16) connects to the SSID using WPA3-Enterprise, MLO, and Suite-B encryption by checking the wireless capture on both the AP and iPhone sides. Support needed from Apple team: We would request Apple team to analyse and enable the IPhone16 users to connect to advanced security WPA3 Suiteb by resolving the issue. Below is our analysis and observation for your reference. As per IEEE, MLD mac address can be set to the same or different from radio address, Iphone16 is not accepting EAPOL M1 message if source address(MLD) is different from radio address. IPhone16 is accepting EAPOL M1 if the source address(MLD) is set to the same as the radio address and responds with M2 message IPhone16 is not accepting EAPOL M1 if source address(MLD) set to different from radio address and fails to respond with M2 message
1
0
92
Aug ’25
Need Help with Relay Configurations in My App
Hi, I’m urgently seeking assistance with an issue in my app development. The app allows users to control which domains are routed through my relay servers (six server URLs). However, I’ve encountered a problem: When a single relay configuration (for a single server URL) contains more than 70 domains, only one configuration can be active at a time. If I manually activate another relay configuration (for another server URL), the previously activated one automatically deactivates. Is there a way to overcome this limitation? Also, is there a maximum amount of domains that can exist across the per-app relays? I’m referencing the Apple documentation here: https://developer.apple.com/documentation/networkextension/relays Any guidance or insights into resolving this issue would be greatly appreciated! Thank you in advance :)
1
0
290
Jan ’25
IOS VPN APP DEPLOYMENT
Hi everyone, I developed an Android version of a VPN app built with Flutter using OpenVPN, and it works perfectly on Android. However, when porting it to iOS, I’ve encountered an issue: the app connects successfully but then automatically disconnects when tested via TestFlight. We’ve already added all the necessary network extensions. Despite this, we decided to submit the app to the App Store. It’s been five days now, and the app is still 'Waiting for Review.' Could anyone share their experience deploying and working on an iOS version of a VPN app? I’d really appreciate your insights!
1
0
109
Mar ’25
OAuth login from NEPacketTunnelProvider
How can NEPacketTunnelProvider launch the companion application, or notify user to launch the application? I have built an iOS VPN that uses credentials stored in the keychain, and it works as expected. Now I'm trying to add OAuth login support. Everything works fine at first. I login from the companion application, store tokens in the keychain, then launch the VPN from either System Settings or the companion application. However, when the OAuth refresh tokens expire, or the OAuth IdP otherwise requires login, I can't perform the OAuth login from the NEPacketTunnelProvider. Login must happen from the companion application, which likely isn't running. I need the NEPacketTunnelProvider to either launch the companion application directly or to notify the user to do so. Searching and reading docs yields: You can't perform OAuth login from within the NEPacketTunnelProvider because it requires user interaction There is no way to guarantee that the companion application is running on iOS (otherwise one would use NEVPNStatusDidChange) You can't launch the companion application from NEPacketTunnelProvider using a custom URL because of security concerns You might be able to launch the companion application from a system extension... Some sources say you still can't guarantee that the system extension is loaded whenever the NEPacketTunnelProvider needs it anyway. Of course, any of these conclusions could be wrong. At this point I'm not sure where to begin. Is there another approach that could be initiated by the NEPacketTunnelProvider (push notifications, system notifications, smoke signals)? Any help would be appreciated. Thanks, Bill Welch
1
0
310
Feb ’25
Do watchOS apps support IP request communication within a local area network?
As a third-party application on Apple Watch, can it be located in the same LAN httpServer? Currently, when testing to initiate an http request in the LAN, the connection timeout is returned, code: -1001 self.customSession.request("http://10.15.48.191:9000/hello").response { response in switch response.result { case .success(let data): dlog("✅ 请求成功,收到数据:") if let html = String(data: data ?? Data(), encoding: .utf8) { dlog(html) } case .failure(let error): dlog("❌ 请求失败:\(error.localizedDescription)") } } 执行后报错 Task <B71BE820-FD0E-4880-A6DD-1F8F6EAF98B0>.<1> finished with error [-1001] Error Domain=NSURLErrorDomain Code=-1001 "请求超时。" UserInfo={_kCFStreamErrorCodeKey=-2102, _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask <B71BE820-FD0E-4880-A6DD-1F8F6EAF98B0>.<1>, _NSURLErrorRelatedURLSessionTaskErrorKey=( "LocalDataTask <B71BE820-FD0E-4880-A6DD-1F8F6EAF98B0>.<1>", "LocalDataPDTask <B71BE820-FD0E-4880-A6DD-1F8F6EAF98B0>.<1>", "LocalDataTask <B71BE820-FD0E-4880-A6DD-1F8F6EAF98B0>.<1>" ), NSLocalizedDescription=请求超时。, _kCFStreamErrorDomainKey=4, NSErrorFailingURLStringKey=http://10.15.48.191:9000/hello, NSErrorFailingURLKey=http://10.15.48.191:9000/hello}
1
0
96
May ’25
Clarification on IPv4 and Relay Configuration with matchDomains
Hi, I would like to confirm whether the matchDomains property in NERelayManager operates strictly at the Application Layer. Specifically, it seems that adding IPv4 addresses or IPv4 CIDR blocks to the matchDomains list does not work, as the relay manager appears unable to match them. For example, I tried adding the following IPv4 patterns to the matchDomains list: 11.22.33.44 11.22.. 11.22.* However, these IPv4 addresses or patterns are not routed through my Relay server. Additionally, I have observed that when using only the excludedDomains property, the desired IPv4 traffic is correctly routed to the relay server as expected. My question is: Can IPv4 addresses or IPv4 CIDR ranges work with matchDomains? If not, is there an alternative approach to enable IPv4 matching while matchDomains is active?
1
0
396
Jan ’25
NWPathMonitor Reports Unexpected satisfied→unsatisfied→satisfied Sequence After WiFi Re-enablement
I am developing an iOS application using NWPathMonitor for network connectivity monitoring. We discovered a reproducible issue where disabling and re-enabling WiFi triggers an unexpected network status sequence. ENVIRONMENT: iOS Version: 17.x Device: iPhone (various models tested) Network Framework: NWPathMonitor from iOS Network framework STEPS TO REPRODUCE: Device connected to WiFi normally Disable WiFi via Settings or Control Center Re-enable WiFi via Settings or Control Center EXPECTED BEHAVIOR: WiFi reconnects and NWPathMonitor reports stable satisfied status ACTUAL BEHAVIOR: T+0s: WiFi re-enables, NWPathMonitor reports path.status = .satisfied T+8s: NWPathMonitor unexpectedly reports path.status = .unsatisfied with unsatisfiedReason = .notAvailable T+9-10s: NWPathMonitor reports path.status = .satisfied again Connection becomes stable afterward NETWORK PATH TIMELINE: T+0s: satisfied (IPv4: true, DNS: false) T+140ms: satisfied (IPv4: true, DNS: true) T+8.0s: unsatisfied (reason: notAvailable, no interfaces available) T+10.0s: satisfied (IPv4: true, DNS: true) KEY OBSERVATIONS: Timing consistency: unsatisfied event always occurs ~8 seconds after reconnection resolution: "Reset Network Settings" eliminates this behavior TECHNICAL QUESTIONS: What causes the 8-second delayed unsatisfied status after WiFi re-enablement? Is this expected behavior that applications should handle? Why does reset network setting in iPhone fix this issue?
1
0
97
Jul ’25
Real-Time WatchConnectivity Sync Not Working Between iPhone and Apple Watch
Hi everyone, I'm building a health-focused iOS and watchOS app that uses WatchConnectivity to sync real-time heart rate and core body temperature data from iPhone to Apple Watch. While the HealthKit integration works correctly on the iPhone side, I'm facing persistent issues with WatchConnectivity — the data either doesn't arrive on the Watch, or session(_:didReceiveMessage:) never gets triggered. Here's the setup: On iPhone: Using WCSession.default.sendMessage(_:replyHandler:errorHandler:) to send real-time values every few seconds. On Apple Watch: Implemented WCSessionDelegate, and session(_:didReceiveMessage:) is supposed to update the UI. Both apps have WCSession.isSupported() checks, activate the session, and assign delegates correctly. The session state shows isPaired = true and isWatchAppInstalled = true. Bluetooth and Wi-Fi are on, both devices are unlocked and nearby. Despite all this, the Watch never receives messages in real-time. Sometimes, data comes through in bulk much later or not at all. I've double-checked Info.plist configurations and made sure background modes include "Uses Bluetooth LE accessories" and "Background fetch" where appropriate. I would really appreciate guidance on: Best practices for reliable, low-latency message delivery with WatchConnectivity. Debugging steps or sample code to validate message transmission and reception. Any pitfalls related to UI updates from the delegate method. Happy to share further details. Thanks in advance!
1
0
134
Jun ’25
stop content filter causing smb shared folder connection interruption
hi all. I’m working on a content filter system extension on MacOS. I try to disable the filtering in system settings, and it will cause smb shared folder connection interrupted. what I do in stopFilterWithReason:completionHandler: is waiting for the connection that is being filtered be allowed, then invoked the completionHandler. did I do something wrong here? is there a way to avoid the connection interruption?
1
0
431
Jan ’25