Hi all,
We've been exploring the capabilities of the Network.framework for peer-to-peer communication and have run into some behavior that we haven't been able to fully explain with the existing documentation.
In our tests, we’re working with 12 iOS devices, all disconnected from Wi-Fi to force communication over Apple Wireless Direct Link (AWDL). While using the Network.framework to create peer-to-peer connections, we observed that the number of connected peers never exceeded 8, despite all 12 devices being active and configured identically.
Some questions we’re hoping to get clarification or discussion on:
Is there a known upper limit to the number of peer-to-peer connections supported via AWDL?
Are there conditions under which the framework or system limits or throttles visible peers?
Does AWDL behavior vary by hardware model, iOS version, or backgrounding state of the app?
Is there any official documentation or guidance around peer discovery or connection limits when using NWBrowser and NWConnection in a peer-to-peer context?
We’d appreciate any insights from the Apple engineering team or other developers who have worked with larger peer groups using Network.framework in peer-to-peer mode.
Networking
RSS for tagExplore the networking protocols and technologies used by the device to connect to Wi-Fi networks, Bluetooth devices, and cellular data services.
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
Could anyone tell me how to detect status of Local Network for iOS 18+ systems ?
I've implemented a custom system extension VPN for macOS using Packet Tunnel Provider. The VPN is configured with on-demand, and a rule to always connect whenever there's traffic:
onDemandRules = [NEOnDemandRuleConnect()]
As expected, if the VPN isn't active, all traffic gets blocked until it is ready.
Not expected: In the following scenario, there is some 'traffic leak':
Use only WiFi (not wired cable)
Connect the VPN
Disable the WiFi and wait for the VPN to disconnect
Enable the WiFi
Some packets are routed outside the VPN, and aren't being blocked
Some moments after, all traffic will be blocked, and the VPN will start the 'connecting' process.
Is the above scenario a 'known' issue? Can it be a race condition in the OS, where some packets can be sent after the network is brought back before the VPN process starts? Is there any way to fix this problem?
P.S:
I'm not using flags such as 'capture all network'
We have developed a DNS filter based on NEDNSProxyProvider. It works great for a minute, then it stops responding. Our logs indicate that during the outage our extension gets DNS requests and formulates DNS responses that it hands back to the OS, but from outside of our code it is as though our extension is not responding.
In our App, we have a network extension with a NEAppPushProvider subclass running. We run the following steps
Setup a dual-band wireless router per the following:
Broadcasting 2.4 GHz and 5 GHz channels
Same SSID names for both channels
Connected to the production network to the router
DHCP assigning addresses in the 10.1.x.x network
Connect the mobile device to the 5 GHz network (if needed, turn off the 2.4 GHz network temporarily; once the device connects to the 5 GHz network, the 2.4 GHz network can be turned back on).
Create a NEAppPushManager in the App, using the SSID from the above mentioned network and set it to the matchSSIDs property. Call saveToPreferences() on the push manager to save.
A. We have UI that shows the extension has been started and it has connected to the server successfully.
Walk out of the range of the 5 GHz channel of the router, but stay within range of the 2.4ghz channel.
Wait for the mobile device to connect to the 2.4 GHz channel.
Expected:
The extension would reconnect to the 2.4ghz network.
Observed:
The extension does not reconnect. Checking the logs for the extension we see that the following was called in the push provider subclass.
stop(with:completionHandler:) > PID: 808 | 🗒️🛑 Stopped with reason 3: "noNetworkAvailable"
The expectation is that start() on the NEAppPushProvider subclass would be called. Is this an incorrect expectation?
How does the NEAppPushProvider handle same network SSID roaming among various band frequencies? I looked at the documentation and did not find any settings targeting 2.4 or 5 ghz networks. Please advise on what to do.
Getting cannot parse response on all downalod tasks. Example output
"BackgroundDownloadTask <E277D3D6-2FF0-4574-A617-1612ED779151>.<1>",
"LocalDownloadTask <E277D3D6-2FF0-4574-A617-1612ED779151>.<1>"
), NSLocalizedDescription=cannot parse response, _kCFStreamErrorDomainKey=4, NSErrorFailingURLStringKey=https://traffic.megaphone.fm/ESP7536701051.mp3?updated=1740573440, NSErrorFailingURLKey=https://traffic.megaphone.fm/ESP7536701051.mp3?updated=1740573440}
Can't seem to find a workaround that i can push for app to work with 18.4 beta. Can't believe that beta went to the public.
Hey, our app is host for system extension and since macOS 15.3 there is an error when user tries delete an app pop with missing permission appears
Is it intentional? Is it a bug? if not how in correct way should we handle removing of SE when app is being to removed?
Topic:
App & System Services
SubTopic:
Networking
Tags:
Network Extension
System Extensions
Endpoint Security
Hi everyone,
I’ve been working with the NEPacketTunnelProvider class and came across the cancelTunnelWithError() method. The documentation mentions its general purpose but doesn’t provide much clarity on how and when it should be called.
From what I’ve gathered in other forum posts, it seems that cancelTunnelWithError() should be called within my own implementation of the stopTunnel() method, but I’m not entirely sure if that’s the correct usage or whether there are specific scenarios where this applies.
Here are my specific questions:
Is it correct to always call cancelTunnelWithError() in my implementation of stopTunnel()?
Are there specific conditions or scenarios where cancelTunnelWithError() is the preferred way to terminate a tunnel session, rather than other termination methods?
What does the system do with the error that I pass to cancelTunnelWithError()? Does it have an impact on how the session termination is handled?
Are there best practices or common pitfalls to avoid when using cancelTunnelWithError()?
Any insights, examples, or guidance would be greatly appreciated!
Thanks in advance for your help!
Hi everyone,
I'm currently working on a project where I need to send multicast packets across all available network interfaces using Apple Network Framework's NWConnectionGroup. Specifically, the MacBook (device I am using for sending multicast requests, MacOS: 15.1) is connected to two networks: Wi-Fi (Network 1) and Ethernet (Network 2), and I need to send multicast requests over both interfaces.
I tried using the .requiredInterface property as suggested by Eskimo in this post, but I’m running into issues.
It seems like I can't create an NWInterface object because it doesn't have any initializers.
Here is the code which I wrote:
var multicast_group_descriptor : NWMulticastGroup
var multicast_endpoint : NWEndpoint
multicast_endpoint = NWEndpoint.hostPort(host: NWEndpoint.Host("234.0.0.1"), port: NWEndpoint.Port(rawValue: 49154)!)
var connection_group : NWConnectionGroup
var multicast_params : NWParameters
multicast_params = NWParameters.udp
var interface = NWInterface(NWInterface.InterfaceType.wiredEthernet)
I get following error:
'NWInterface' cannot be constructed because it has no accessible initializers
I also experimented with the .requiredInterfaceType property. Even when I set it to .wiredEthernet and then change it to .wifi, I am still unable to send requests over the Wi-Fi network.
Here is the code I wrote:
var multicast_params : NWParameters
multicast_params = NWParameters.udp
multicast_params.allowLocalEndpointReuse = true
multicast_params.requiredInterfaceType = .wiredEthernet
var ip = multicast_params.defaultProtocolStack.internetProtocol! as! NWProtocolIP.Options
ip.disableMulticastLoopback = true
connection_group = NWConnectionGroup(with: multicast_group_descriptor, using: multicast_params)
connection_group.stateUpdateHandler = { state in
print(state)
if state == .ready {
connection_group.send(content: "Hello from machine on 15".data(using: .utf8)) { error in
print("Send to mg1 completed on wired Ethernet with error \(error?.errorCode)")
var params = connection_group.parameters
params.requiredInterfaceType = .wifi
connection_group.send(content: "Hello from machine on 15 P2 on Wi-Fi".data(using: .utf8)) { error in
print("Send to mg1 completed on Wi-Fi with error \(error?.errorCode)")
}
}
}
}
Is this expected behavior when using NWConnectionGroup? Or is there a different approach I should take to ensure multicast requests are sent over both interfaces simultaneously?
Any insights or suggestions would be greatly appreciated!
Thanks in advance,
Harshal
Hello,
I'm developing a transparent proxy which only intercepts traffic coming from certain apps.
I'm having a problem when there are other transparent proxies active where the flow.metaData.sourceApplicationSigningIdentifier property is whichever provider intercepted the traffic before my provider did.
To verify this, I have implemented a small application that installs two transparent proxy profiles which handle the flows only coming from Safari.
Here's the is the bit of the code where the provider determines that:
open override func handleNewFlow(_ flow: NEAppProxyFlow) -> Bool {
guard let flow = flow as? NEAppProxyTCPFlow else { return false }
let sourceApp = flow.metaData.sourceAppSigningIdentifier
NSLog("[TransparentProxyProvider] Received flow from: \(sourceApp)")
guard sourceApp == "com.apple.Safari" else { return false }
// Create NWConnection and handle flow copying as needed
return true
}
As you can see from the following screenshots, when both profiles are active are the same time, the logs show that the second profile sees that the source application is the first profile:
From what I understand, that happens because the Transparent Proxy Provider creates a TCP connection and therefore, from the Operating System's perspective, is initiating a new separate flow which is what is then intercepted by the second provider.
My questions are:
Is this expected behavior?
Is there a way to find what the actual source application was?
How does the Operating System determine which profile receives the traffic first?
I've implemented a VPN app with Packet Tunnel Provider for MacOS and iOS.I have two questions regarding the Extension's sleep/wake functions:1. If the VPN configuration is set with disconnectOnSleep = false, and at the extension I'm sending keep-alives every X seconds, What would happen when the device enters sleep mode? Will it keep sending keep-alive (because the VPN is configured with disconnectOnSleep=false) ?2. If the VPN configuration is set with disconnectOnSleep = true, and also isOnDemandEnabled = true. When the device enters sleep mode, do I need to disconnect the VPN myself? Or the OS would take care of it? And if I should disconnect it myself, the on-demand won't try to turn it on again (because the on-demand) ?
iPhone 12 pro with iOS 26.0 (23A5276f)
App: https://developer.apple.com/documentation/wifiaware/building-peer-to-peer-apps
We aim to use Wi-Fi Aware to establish file transfer between Android and Apple devices.
Apple will act as the Publisher, and Android will act as the Subscriber.
According to the pairing process outlined in the Wi-Fi Aware protocol (Figure 49 in the Wi-Fi Aware 4.0 specification), the three PASN Authentication frames have been successfully exchanged. Subsequently, Android sends the encrypted Follow-up PMF to Apple, but the Apple log shows: Failed to parse event. Please refer to the attached complete log.
We request Apple to provide a solution.
apple Log-20250808a.txt
When i try to set the value ‘false’ for ‘usesClassicLoadingMode’ it is getting crashed.
The crash logs has been shared below
Ex:
let config = URLSessionConfiguration.default
if #available(iOS 18.4, *) {
config.usesClassicLoadingMode = false
}
Error log :
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFBoolean objectForKeyedSubscript:]: unrecognized selector sent to instance 0x1f655c390'
*** First throw call stack:
(0x188ae52ec 0x185f69a7c 0x188b4f67c 0x1889fcb84 0x1889fc4f0 0x191393bc8 0x1889ec8a0 0x1889ec6e4 0x191393ad0 0x191344dac 0x191344b58 0x107cfa064 0x107ce36d0 0x191343fcc 0x1891b3b18 0x1892dae58 0x189235c60 0x18921e270 0x18921d77c 0x18921a8ac 0x107ce0584 0x107cfa064 0x107ce891c 0x107ce95d8 0x107ceabcc 0x107cf5894 0x107cf4eb0 0x212f51660 0x212f4e9f8)
terminating due to uncaught exception of type NSException
Can you please provider the resolution steps
In my application, there is a Network Extension with the bundle ID com.***.agent.yyy.zzz.ne. There is a user upgraded their system to macOS Sequoia 15.3, they faced an issue where enabling this Network Extension failed. Even after uninstalling the application and the Network Extension, restarting the system, and reinstalling multiple times, the enabling process still failed.
it alert: Failed to enable the Network Extension.
When checking the status via "systemextension list", it always shows "activated waiting for user".
This shows the normal enabling process log:
This shows the log when the enabling fails upon clicking. Strangely enough, there is no activation operation log when it fails. What could be the problem?
Are there any known memory leaks in the Network framework? When using the start function on NWConnection I find a small leak appear every time (see attached image). I am using it for websockets
My App is a rather small menu-bar status-item app with 2 informational windows. It does NOT make use of ANY of the APIs mentioned here: https://developer.apple.com/forums/thread/663874 that are bound to need "Local Network" hence trigger TCC dialog.
Yet - on first run of the app, the dialog pops.
App is Obj-C, and the only APIs used are Notification-Center (for scheduling local notifications to the user), XPC connections and calls to other (our) apps for gathering that information, plus normal AppKit windowing (Controls, Text-fields, etc.) nothing else.
Obviously SOMETHING I do causes the thing - and I know for sure this app DOES NOT NEED access to the local network - only I do not know how to identify the specific API I need to avoid using (or change the way I'm using)
Are there any specific system logs to watch for?
Is there any official set of APIs that will trigger the dialog?
Provided that I cannot avoid this - could this permission be granted via MDM profile payload? Our product comes with
I'm coding resumable uploads using iOS 17's URLSession's uploadTask(withResumeData:. This function returns a non-Optional URLSessionUploadTask and does not throw. In cases where the system determines the resumeData is no longer valid, how do I detect that (so I can create a new URLSessionUploadTask from scratch)?
I'm doing this for background uploads, so it's all URLSessionDelegate apis, but what are the failure modes, and what Error types and Codes would we get specially?
Obviously, I expect the resume data is no longer usable or necessary when get a server success i.e. in the 2xx range. Does the resume data also become invalid for other server responses, like 4xx's? or 5xx's?.
I expect the resume data usually shouldn't become invalid when getting URLError's like .networkConnectionLost, since that's like half the point of having the feature in the first place, to resume after the a broken network connection. But I do expect that if the resumeData is invalid, then I should be able to reach the server and get a server response, so in that case what Code would we get?
I'm assuming the system is caching our upload file somewhere, and the resume data somehow makes a reference to it, so does that file get optimized away at some point in time when left untouched, and need us to start a fresh upload? We are also saving the file for potential future re-uploads, until we get certain assurances of completion from our backend, but I am just wondering on which logic branches I need to determine that the resumeData I thought I could use is no longer usable.
Our company has a VPN client that uses the Packet Tunnel Provider network extension and when 18 came out we noticed that we were no longer seeing DNS requests get sent to the VPNs TUN interface.
Do a packet trace, once the VPN becomes active we see requests to _dns.resolver.arpa and 12-courier.push.apple.com, which both get resolved as expected. Also our main app that controls the VPN service and does authentication has to resolve a hostname to get to an authentication service and we see those requests just fine as well. However, when we try to resolve by going to a webpage in Safari we see no DNS request corresponding to that.
What are we missing? At first I thought it was the RFC9461 stuff but from the packet traces I don't believe that is the case.
I have also tried other networking tools to send the DNS requests and that failed as well.
Hi,
I'm looking for feedback regarding SCNetworkReachability under macOS Sonoma.
It seems that since beta 3 the notifications behaviour changed.
In a LaunchAgent I'm using SCNetworkReachabilityCreateWithName + SCNetworkReachabilitySetCallback + SCNetworkReachabilityScheduleWithRunLoop and wait for callbacks looking at the kSCNetworkReachabilityFlagsReachable flag. This is running fine under macOS 12.x, 13.x and 14.0 for more than a year.
If I log all callback entries I observe unexpected notifications as if the looked host became unreachable for very small amount of time (ms). The host is flagged as unreachable then few ms later reachable again then unreachable again.
Fast switching is fine, I can accept that the service is unreachable even for 1s but the probleme is the latest status do not reflect actual reachability of the service.
This is in a corporate network with the complexity of using a proxy.pac.
Does anybody noticed something similar ?
I filled a Feedback FB13442134 in case it could be a regression of 14.2
最近服务器做了防重放功能,发现iOS有很多命中重放错误,因为我们的请求使用了UUID签名,排除了算法问题
经过排查发现iOS在请求过程中,如果网络发生变化,例如开启和断开vpn,或者开启和关闭WIFI,就会导致系统把正在进行的请求多次重放,这会导致从App的感知来看,请求和响应都只调用了一次,但是服务端却收到了多次
具体操作步骤:
1、开启抓包工具,例如wireshark
2、使用demo代码发送请求(先开启慢速网络,不然速度太快来不及操作):
3、不等请求完成,关闭wifi,这时会切换到蜂窝数据
4、等待请求完成后,通过日志可以看出请求的发送和响应都只进行了一次,但是抓包工具可以看到请求被发送了2次
demo如下:
// Create a URLSession with the default configuration
NSURLSession *defaultSession = [NSURLSession sharedSession];
// Setup the request to the URL
NSTimeInterval ms = [NSDate.date timeIntervalSinceReferenceDate] * 1000;
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"https://static.fusionbank.com/resource/20240930/8f54352194ac8beecbd5d3f5842b27bb.png?_t=%f",ms]];
NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url];
urlRequest.timeoutInterval = 20;
// Create dataTask
NSLog(@"--- request start");
dataTask = [defaultSession dataTaskWithRequest:urlRequest completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"--- request finish %@", [error localizedDescription]);
// Handle your response here
[self.loadingView stopAnimating];
if (data) {
UIImage* img = [UIImage imageWithData:data];
self.imageView.image = img;
}
});
}];
// Fire the request
[dataTask resume];
日志如下:
111.log
抓包工具显示请求发了2次:
请求和响应情况:
Topic:
App & System Services
SubTopic:
Networking