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
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
Hi! My project has the Local Push Connectivity entitlement for a feature we have requiring us to send low-latency critical notifications over a local, private Wi-Fi network.
We have our NEAppPushProvider creating a SSE connection using the Network framework with our hardware running a server. The server sends a keep-alive message every second. On an iPhone 16 with iOS 18+, the connection is reliable and remains stable for hours, regardless of whether the iOS app is in the foreground, background, or killed.
One of our QA engineers has been testing on an iPhone 13 running iOS 16, and has notice shortly after locking the phone, specifically when not connected to power the device seems to turn off the Wi-Fi radio. So when the server sends a notification, it is not received. About 30s later, it seems to be back on. This happens on regular intervals.
When looking at our log data, the provider does seem to be getting stopped, then restarted shortly after. The reason code is NEProviderStopReasonNoNetworkAvailable, which further validates that the network is getting dropped by the device in regular intervals.
My questions are:
Were there possibly silent changes to the framework between iOS versions that could be the reason we're seeing inconsistent behavior?
Is there a connection type we could use, instead of SSE, that would prevent the device from disconnecting and reconnecting to the Wi-Fi network?
Is there an alternative approach to allow us to maintain a persistent network connection with the extension or app?
Topic:
App & System Services
SubTopic:
Networking
Tags:
Extensions
Network
User Notifications
Network Extension
I've been wondering what is the memory limit for network extensions. Specifically, I'm using the NEPacketTunnelProvider extension point.The various posts on this forum mention 5 MB and 6 MB for 32-bit and 64-bit respectively. However I find that (at least on iOS 10) the upper limit seems to be 15 MB. Is this the new memory limit for extensions?
Hi,
I've encountered a strange behavior in the DNS Proxy Provider extension. Our app implements both DNS Proxy Provider and Content Filter Providers extensions, configured via MDM.
When the app is uninstalled, the behavior of the providers differs:
For Content Filter Providers (both Filter Control and Filter Data Providers), the providers stop as expected with the stop reason:
/** @const NEProviderStopReasonProviderDisabled The provider was disabled. */
case providerDisabled = 5
However, for the DNS Proxy Provider, the provider remains in the "Running" state, even though there is no app available to match the provider's bundle ID in the uploaded configuration profile.
When the app is reinstalled:
The Content Filter Providers start as expected.
The DNS Proxy Provider stops with the stop reason:
/** @const NEProviderStopReasonAppUpdate The NEProvider is being updated */
@available(iOS 13.0, *)
case appUpdate = 16
At this point, the DNS Proxy Provider remains in an 'Invalid' state. Reinstalling the app a second time seems to resolve the issue, with both the DNS Proxy Provider and Content Filter Providers starting as expected.
This issue seems to occur only if some time has passed after the DNS Proxy Provider entered the 'Running' state. It appears as though the system retains a stale configuration for the DNS Proxy Provider, even after the app has been removed.
Steps to reproduce:
Install the app and configure both DNS Proxy Provider and Content Filter Providers using MDM.
Uninstall the app.
Content Filter Providers are stopped as expected (NEProviderStopReason.providerDisabled = 5).
DNS Proxy Provider remains in the 'Running' state.
Reinstall the app.
Content Filter Providers start as expected.
DNS Proxy Provider stops with NEProviderStopReason.appUpdate (16) and remains 'Invalid'.
Reinstall the app again.
DNS Proxy Provider now starts as expected.
This behavior raises concerns about how the system manages the lifecycle of DNS Proxy Provider, because DNS Proxy Provider is matched with provider bundle id in .mobileconfig file.
Has anyone else experienced this issue? Any suggestions on how to address or debug this behavior would be highly appreciated.
Thank you!
1) Blocked page UX
When a URL is blocked, the browser typically shows a generic error like “"Safari cannot open the page because it couldn’t load any data,” with no indication that the page was blocked by a policy.
Is there any plan to add an API that allows developers to present a custom “blocked” page or remediation action, similar to NEFilterControlProvider’s remediationMap?
Even a minimal hook (custom HTML, deep link, or support URL) would make the experience clearer for users.
2) Cross‑app link‑opening behavior
With a block rule in place, direct navigation in Safari is blocked as expected. However, tapping the same URL in a messaging app (e.g., WhatsApp) opens Safari - and the page loads, not blocked.
Repro steps:
Configure a URL Filter extension that blocks https://example.com.
Case A: Open a browser and type the URL in the address bar → blocked (expected).
Case B: Tap the same URL in WhatsApp (or another messenger) → a browser opens and the page loads (unexpected).
iOS version - 26.0
I haven’t been able to get this to work at any level! I’m running into multiple issues, any light shed on any of these would be nice:
I can’t implement a bloom filter that produces the same output as can be found in the SimpleURLFilter sample project, after following the textual description of it that’s available in the documentation. No clue what my implementation is doing wrong, and because of the nature of hashing, there is no way to know. Specifically:
The web is full of implementations of FNV-1a and MurmurHash3, and they all produce different hashes for the same input. Can we get the proper hashes for some sample strings, so we know which is the “correct” one?
Similarly, different implementations use different encodings for the strings to hash. Which should we use here?
The formulas for numberOfBits and numberOfHashes give Doubles and assign them to Ints. It seems we should do this conversing by rounding them, is this correct?
Can we get a sample correct value for the combined hash, so we can verify our implementations against it?
Or ignoring all of the above, can we have the actual code instead of a textual description of it? 😓
I managed to get Settings to register my first attempt at this extension in beta 1. Now, in beta 2, any other project (including the sample code) will redirect to Settings, show the Allow/Deny message box, I tap Allow, and then nothing happens. This must be a bug, right?
Whenever I try to enable the only extension that Settings accepted (by setting its isEnabled to true), its status goes to .stopped and the error is, of course, .unknown. How do I debug this?
While the extension is .stopped, ALL URL LOADS are blocked on the device. Is this to be expected? (shouldFailClosed is set to false)
Is there any way to manually reload the bloom filter? My app ships blocklist updates with background push, so it would be wasteful to fetch the filter at a fixed interval. If so, can we opt out of the periodic fetch altogether?
I initially believed the API to be near useless because I didn’t know of its “fuzzy matching” capabilities, which I’ve discovered by accident in a forum post. It’d be nice if those were documented somewhere!
Thanks!!
I've recently updated one of our CI mac mini's to Sequoia in preparation for the transition to Tahoe later this year. Most things seemed to work just fine, however I see this dialog whenever the UI Tests try to run.
This application BoostBrowerUITest-Runner is auto-generated by Xcode to launch your application and then run your UI Tests. We do not have any control over it, which is why this is most surprising.
I've checked the codesigning identity with codesign -d -vvvv
as well as looked at it's Info.plist and indeed the usage descriptions for everything are present (again, this is autogenerated, so I'm not surprised, but just wanted to confirm the string from the dialog was coming from this app)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>BuildMachineOSBuild</key>
<string>22A380021</string>
<key>CFBundleAllowMixedLocalizations</key>
<true/>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>BoostBrowserUITests-Runner</string>
<key>CFBundleIdentifier</key>
<string>company.thebrowser.Browser2UITests.xctrunner</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>BoostBrowserUITests-Runner</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleSupportedPlatforms</key>
<array>
<string>MacOSX</string>
</array>
<key>CFBundleVersion</key>
<string>1</string>
<key>DTCompiler</key>
<string>com.apple.compilers.llvm.clang.1_0</string>
<key>DTPlatformBuild</key>
<string>24A324</string>
<key>DTPlatformName</key>
<string>macosx</string>
<key>DTPlatformVersion</key>
<string>15.0</string>
<key>DTSDKBuild</key>
<string>24A324</string>
<key>DTSDKName</key>
<string>macosx15.0.internal</string>
<key>DTXcode</key>
<string>1620</string>
<key>DTXcodeBuild</key>
<string>16C5031c</string>
<key>LSBackgroundOnly</key>
<true/>
<key>LSMinimumSystemVersion</key>
<string>13.0</string>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
<key>NSAppleEventsUsageDescription</key>
<string>Access is necessary for automated testing.</string>
<key>NSBluetoothAlwaysUsageDescription</key>
<string>Access is necessary for automated testing.</string>
<key>NSCalendarsUsageDescription</key>
<string>Access is necessary for automated testing.</string>
<key>NSCameraUsageDescription</key>
<string>Access is necessary for automated testing.</string>
<key>NSContactsUsageDescription</key>
<string>Access is necessary for automated testing.</string>
<key>NSDesktopFolderUsageDescription</key>
<string>Access is necessary for automated testing.</string>
<key>NSDocumentsFolderUsageDescription</key>
<string>Access is necessary for automated testing.</string>
<key>NSDownloadsFolderUsageDescription</key>
<string>Access is necessary for automated testing.</string>
<key>NSFileProviderDomainUsageDescription</key>
<string>Access is necessary for automated testing.</string>
<key>NSFileProviderPresenceUsageDescription</key>
<string>Access is necessary for automated testing.</string>
<key>NSLocalNetworkUsageDescription</key>
<string>Access is necessary for automated testing.</string>
<key>NSLocationUsageDescription</key>
<string>Access is necessary for automated testing.</string>
<key>NSMicrophoneUsageDescription</key>
<string>Access is necessary for automated testing.</string>
<key>NSMotionUsageDescription</key>
<string>Access is necessary for automated testing.</string>
<key>NSNetworkVolumesUsageDescription</key>
<string>Access is necessary for automated testing.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>Access is necessary for automated testing.</string>
<key>NSRemindersUsageDescription</key>
<string>Access is necessary for automated testing.</string>
<key>NSRemovableVolumesUsageDescription</key>
<string>Access is necessary for automated testing.</string>
<key>NSSpeechRecognitionUsageDescription</key>
<string>Access is necessary for automated testing.</string>
<key>NSSystemAdministrationUsageDescription</key>
<string>Access is necessary for automated testing.</string>
<key>NSSystemExtensionUsageDescription</key>
<string>Access is necessary for automated testing.</string>
<key>OSBundleUsageDescription</key>
<string>Access is necessary for automated testing.</string>
</dict>
</plist>
Additionally, spctl --assess --type execute BoostBrowserUITests-Runner.app return an exit code of 0 so I assume that means it can launch just fine, and applications are allowed to be run from "anywhere" in System Settings.
I've found the XCUIProtectedResource.localNetwork value, but it seems to only be accessible on iOS for some reason (FB17829325).
I'm trying to figure out why this is happening on this machine so I can either fix our code or fix the machine. I have an Apple script that will allow it, but it's fiddly and I'd prefer to fix this the correct way either with the machine or with fixing our testing code.
send a request and it returns with timeout
Integration Team are Using Fortigate as a firewall and NGINX for some reasons
so we use VPN TO Access , requests always succeed but at once it failed with timeout in randomize request not specific one
we are using URLSession as a network layer
when I retry the same failed request again, it success
the request cannot connect apigee
Sec Team concern {
app session hits the security gateway with lots of SYN step to try to initiate a new session and doesn’t wait for (SYN-ACK / ACK) steps to happen to make sure the connection initiated correctly and gateway consider it flooding attack
}
Topic:
App & System Services
SubTopic:
Networking
Hi,I am trying to create an NAT64 Network with Sharing options to test my Apps.I did follow the guide provided here https://forums.developer.apple.com/thread/14213But even with the option key pressed the "Create NAT64 Network" check box is still missing.I am using a OS X 10.11Any ideas?!
I'm developing a per-app VPN iOS app with Wireguard. For that, I created a configuration file with payload type "com.apple.vpn.managed.applayer". Using the MDM server I installed some apps which need to use the VPN connection. But when I open these apps, I could see the VPN getting enabled in the device. The VPN icon appears on the notification bar but no internet connection. The VPN and internet is working correctly if I change the payload type to "com.apple.vpn.managed" in configuration file.
HI,
I am currently prototyping an app that compares transport protocol performances using a peer to peer connection. I have already setup TCP and UDP connections and am sending data between the clients, it works like I want it to.
Next I was trying to setup a connection using QUIC, but the NWConnection.State stays in the preparing state and I couldn't find a way to get more information from the framework or the instances about why it was not fully connecting. After searching the internet and stumbling across the forum I noticed that the missing encryption might be the issue, so I created a local root certificate*. Then I used the SecPKCS12Import function to read/extract the SecIdentity instance of the p12 file (cert + private key) stored in my bundle** and set it as a local identity with the sec_protocol_options_set_local_identity function***.
//function that creates/returns different NWParameteres
//...
let quicOptions = NWProtocolQUIC.Options()
quicOptions.alpn = ["test"]
if let identityPath = Bundle.main.path(forResource: "QUICConnect", ofType: "p12"),
let identityData = try? Data(contentsOf: URL(fileURLWithPath: identityPath)) {
if let identity = loadIdentityFromPKCS12(p12Path: identityPath, password: "insecure") { //****
sec_protocol_options_set_local_identity(quicOptions.securityProtocolOptions, sec_identity_create(identity)!)
}
}
let parameters = NWParameters(quic: quicOptions)
parameters.includePeerToPeer = true
return parameter
The documentation comments had me thinking that setting a local identity could be enough, since it consists of the private key for the "server" and the cert for the "client".
Set the local identity to be used for this protocol instance.
Unfortunately at this stage the QUIC Connection is still stuck in preparing state and since I don't know how to extract more information from the networking connection instances/framework, I am stuck.
I have seen the following other functions in Quinns answer and am confident that I could somehow figure it out with some more time put into it, but not really understanding why or how I could do it better in the future. So I am also wondering how I could have found info about this more efficiently and tackled this more strategically without needing to browse through so many forums.
sec_protocol_options_set_verify_block
sec_protocol_options_set_challenge_block
I would really appreciate any help, many thanks.
BR Matthias!
TLDR:
I want to establish a peer to peer QUIC Connection but the state is stuck in preparing. Secondary question is how I could approach a similar topic more efficiently next time, instead of browsing many forums.
* I had to create it with the openssl CLI since the keychain app created a cert, that when using the openssl CLI to get the info would throw an error unless used with the -legacy flag. The root cert, created form the keychain app also wasn't able to be imported by the SecPKCS12Import function. No clue why but it worked with a cert created from the openssl CLI. There's a chance that I messed up something else here, but these were my experiences. Info: Since QUIC is limited to TLS v1.3 I can't use PSK, afaik. Therefore the TicTacToe doesn't help me anymore.
** I know this is highly insecure, I am just using it for prototyping.
*** Forum users Info: One needs to use the sec_identity_create function to convert the SecIdentity instance to the expected parameter type.
****
func loadIdentityFromPKCS12(p12Path: String, password: String) -> SecIdentity? {
guard let p12Data = try? Data(contentsOf: URL(fileURLWithPath: p12Path)) else {
print("didnt find p12 file at path")
return nil
}
let options: NSDictionary = [kSecImportExportPassphrase as String: password, kSecImportToMemoryOnly as String: kCFBooleanTrue!]
var items: CFArray?
let status = SecPKCS12Import(p12Data as CFData, options, &items)
if status == 0, let dict = (items as? [[String: Any]])?.first {
if let identity = dict[kSecImportItemIdentity as String] {
return identity as! SecIdentity
} else {
return nil
}
} else {
return nil
}
}
PS: For TCP and UDP I am using bonjour to discover the peer and connect to the advertised ports. AFAIK I can't just use _testproto._quic to advertise a QUIC service like with tcp and udp. Therefore I am using the local domain name (it's just for prototyping and always the same device) and a hard coded port number to create the peer connection. When using a wrong name the DNS threw an error telling it could not find a peer, so the lookup itself is working I guess. The lookup should come from the cache since I already looked up when connecting to the same peer via Bonjour.
//Server
//....
listener = try NWListener(
using: transportProtocol.parameters,
on: Config.quicPort
)
//...
listener.newConnectionHandler = { [weak self] connection in
self?.connection?.cancel()
self?.connection = nil
self?.connection = C(connection) //here C is a generic that conforms to a custom connection interface, nothing to worry about :)
self?.connectionStatus.value = "Connection established"
}
listener.stateUpdateHandler = { [weak self] state in
self?.connectionStatus.value = "\(state)"
}
listener.start(queue: .global())
//Client
//...
nwConnection = NWConnection(host: "iPad.local.", port: Config.quicPort, using: transportProtocol.parameters)
//...
I’m working with the NEHotspotHelper API in my iOS app, and I noticed the following log message in Console:
"(BUNDLE ID ) is using NEHotspotHelper API and it's unresponsive to API's evaluate command. The API gives 45 seconds to 3rd party apps to respond, and then it launches WebSheet to allow user to interact with the portal."
I have two different apps that both register a NEHotspotHelper handler:
App A checks for .evaluate and calls createResponse(.unsupportedNetwork) if we don’t manage that particular network.
App B registers for hotspot events but does not handle .evaluate at all.
In App A, whenever I see that “unresponsive” or “45 seconds” log, the system eventually launches the standard captive portal WebSheet. In App B, I never see those logs.
I have a few questions:
Are these “unresponsive” logs indeed triggered by the .evaluate command specifically?
In other words, do we only see that 45-second timeout and the subsequent WebSheet message if our app is registered to handle Evaluate but doesn’t respond quickly (or responds with .unsupportedNetwork)?
Is it best practice (or required) to always respond to .evaluate—for example, sending .unsupportedNetwork if we don’t plan on managing the user’s login or captive portal? Does ignoring .evaluate lead to other unexpected behavior or logs?
Should we still explicitly respond to Evaluate with .unsupportedNetwork? Or is it okay to skip Evaluate handling entirely on every app or invocation?
I’d love to confirm whether .evaluate handling is the direct cause of these logs, and how best to avoid the “unresponsive”/“45 seconds” fallback if our app isn’t intended to manage the portal.
Thanks in advance for any insights!
Topic:
App & System Services
SubTopic:
Networking
I'm simply trying to use a proxy to route a http request in Swift. I've tried using a URLSession Delegate but that results in the same issue with the iOS menu.
proxy format: host:port:username:password
When I run the code below I am prompted with a menu to add credentials for the proxy. I closed this menu inside my app and tried the function below again and it worked without giving me the menu a second time. However even though the function works without throwing any errors, it does NOT use the proxies to route the request.
I've spent days on this and the only solution I found was using a NWConnection but this is super low level and now I need a shared session to manage cookies. If you want to see the NWConnection solution I made its here
func averageProxyGroupSpeed(proxies: [String], completion: @escaping (Int, String) -> Void) {
let numProxies = proxies.count
if numProxies == 0 {
completion(0, "No proxies")
return
}
var totalTime: Int64 = 0
var successCount = 0
let group = DispatchGroup()
let queue = DispatchQueue(label: "proxyQueue", attributes: .concurrent)
let lock = NSLock()
let shuffledProxies = proxies.shuffled()
let selectedProxies = Array(shuffledProxies.prefix(25))
for proxy in selectedProxies {
group.enter()
queue.async {
let proxyDetails = proxy.split(separator: ":").map(String.init)
guard proxyDetails.count == 4,
let port = Int(proxyDetails[1]),
let url = URL(string: "http://httpbin.org/get") else {
completion(0, "Invalid proxy format")
group.leave()
return
}
var request = URLRequest(url: url)
request.timeoutInterval = 15
let configuration = URLSessionConfiguration.default
configuration.connectionProxyDictionary = [
AnyHashable("HTTPEnable"): true,
AnyHashable("HTTPProxy"): proxyDetails[0],
AnyHashable("HTTPPort"): port,
AnyHashable("HTTPSEnable"): false,
AnyHashable("HTTPUser"): proxyDetails[2],
AnyHashable("HTTPPassword"): proxyDetails[3]
]
let session = URLSession(configuration: configuration)
let start = Date()
let task = session.dataTask(with: request) { _, _, error in
defer { group.leave() }
if let error = error {
print("Error: \(error.localizedDescription)")
} else {
let duration = Date().timeIntervalSince(start) * 1000
lock.lock()
totalTime += Int64(duration)
successCount += 1
lock.unlock()
}
}
task.resume()
}
}
group.notify(queue: DispatchQueue.main) {
if successCount == 0 {
completion(0, "Proxies Failed")
} else {
let averageTime = Int(Double(totalTime) / Double(successCount))
completion(averageTime, "")
}
}
}
Delegate example
class ProxySessionDelegate: NSObject, URLSessionDelegate {
let username: String
let password: String
init(username: String, password: String) {
self.username = username
self.password = password
}
func urlSession(_ session: URLSession, task: URLSessionTask, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodHTTPBasic {
let credential = URLCredential(user: self.username, password: self.password, persistence: .forSession)
completionHandler(.useCredential, credential)
} else {
completionHandler(.performDefaultHandling, nil)
}
}
}
When our content filter is deployed, some customers report issues which show that the content filter activation was performed but the filter is showing the state [activated waiting for user].
This typically happens if the customer isn't deploying a profile to pre-authorise the system extension.
The customers report that there was no popup shown for them to allow the filter to complete activation.
Once the filter is in this state, there doesn't seem to be a way to clear it without resorting to disabling SIP.
Attempting a deactivation does not work, the filter remains in the same state.
Is there a way we can we resolve this "stuck" state when it happens without disabling SIP?
Hi everyone,
I'm developing a visionOS app that allows users to download large video files (similar to a movie download experience, with each file being around 10 GB). I've successfully implemented the core video download functionality using URLSession, and everything works as expected while the app is active.
Now, I’m looking to support background downloading. Specifically, I want users to be able to start a download and then leave the app (e.g., switch apps or return to the home screen) while the download continues in the background.
Additionally, I’d like to confirm a specific scenario:
If the user starts a download, then removes the headset (keeping the device turned on and connected to power), will the download continue in the background? Or does visionOS suspend the app or downloads in this case?
I’m considering using a background URLSessionConfiguration (as done in iOS/macOS) to enable this behavior, but I’m not sure if it behaves the same way on visionOS or if there are special limitations or best practices when handling large downloads on this platform.
Any insights or official guidance would be greatly appreciated!
Thanks!
Context: We are using NWConnection for UDP and TCP Connections, and wanted to know the best way to keep the number of pending send completions in control to limit resource usage
Questions:
Is there a way to control the send rate, such that too many 'send pending completion' does not get queued. Say if I do a ‘extremely dense flurry of 10 million NWConnection.send’ will all go asynchronous without any complications? Or I would be informed once it reaches some threshold.
Or no? And is it the responsibility of the application using NWConnection.send to limit the outstanding completion , as if they were beyond a certain limit, it would have an impact on outstanding and subsequent requests?
If so – how would one know ‘what is supposed to be the limit’ at runtime? Is this a process level or system level limit.
Will errors like EAGAIN and ETIMEOUT ever will be reported. In the test I simulated, where the TCP Server was made to not do receive, causing the 'socket send buffer' to become full on the sender side. On the sender side my send stopped getting complete, and became pending. Millions of sends were pending for long duration, hence wanted to know if we will ever get EAGAIN or ETIMEOUT.
I am trying to commission an ESP32-H2 Matter device using the chip-tool. It's running the Light Switch sample. I can commissioning it using the iOS Home App, so I know the code on it's working okay.
I would like to understand more about the Fabric process, so I'd like to use the Home Pod powered Thread network rather than setting up an instance of Open Thread Border Router.
I have created a simple iOS app and can fetch the activeOperationalDataSet from the Preferred network using
func obtainPreferredNetworkCredentials() async -> (Void) {
let client = THClient()
let bIsPreferredAvailable = await client.isPreferredAvailable()
if bIsPreferredAvailable == true
{
var credential: THCredentials?
do {
credential = try await client.preferredCredentials()
if let dataset = credential?.activeOperationalDataSet {
print(dataset.hexDescription)
}
} catch {
print("Failed to get the credentials")
}
}
}
The hexDescription comes from this extension
extension Data {
var hexDescription: String {
return reduce("") {$0 + String(format: "%02x", $1)}
}
}
I am decoding the Data and displaying it as a hex string. It looks something like this:
0e080000000000000000000300001935060004001fffc002089f651677026f48070708fd9f65167702000ee90914b5d1097de9bb0818dc94690c0402a0f7f8
However, when I attempt to commission the device, it fails during ThreadSetup. Googling the issue says most likely the Operational Dataset is wrong in some way.
Before I spend too much time on this, I want to make sure I'm doing the right thing in terms of getting the Operational Dataset to use with the chip-tool.
Any help is appreciated!
I upgraded my Mac to Sequoia 15.4.1 an i hat to upgrade XCode to Version 16.3.
I access a MQTT Broker by an sending an
mosquitto_sub
request to the Broker.
Now its no longer possible the request fails
i granted Network permission to my App
I have an NEPacketTunnelProvider that's configured using NEPacketTunnelNetworkSettings. I'm using NEDNSSettings to configure the DNS resolver of the packet tunnel, and would like to specify the exact domains that should use this resolver using the matchDomains member variable.
While it's not explicitly mentioned in the documentation [1], I've noticed that if a domain is present in matchDomains, then all subdomains of it will also be resolved using this resolver, as if a wildcard match rule is in place.
I wanted to ask if this the intended behavior, and if so, is there any way to disable it so that only exact domain matches will be resolved?
I.e., if "example.com" is in the matchDomains list, I would like requests for this domain be resolved using the configured DNS resolver, while ignoring requests to the subdomain"test.example.com".
[1] https://developer.apple.com/documentation/networkextension/nednssettings/matchdomains
Hello, I'm having some problems when install my Packet Tunnel network extension as system extension on my mac(macos 15.0).
It stuck on Validation By Category. (it works well as NE app extension on ios)
systemextensionsctl list
--- com.apple.system_extension.network_extension
enabled active teamID bundleID (version) name [state]
<...> com.myteam.balabalabla.ne (1.0/1) - [validating by category]
This is my install System Extension Code sample
public class SystemExtension: NSObject, OSSystemExtensionRequestDelegate {
private let forceUpdate: Bool
private let inBackground: Bool
private let semaphore = DispatchSemaphore(value: 0)
private var result: OSSystemExtensionRequest.Result?
private var properties: [OSSystemExtensionProperties]?
private var error: Error?
private init(_ forceUpdate: Bool = false, _ inBackground: Bool = false) {
}
// some request function i overwrite
public func activation() throws -> OSSystemExtensionRequest.Result? {
let request = OSSystemExtensionRequest.activationRequest(forExtensionWithIdentifier: FilePath.packageName + ".myNeName", queue: .main)
request.delegate = self
OSSystemExtensionManager.shared.submitRequest(request)
semaphore.wait()
if let error {
throw error
}
return result
}
public func getProperties() throws -> [OSSystemExtensionProperties] {
let request = OSSystemExtensionRequest.propertiesRequest(forExtensionWithIdentifier: FilePath.packageName + ".myNeName", queue: .main)
request.delegate = self
OSSystemExtensionManager.shared.submitRequest(request)
semaphore.wait()
if let error {
throw error
}
return properties!
}
public nonisolated static func install(forceUpdate: Bool = false, inBackground: Bool = false) async throws -> OSSystemExtensionRequest.Result? {
try await Task.detached {
try SystemExtension(forceUpdate, inBackground).activation()
}.result.get()
}
public nonisolated static func uninstall() async throws -> OSSystemExtensionRequest.Result? {
try await Task.detached {
try SystemExtension().deactivation()
}.result.get()
}
}
// And other methods
I follow this post Your Friend the System Log and use this command line to collect log. After I initiated the system extension request
sudo log collect --last 5m
Here is my log (),I only pasted some code snippets that caught me, full version see attachments.(only include com.apple.sysextd), if need more, plz ask me.
1. Some policy missing
```log
22:00:13.818257 `sysextd` extension mockTeamID app.balabala.com.mockbalabala (1.0/1) advancing state from staging to validating
22:00:13.818263 sysextd returning cdhash for local arch arm64 of extension app.balabala.com.mockbalabala
info 2025-05-01 22:00:13.818336 sysextd Extension with identifier <private> reached state <private>
22:00:13.819185 sysextd [0x9a2034b00] activating connection: mach=false listener=false peer=false name=com.apple.CodeSigningHelper
22:00:13.819911 sysextd [0x9a2034b00] invalidated after the last release of the connection object
22:00:13.821024 sysextd making activation decision for extension with teamID teamID("mockTeamID ), identifier app.balabala.com.mockbalabala
22:00:13.821026 sysextd no related kext found for sysex `app.balabala.com.mockbalabala`
22:00:13.821027 sysextd no extension policy -- activation decision is UserOption
nesessionmanager.system-extensions interrupted
22:00:14.313576 sysextd [0x9a2178280] invalidated because the client process (pid 1886) either cancelled the connection or exited
22:00:14.542154 sysextd connection to com.apple.nesessionmanager.system-extensions interrupted
22:00:14.542319 sysextd [0x9a2178000] Re-initialization successful; calling out to event handler with XPC_ERROR_CONNECTION_INTERRUPTED
22:00:14.542351 sysextd connection to com.apple.nesessionmanager.system-extensions interrupted
22:00:14.589375 nesessionmanager [0x6c80e4500] activating connection: mach=true listener=false peer=false name=com.apple.sysextd
And when i debug the System Extension code i notice the request Error catch by didFailWithError
public func request(_: OSSystemExtensionRequest, didFailWithError error: Error) {
self.error = error
semaphore.signal()
}
error is
OSSystemExtensionErrorDomain code 1
This problem has been bothering me for a long time, I would appreciate any help, if need more info, comment, thank you.
Topic:
App & System Services
SubTopic:
Networking
Tags:
macOS
Network Extension
Network
System Extensions