iOS Development environment
Xcode 16.4, macOS 15.6.1 (24G90)
Run-time configuration: iOS 17.2+
Short Description
After having successfully established an NWConnection (either as UDP or TCP), and subsequently receiving the error code:
UDP Connection failed: 57 The operation couldn't be completed. (Network.NWError error 57 - Socket is not connected), available Interfaces: [enO]
via
NWConnection.stateUpdateHandler = { (newState) in ... } while newState == .failed
the data connection does not restart by itself once cellular (RF) telephony coverage is established again.
Detailed Description
Context: my app has a continuous cellular data connection while in use. Either a UDP or a TCP connection is established depending on the user settings.
The setup data connection works fine until the data connection gets disconnected by loss of connection to a available cellular phone base station. This disconnection simply occurs in very poor UMTS or GSM cellular phone coverage. This is totally normal behavior in bad reception areas like in mountains with signal loss.
STEPS TO REPRODUCE
Pre-condition
App is running with active data connection.
Action
iPhone does loss the cellular data connection previously setup. Typically reported as network error code 57.
Observed
The programmed connection.stateUpdateHandler() is called in network connection state '.failed' (OK).
The self-programmed data re-connection includes:
a call to self.connection.cancel()
a call to self.setupUDPConnection() or self.setupConnection() depending on the user settings to re-establish an operative data connection.
However, the iPhone's UMTS/GSM network data (re-)connection state is not properly identified/notified via NWConnection API. There's no further network state notification by means of NWConnection even though the iPhone has recovered a cellular data network.
Expected
The iPhone or any other means automatically reconnects the interrupted data connection on its own. The connection.stateUpdateHandler() is called at time of the device's networking data connection (RF) recovering, subsequently to a connection state failed with error code 57, as the RF module is continuously (independently from the app) for available telephony networks.
QUESTION
How to systematically/properly detect a cellular phone data network reconnection readiness in order to causally reinitialize the NWConnection data connection available used in app.
Relevant code extract
Setup UDP connection (or similarly setup a TCP connection)
func setupUDPConnection() {
let udp = NWProtocolUDP.Options.init()
udp.preferNoChecksum = false
let params = NWParameters.init(dtls: nil, udp: udp)
params.serviceClass = .responsiveData // service type for medium-delay tolerant, elastic and inelastic flow, bursty, and long-lived connections
connection = NWConnection(host: NWEndpoint.Host.name(AppConstant.Web.urlWebSafeSky, nil), port: NWEndpoint.Port(rawValue: AppConstant.Web.urlWebSafeSkyPort)!, using: params)
connection.stateUpdateHandler = { (newState) in
switch (newState) {
case .ready:
//print("UDP Socket State: Ready")
self.receiveUDPConnection(). // data reception works fine until network loss
break
case .setup:
//print("UDP Socket State: Setup")
break
case .cancelled:
//print("UDP Socket State: Cancelled")
break
case .preparing:
//print("UDP Socket State: Preparing")
break
case .waiting(let error):
Logger.logMessage(message: "UDP Connection waiting: "+error.errorCode.description+" \(error.localizedDescription), available Interfaces: \(self.connection.currentPath!.availableInterfaces.description)", LoggerLevels.Error)
break
case .failed(let error):
Logger.logMessage(message: "UDP Connection failed: "+error.errorCode.description+" \(error.localizedDescription), available Interfaces: \(self.connection.currentPath!.availableInterfaces.description)", LoggerLevels.Error)
// data connection retry (expecting network transport layer to be available)
self.reConnectionServer()
break
default:
//print("UDP Socket State: Waiting or Failed")
break
}
self.handleStateChange()
}
connection.start(queue: queue)
}
Handling of network data connection loss
private func reConnectionServer() {
self.connection.cancel()
// Re Init Connection - Give a little time to network recovery
let delayInSec = 30.0. // expecting actually a notification for network data connection availability, instead of a time-triggered retry
self.queue.asyncAfter(deadline: .now() + delayInSec) {
switch NetworkConnectionType {
case 1:
self.setupUDPConnection() // UDP
break
case 2:
self.setupConnection() // TCP
break
default:
break
}
}
}
Does it necessarily require the use of CoreTelephony class CTTelephonyNetworkInfo or class CTCellularData to get notifications of changes to the user’s cellular service provider?
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
With my UDP Flow Copier working as demonstrated by the fact that it is proxying DNS traffic successfully, I am finally writing tests to verify UDP packet filtering. I'm sending packets to a public UDP echo server and reading the response successfully. In my initial testing however the TransparentProxyProvider System Extension is not intercepting my UDP traffic. handleNewUDPFlow() is being called for DNS but not for my test case UDP echo sends and receives. I've tried sending UDP with both GCDAsyncSocket and NWConnection as:
connection = NWConnection(host: host, port: port, using: .udp)
Is there some other criteria for UDP datagrams to be intercepted? Google search suggests this might be a known issue for connected or async UDP sockets.
I'm using a Mac Studio in a homelab context and use Homebrew to manage the installed services. The services include things that access the local network, for example Prometheus which monitors some other servers, a reverse proxy which fronts other web services on the network, and a DNS server which can use another as upstream.
Local Network Access permissions make it impossible to reliably perform unattended updates of services because an updated binary requires a GUI login to grant local network permissions (again).
I use brew services to manage the services as launchd agents, i.e. they run in a non-root GUI context. I know that I can also use sudo brew services which instead installs the services as launchd daemons, but running services as root has negative security implication and generally doesn't look like a good idea to me.
If only there was a way to disable local network access checks altogether…
Hello,
I am working to integrate the new com.apple.developer.networking.carrier-constrained.app-optimized entitlement in my iOS 26 app so that my app can use a carrier-provided satellite network, and want to confirm my understanding of how to detect and optimize for satellite network conditions.
(Ref: https://developer.apple.com/documentation/bundleresources/entitlements/com.apple.developer.networking.carrier-constrained.app-optimized )
My current approach:
I plan to set the entitlement to true once my app is optimized for satellite networks.
To detect if the device is connected to a satellite network, I intend to use the Network framework’s NWPath properties:
isUltraConstrained — I understand this should be set to true when the device is connected to a satellite network.
(Ref: https://developer.apple.com/documentation/network/nwpath/isultraconstrained )
linkQuality == .minimal — I believe this will also be set in satellite scenarios, though it may not be exclusive to satellite connections.
(Ref:
https://developer.apple.com/documentation/network/nwpath/linkquality-swift.enum/minimal )
Questions:
Is it correct that isUltraConstrained will reliably indicate a satellite connection?
Should I also check for linkQuality == .minimal, or is isUltraConstrained sufficient?
Are there any additional APIs or best practices for detecting and optimizing for satellite connectivity that I should be aware of?
Thank you for confirming whether my understanding and approach are correct, and for any additional guidance.
I want to configure one aspect of my networking configuration (the QUIC keepalive interval). This only seems to be configurable via Network.framework’s nw_quic_set_keepalive_interval. Is there any way to apply this to a URLSession? Or do I need to implement the whole connection management myself using Network.framework?
I am developing a program on my chip and attempting to establish a connection with the WiFi Aware demo app launched by iOS 26. Currently, I am encountering an issue during the pairing phase.
If I am the subscriber of the service and successfully complete the follow-up frame exchange of pairing bootstrapping, I see the PIN code displayed by iOS.
Question 1: How should I use this PIN code?
Question 2: Subsequently, I need to negotiate keys with iOS through PASN. What should I use as the password for the PASN SAE process?
If I am the subscriber of the service and successfully complete the follow-up frame exchange of pairing bootstrapping, I should display the PIN code.
Question 3: How do I generate this PIN code?
Question 4: Subsequently, I need to negotiate keys with iOS through PASN. What should I use as the password for the PASN SAE process?
Topic:
App & System Services
SubTopic:
Networking
On my iPhone 16 Pro and iPhone 16 Pro Max devices, running iOS 26.0, 26.0.1, and 26.1, Wi-Fi raw socket communication works flawlessly. Even after keeping the connection active for over 40 minutes, there are no disconnections during data transmission.
However, on the iPhone 17 and iPhone 17 Pro, the raw socket connection drops within 20 seconds. Once it disconnects, the socket cannot reconnect unless the Wi-Fi module itself is reset.
I believe this issue is caused by a bug in the iPhone 17 series’ communication module. I have looked into many cases, and it appears to be related to a bug in the N1 chipset.
Are there any possible solutions or workarounds for this issue?
Apologies if this is not the correct topic to post under.
EpochField 5.2 is our application. It's a .NET MAUI application built against XCode 16. A customer of ours uses another app, TN3270, to connect to a mainframe host. After installing our app on an iPad and restarting the device, the TN3270 app will disconnect when suspended. Uninstalling our app (EpochField) will allow the TN3270 to suspend without disconnecting. We have tried removing background services, setting UIRequiresFullScreen to false or removing it entirely, and several other ideas. The only remedy seems to be uninstalling EpochField.
On an iPad device:
Install MochaSoft’s TN3270 app (free version is fine). Create a connection to ssl3270.nccourts.org, port 2023, SSL/TLS turned on, keep alive turned on.
Verify that you can connect. Suspend the app by swiping up or choosing another app. Go back to TN3270 and verify that the app has not disconnected.
Install EpochField 5.2. Do not run or configure the app, just install it.
Repeat step 2.
Restart the device.
Open EpochField 5.2. You do not need to configure the app or login. Sometimes it isn't necessary to ever open EpochField to get the disconnects, but this is the most reliable way to reproduce the situation.
Repeat step 2. The TN3270 app will now disconnect when suspended, even if EpochField is closed. You may need to wait a few seconds after suspending.
Uninstall EpochField 5.2.
Repeat step 2: the TN3270 app will now remain connected when suspended.
Topic:
App & System Services
SubTopic:
Networking
I want to detect if the adapter is connected to the iPhone even if no IP has been given to the iPhone. I can detect that the interface is connected when the iPhone has been given an IP address, but how can I detect the adapter when not?
Topic:
App & System Services
SubTopic:
Networking
My company has a server that supports ticket-based TLS session resumption (per RFC 5077).
We have done Wireshark captures that show that our iOS client app, which uses URLSession for REST and WebSocket connections to the server, is not sending the TLS "session_ticket" extension in the Client Hello package that necessary to enable ticket-based resumption with the server.
Is it expected that URLSession does not support ticket-based TLS session resumption?
If "yes", is there any way to tell URLSession to enable ticket-based session resumption? the lower-level API set_protocol_options_set_tls_tickets_enabled() hints that the overall TLS / HTTP stack on IOS does support ticket-based resumption, but I can't see how to use that low-level API with URLSession.
I can provide (lots) more technical details if necessary, but hopefully this is enough context to determine whether ticket-based TLS resumption is supported with URLSession.
Any tips / clarifications would be greatly appreciated.
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
My app has local network permission on macOS Sequoia and works in most cases. I've noticed that after unlocking my MacBook Pro, the very first request will regularly fail with a No Route to Host. A simple retry resolves the issue, but I would have expected the very first request to succeed.
Is this is a known issue on macOS Sequoia or by design? I'd prefer not to add a retry for this particular request as the app is a network utility.
Topic:
App & System Services
SubTopic:
Networking
Hi everyone,
I’m encountering what appears to be a system-level issue with NEAppPushProvider extensions being unable to communicate with other devices on the local network, even when the main app has already been granted Local Network permission by the user.
Context
The following problem occurs in an iPad app running iOS 18.5.
The main app successfully requests and is granted Local Network access via NSLocalNetworkUsageDescription in its Info.plist configuration. It can connect to a WebSocket server hosted on the local network without any issues, resolving its address by name.
The extension (NEAppPushProvider) uses the same networking code as the app, extended via target membership of a controller class. It attempts to connect to the same hostname and port but consistently fails to establish a connection. The system log shows it properly resolving DNS but being stopped due to "local network prohibited". An extract of the logs from the Unified Logging System:
12:34:10.086064+0200 PushProvider [C526 Hostname#fd7b1452:8443 initial parent-flow ((null))] event: path:start @0.000s
12:34:10.087363+0200 PushProvider [C526 Hostname#fd7b1452:8443 waiting parent-flow (satisfied (Path is satisfied), interface: en0[802.11], ipv4, dns, uses wifi)] event: path:satisfied @0.005s
12:34:10.090074+0200 PushProvider [C526 Hostname#fd7b1452:8443 in_progress parent-flow (satisfied (Path is satisfied), interface: en0[802.11], ipv4, dns, uses wifi)] event: flow:start_connect @0.006s
12:34:10.093190+0200 PushProvider [C526.1 Hostname#fd7b1452:8443 in_progress resolver (satisfied (Path is satisfied), interface: en0[802.11], ipv4, dns, uses wifi)] event: resolver:start_dns @0.009s
12:34:10.094403+0200 PushProvider [C526.1.1 IPv4#f261a0dc:8443 waiting path (unsatisfied (Local network prohibited), interface: en0[802.11], ipv4, uses wifi)] event: path:unsatisfied @0.010s
12:34:10.098370+0200 PushProvider [C526.1.1.1 IPv4#f261a0dc:8443 failed path (unsatisfied (Local network prohibited), interface: en0[802.11], ipv4, uses wifi)] event: null:null @0.014s
12:34:10.098716+0200 PushProvider [C526.1 Hostname#fd7b1452:8443 failed resolver (satisfied (Path is satisfied), interface: en0[802.11], ipv4, dns, uses wifi)] event: resolver:children_failed @0.015s
12:34:10.099297+0200 PushProvider [C526 Hostname#fd7b1452:8443 waiting parent-flow (satisfied (Path is satisfied), interface: en0[802.11], ipv4, dns, uses wifi)] event: flow:child_failed @0.016s
What I’ve Confirmed:
The extension works perfectly if the DNS is changed to resolve the name to a public IP instead of a local one. The extension always connects by hostname.
Devices on the local network can resolve each other’s IP addresses correctly and respond to pings.
What I’ve Tried
Adding NSLocalNetworkUsageDescription to the main app’s Info.plist, as recommended.
Clean building the project again.
Removing and reinstalling the app to ensure permission prompts are triggered fresh.
Restarting the iPad.
Ensuring main app cannot access the local network until the permission is granted.
Ensuring the main app has connected to the same hostname and port before the extension attempts a connection
Toggling the permission manually in Settings.
Apple’s documentation states (TN3179):
“In general, app extensions share the Local Network privilege state of their container app.”
It also notes that some background-running extension types may be denied access if the privilege is undetermined. But in my case, the main app clearly has Local Network access, and the extension never receives it, even after repeated successful connections by the main app.
Question
Is this a known limitation with NEAppPushProvider? Is there a recommended way to ensure the extension is able to use the local network permission once the user has granted it on the app?
Any feedback, suggestions, or confirmation would be greatly appreciated. Thanks in advance.
Hello all,
WWDC 2025 introduced Wi‑Fi Aware (NAN) support on iOS 26 for peer-to-peer discovery and direct connections, but I noticed macOS Tahoe doesn’t include it. I couldn’t find any references to Wi‑Fi Aware APIs or framework support in the macOS SDK.
Is Apple planning to bring Wi‑Fi Aware to macOS?
If so, will this come in a future update to macOS 26 (e.g., 26.x), or is it deferred to macOS 27 or beyond?
Thanks for any insights!
Topic:
App & System Services
SubTopic:
Networking
Hi everyone,
I'm trying to establish a connection to a server that requires mutual TLS (mTLS) using NSURLSession in an iOS app. The server is configured with a self-signed root CA (in the project, we are using ca.cer) and requires clients to present a valid certificate during the TLS handshake.
What I’ve done so far:
Server trust is working:
I manually trust the custom root CA using SecTrustSetAnchorCertificates and SecTrustEvaluateWithError.
I also configured the necessary NSAppTransportSecurity exception in Info.plist to allow the server certificate to pass ATS.
This is confirmed by logs showing: Server trust succeeded
The .p12 identity is correctly created: Contains the client certificate and private key.
Loaded using SecPKCS12Import with the correct password.
I implemented the delegate method:
func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge,
completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {
// Server trust override code (working)
...
}
if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodClientCertificate {
print("🔐 Client cert challenge triggered")
if let identity = loadIdentity() {
let credential = URLCredential(identity: identity, certificates: nil, persistence: .forSession)
completionHandler(.useCredential, credential)
} else {
completionHandler(.cancelAuthenticationChallenge, nil)
}
return
}
completionHandler(.performDefaultHandling, nil)
}
The session is correctly created using my custom delegate:
let delegate = MTLSDelegate(identity: identity, certificates: certs)
let session = URLSession(configuration: .default, delegate: delegate, delegateQueue: nil)
Despite everything above, the client certificate is never sent, and the request fails with:
Error Domain=NSURLErrorDomain Code=-1206
"The server requires a client certificate."
From logs, it's clear the delegate is being hit for NSURLAuthenticationMethodServerTrust, but not for NSURLAuthenticationMethodClientCertificate.
On iOS 26 beta 5, it is impossible to add a VPN configuration when a passcode is set on the device. Every time, all it does is redirect to the Settings app with no prompt for passcode.
The only way around this is to disable passcode on the device so adding a VPN configuration doesn’t have to open the Settings app.
This issue happened intermittently in the past with previous iOS 26 betas and even on iOS 18, but the problem has worsened on iOS 26 beta 5 to the point where you have to turn off passcode to add a VPN.
Feedback ID: FB17974765
We are currently working on enhancing our iOS app with satellite mode support, allowing users to access a limited set of core features even in the absence of traditional cellular or Wi-Fi connectivity. As part of this capability, we're introducing a chatbot feature that relies on both WebSocket and HTTP connections for real-time interaction and data exchange.
Given the constrained nature of satellite networks—especially in terms of latency, bandwidth, and connection stability—we're evaluating the feasibility of supporting these communication protocols under such conditions.
Could you please advise whether WebSocket and HTTP connections are expected to work over satellite networks?
Topic:
App & System Services
SubTopic:
Networking
I've had a Unreal Engine project that uses libwebsocket to make a websocket connection with SSL to a server. Recently I made a build using Unreal Engine 5.4.4 on MacOS Sequoia 15.5 and XCode 16.4 and for some reason the websocket connection now fails because it can't get the local issuer certificate. It fails to access the root certificate store on my device (Even though, running the project in the Unreal Editor works fine, it's only when making a packaged build with XCode that it breaks)
I am not sure why this is suddenly happening now. If I run it in the Unreal editor on my macOS it works fine and connects. But when I make a packaged build which uses XCode to build, it can't get the local issuer certificate. I tried different code signing options, such as sign to run locally or just using sign automatically with a valid team, but I'm not sure if code signing is the cause of this issue or not.
This app is only for development and not meant to be published, so that's why I had been using sign to run locally, and that used to work fine but not anymore.
Any guidance would be appreciated, also any information on what may have changed that now causes this certificate issue to happen.
I know Apple made changes and has made notarizing MacOS apps mandatory, but I'm not sure if that also means a non-notarized app will now no longer have access to the root certificate store of a device, in my research I haven't found anything about that specifically, but I'm wondering if any Apple engineers might know something about this that hasn't been put out publicly.
Hello,
I have been playing around the the SimpleURLFilter sample code. I keep getting this error upon installed the filter profile on the device:
mapError unexpected error domain NEVPNConnectionErrorDomainPlugin code 7
which then causes this error:
Received filter status change: <FilterStatus: 'stopped' errorMessage: 'The operation couldn’t be completed. (NetworkExtension.NEURLFilterManager.Error error 14.)'>
I can't find much info about code 7.
Here is the configuration I am trying to run:
<Configuration: pirServerURL: 'http://MyComputer.local:8080' pirAuthenticationToken: 'AAAA' pirPrivacyPassIssuerURL: 'http://MyComputer.local:8080' enabled: 'true' shouldFailClosed: 'true' controlProviderBundleIdentifier: 'krpaul.SimpleURLFilter.SimpleURLFilterExtension' prefilterFetchInterval: '2700.0'>
Hello Apple Support Team,
We are experiencing a performance issue with HTTP/3 in our iOS application during testing.
Problem Description:
Network requests using HTTP/3 are significantly slower than expected. This issue occurs on both Wi-Fi and 4G networks, with both IPv4 and IPv6. The same setup worked correctly in an earlier experiment.
Key Observations:
The slowdown disappears when the device uses:
· A personal hotspot.
· Network Link Conditioner (with no limitations applied).
· Internet sharing from a MacBook via USB (where traffic was also inspected with Wireshark without issues).
The problem is specific to HTTP/3 and does not occur with HTTP/2.
The issue is reproducible on iOS 15, 18.7, and the latest iOS 26 beta.
HTTP/3 is confirmed to be active (via assumeHttp3Capable and Alt-Svc header).
Crucially, the same backend endpoint works with normal performance on Android devices and using curl with HTTP/3 support from the same network.
I've checked the CFNetwork logs in the Console but haven't found any suspicious errors or obvious clues that explain the slowdown.
We are using a standard URLSession with basic configuration.
Attempted to collect qlog diagnostics by setting the QUIC_LOG_DIRECTORY=~/ tmp environment variable, but the logs were not generated.
Question:
What could cause HTTP/3 performance to improve only when the device is connected through a hotspot, unrestricted Network Link Conditioner, or USB-tethered connection? The fact that Android and curl work correctly points to an issue specific to the iOS network stack. Are there known conditions or policies (e.g., related to network interface handling, QoS, or specific packet processing) that could lead to this behavior?
Additionally, why might the qlog environment variable fail to produce logs, and are there other ways to obtain detailed HTTP/3 diagnostic information from iOS?
Any guidance on further diagnostic steps or specific system logs to examine would be greatly appreciated.
Thank you for your assistance.