Hello,
I have been testing my app in iOS 18 device and while creating a server with TCP, then apple make a request for local network permission automatically. If we don't allow the permission, the connection not working. We are getting the connection timeout error even after allowing again from device setting.
Has something changed in the flow for iOS 18 version? Can someone help me to solve this issue?
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!
We have created an app that communicates with devices over BLE, and it is currently out in Testflight. It works as expected for almost everyone, but for some users we get a strange behaviour.
We start by scanning for devices with
scanForPeripherals(withServices:options:),
then connect, and finally initiate pairing by subscribing and writing to a pair of characteristics, which both require encryption.
The issue is that for these users, the following code:
func peripheral(
_ peripheral: CBPeripheral,
didDiscoverCharacteristicsFor service: CBService,
error: Error?
) {
guard error == nil else {
LogManager.shared.log(
"❌ Error discovering characteristics: \(error!)"
)
return
}
for characteristic in service.characteristics ?? [] {
if characteristic.uuid == controlPointUUID {
controlPointCharacteristic = characteristic
LogManager.shared.debugLog(
"Control Point characteristic found."
)
} else if characteristic.uuid == statusUUID {
statusCharacteristic = characteristic
LogManager.shared.debugLog("Notify characteristic found.")
}
}
if statusCharacteristic != nil {
LogManager.shared.debugLog("Call Set notify.")
peripheral.setNotifyValue(true, for: statusCharacteristic!)
}
}
func peripheral(
_ peripheral: CBPeripheral,
didUpdateNotificationStateFor characteristic: CBCharacteristic,
error: Error?
) {
if error != nil {
LogManager.shared.log(
"❌ Failed to subscribe to \(characteristic.uuid): \(error.debugDescription)"
)
produces this error:
> > [22:31:34.632] ❌ Failed to subscribe to F1D0FFF2-DEAA-ECEE-B42F-C9BA7ED623BB: Optional(Error Domain=CBATTErrorDomain Code=15 "Encryption is insufficient." UserInfo={NSLocalizedDescription=Encryption is insufficient.})
So in essence, we can't perform pairing and enable encryption, because we have insufficient encryption.
I know that the system caches some key material after pairing. When I do "Forget device" and then pair again, I don't need to put my device in pairing mode for the pairing pin to appear, which is not the case for devices that have not been paired before.
Given that I can't reproduce the problem locally, it's hard to debug using the console. What I've been trying to do is figure out how to reset Bluetooth, which should hopefully remove old keys and whatever else might be there.
The top hit when searching for 'clear corebluetooth cache macos' is on stackexchange, and writes:
Turn off Bluetooth
Delete com.apple.Bluetooth.plist from /Library/Preferences
Delete files named com.apple.Bluetooth.somehexuuidstuff.plist from ~/Library/Preferences/ByHost (note that this is the user preference folder, not the system one)
Turn on Bluetooth
The answer is from December 2013, so it's not surpising that things don't work out of the box, but anyways:
My ByHost folder does not contain any plist files with Bluetooth in them, and deleting the one in /Library/Preferences did not do anything, and judging from the content, it does not contain anything valuable.
I have tried "sudo grep -r 'Bluetooth' ." in both /Library/Preferences/ and ~/Library/Preferences/ and looked at the resulting hits, but I can't seem to find anything meaningful.
As a sidenote, does anyone know what is going on with Apple's entitlement service? We applied for an entitlement in August and have yet to receive a response.
I have read the other most relevant posts on this topic here and here. However, the situations described in these posts are different. My app is just a regular Mach-O bundle with a single executable that is launched by the user from the Finder. I've read the Local Network Privacy FAQ and TN3179 carefully and these also doesn't cover the problem described below, which is being reported to me by several of my users.
The problem is that some days after giving Local Network permission to my app, without having changed anything, local network connections will spontaneously start failing with EHOSTUNREACH, indicating that it is being blocked by macOS. This typically happens after a Mac reboot. Toggling off/on the Local Network permission for my app will get it working again, until the next time it fails.
My users who are reporting this have stated that they are running macOS Sonoma 15.2, with only a single version/copy of my app installed.
I've tried, and failed, to reproduce this in a VM with a clean 15.2 system, but maybe this is due to the relatively short duration of my testing (days rather than weeks).
I know there isn't much to go on here, and it may be tempting to put this down to misreporting. After all, the vast majority of my users aren't reporting this, and I can't reproduce it. But, I have received enough similar reports at this point that it's starting to feel like a macOS bug.
Is anyone else seeing this? If there is anything that anyone can suggest - either modifications in my app, or anything that my users can do on their side - this would be very much appreciated!
Many thanks,
Ben
I've implemented a custom system extension VPN for macOS, using a Packet Tunnel Provider.
I saw something suspicious on macOS 15.2.0: When I disconnected my VPN, the UTUN was not being cleared.
This results in a lot of UTUNs when the user connects and disconnects multiple times.
utun77: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> mtu 1500
utun78: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> mtu 1500
This happens only on macOS 15.2. I tried the same app on older versions (15.0, 15.1.x), and it didn't reproduce.
Can those 'dirty' UTUNs cause a networking problem?
Since it happens only on macOS 15.2, is there a bug in this OS version?
How can I check if something in my code causes this behavior? How can I 'fix' it or force clean the 'dirty' UTUNs?
Our application uses NEFilterPacketProvider to filter network traffic and we sometimes get a wired crash when removing/updating the network extension.
It only happens on MacOS 11-12 .
The crashing thread is always this one and it shows up after I call the completionHandler from the stopFilter func
Application Specific Information:
BUG IN CLIENT OF LIBDISPATCH: Release of a suspended object
Thread 6 Crashed:: Dispatch queue: com.apple.network.connections
0 libdispatch.dylib 0x00007fff2039cc35 _dispatch_queue_xref_dispose.cold.1 + 24
1 libdispatch.dylib 0x00007fff20373808 _dispatch_queue_xref_dispose + 50
2 libdispatch.dylib 0x00007fff2036e2eb -[OS_dispatch_source _xref_dispose] + 17
3 libnetwork.dylib 0x00007fff242b5999 __nw_queue_context_create_source_block_invoke + 41
4 libdispatch.dylib 0x00007fff2036d623 _dispatch_call_block_and_release + 12
5 libdispatch.dylib 0x00007fff2036e806 _dispatch_client_callout + 8
6 libdispatch.dylib 0x00007fff203711b0 _dispatch_continuation_pop + 423
7 libdispatch.dylib 0x00007fff203811f4 _dispatch_source_invoke + 1181
8 libdispatch.dylib 0x00007fff20376318 _dispatch_workloop_invoke + 1784
9 libdispatch.dylib 0x00007fff2037ec0d _dispatch_workloop_worker_thread + 811
10 libsystem_pthread.dylib 0x00007fff2051545d _pthread_wqthread + 314
11 libsystem_pthread.dylib 0x00007fff2051442f start_wqthread + 15
I do have a DispatchSourceTimer but I cancel it in the stop func.
Any ideas on how to tackle this?
Hi, I have a problem with my Mac crashing sims 4. can you let me know if this is a Mac problem or a sims 4 problem ?
Link to Mac Info : https://prnt.sc/NYG0jn8_u0dB
Link to crash report : https://prnt.sc/UImzDIsqdVYn
From time to time the subject of NECP grows up, both here on DevForums and in DTS cases. I’ve posted about this before but I wanted to collect those tidbits into single coherent post.
If you have questions or comments, start a new thread in the App & System Services > Networking subtopic and tag it with Network Extension. That way I’ll be sure to see it go by.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
A Peek Behind the NECP Curtain
NECP stands for Network Extension Control Protocol. It’s a subsystem within the Apple networking stack that controls which programs have access to which network interfaces. It’s vitally important to the Network Extension subsystem, hence the name, but it’s used in many different places. Indeed, a very familiar example of its use is the Settings > Mobile Data [1] user interface on iOS.
NECP has no explicit API, although there are APIs that are offer some insight into its state. Continuing the Settings > Mobile Data example above, there is a little-known API, CTCellularData in the Core Telephony framework, that returns whether your app has access to WWAN.
Despite having no API, NECP is still relevant to developers. The Settings > Mobile Data example is one place where it affects app developers but it’s most important for Network Extension (NE) developers. A key use case for NECP is to prevent VPN loops. When starting an NE provider, the system configures the NECP policy for the NE provider’s process to prevent it from using a VPN interface. This means that you can safely open a network connection inside your VPN provider without having to worry about its traffic being accidentally routed back to you. This is why, for example, an NE packet tunnel provider can use any networking API it wants, including BSD Sockets, to run its connection without fear of creating a VPN loop [1].
One place that NECP shows up regularly is the system log. Next time you see a system log entry like this:
type: debug
time: 15:02:54.817903+0000
process: Mail
subsystem: com.apple.network
category: connection
message: nw_protocol_socket_set_necp_attributes [C723.1.1:1] setsockopt 39 SO_NECP_ATTRIBUTES
…
you’ll at least know what the necp means (-:
Finally, a lot of NECP infrastructure is in the Darwin open source. As with all things in Darwin, it’s fine to poke around and see how your favourite feature works, but do not incorporate any information you find into your product. Stuff you uncover by looking in Darwin is not considered API.
[1] Settings > Cellular Data if you speak American (-:
[2] Network Extension providers can call the createTCPConnection(to:enableTLS:tlsParameters:delegate:) method to create an NWTCPConnection [3] that doesn’t run through the tunnel. You can use that if it’s convenient but you don’t need to use it.
[3] NWTCPConnection is now deprecated, but there are non-deprecated equivalents. For the full story, see NWEndpoint History and Advice.
Revision History
2025-12-12 Replaced “macOS networking stack” with “Apple networking stack” to avoid giving the impression that this is all about macOS. Added a link to NWEndpoint History and Advice. Made other minor editorial changes.
2023-02-27 First posted.
We updated the apple-app-site-association file two weeks ago and we are only seeing the new content from Apple's CDN serving certain regions such as Texas and Canada. Regions such as Colorado intermittently sees the old content and California has been receiving the old content all the time.
Is this a known issue? If yes, when can we expect this to be fixed and where to check the status? If not, can someone in charge of CDN please look into this? Let me know if there is a better place to report this issue and get the support ASAP though.
Thank you in advance and happy new year!
Hello,
I am currently investigating if we can disable usage of QUIC on application level.
I know we can set enable_quic from /Library/Preferences/com.apple.networkd.plist to false but it will have a global impact since this is a system file, all the applications on machine will stop using QUIC. I don't want that. What i am looking for is to disable QUIC only for my application.
Is there any way i can modify URLSession object in my application and disable QUIC? or modify URLSessionConfiguration so system will not use QUIC?
I haven’t come across any official documentation regarding the limit on the number of Network Extensions macOS can run. However, I did see some discussions suggesting that Apple might restrict this to 5 extensions in macOS Tahoe.
Is there any official confirmation on this?
If I was to build an app that opened a web server at local host on a random port that resolved subdomains for local host at that port, but there was no certificate authority, signed certificate available to provide HTTPS security, would this be in violation of apples ATS policy
We have developed a DNS filter extension that works for most applications, but it does not receive all DNS queries.
In particular, if we have our extension installed and enabled, we see Safari browsing cause local DNS servers to be used instead of going through our extension.
What is the logic for how DNS servers vs. extensions are chosen to resolve DNS queries?
This is a topic that’s come up a few times on the forums, so I thought I’d write up a summary of the issues I’m aware of. If you have questions or comments, start a new thread in the App & System Services > Networking subtopic and tag it with Network Extension. That way I’ll be sure to see it go by.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
Network Extension Provider Packaging
There are two ways to package a network extension provider:
App extension ( appex )
System extension ( sysex )
Different provider types support different packaging on different platforms. See TN3134 Network Extension provider deployment for the details.
Some providers, most notably packet tunnel providers on macOS, support both appex and sysex packaging. Sysex packaging has a number of advantages:
It supports direct distribution, using Developer ID signing.
It better matches the networking stack on macOS. An appex is tied to the logged in user, whereas a sysex, and the networking stack itself, is global to the system as a whole.
Given that, it generally makes sense to package your Network Extension (NE) provider as a sysex on macOS. If you’re creating a new product that’s fine, but if you have an existing iOS product that you want to bring to macOS, you have to account for the differences brought on by the move to sysex packaging. Similarly, if you have an existing sysex product on macOS that you want to bring to iOS, you have to account for the appex packaging. This post summarises those changes.
Keep the following in mind while reading this post:
The information here applies to all NE providers that can be packaged as either an appex or a sysex. When this post uses a specific provider type in an example, it’s just an example.
Unless otherwise noted, any information about iOS also applies to iPadOS, tvOS, and visionOS.
Process Lifecycle
With appex packaging, the system typically starts a new process for each instance of your NE provider. For example, with a packet tunnel provider:
When the users starts the VPN, the system creates a process and then instantiates and starts the NE provider in that process.
When the user stops the VPN, the system stops the NE provider and then terminates the process running it.
If the user starts the VPN again, the system creates an entirely new process and instantiates and starts the NE provider in that.
In contrast, with sysex packaging there’s typically a single process that runs all off the sysex’s NE providers. Returning to the packet tunnel provider example:
When the users starts the VPN, the system instantiates and starts the NE provider in the sysex process.
When the user stops the VPN, the system stops and deallocates the NE provider instances, but leaves the sysex process running.
If the user starts the VPN again, the system instantiates and starts a new instances of the NE provider in the sysex process.
This lifecycle reflects how the system runs the NE provider, which in turn has important consequences on what the NE provider can do:
An appex acts like a launchd agent [1], in that it runs in a user context and has access to that user’s state.
A sysex is effectively a launchd daemon. It runs in a context that’s global to the system as a whole. It does not have access to any single user’s state. Indeed, there might be no user logged in, or multiple users logged in.
The following sections explore some consequences of the NE provider lifecycle.
[1] It’s not actually run as a launchd agent. Rather, there’s a system launchd agent that acts as the host for the app extension.
App Groups
With an app extension, the app extension and its container app run as the same user. Thus it’s trivial to share state between them using an app group container.
Note When talking about extensions on Apple platforms, the container app is the app in which the extension is embedded and the host app is the app using the extension. For network extensions the host app is the system itself.
That’s not the case with a system extension. The system extension runs as root whereas the container app runs an the user who launched it. While both programs can claim access to the same app group, the app group container location they receive will be different. For the system extension that location will be inside the home directory for the root user. For the container app the location will be inside the home directory of the user who launched it.
This does not mean that app groups are useless in a Network Extension app. App groups are also a factor in communicating between the container app and its extensions, the subject of the next section.
IMPORTANT App groups have a long and complex history on macOS. For the full story, see App Groups: macOS vs iOS: Working Towards Harmony.
Communicating with Extensions
With an app extension there are two communication options:
App-provider messages
App groups
App-provider messages are supported by NE directly. In the container app, send a message to the provider by calling sendProviderMessage(_:responseHandler:) method. In the appex, receive that message by overriding the handleAppMessage(_:completionHandler:) method.
An appex can also implement inter-process communication (IPC) using various system IPC primitives. Both the container app and the appex claim access to the app group via the com.apple.security.application-groups entitlement. They can then set up IPC using various APIs, as explain in the documentation for that entitlement.
With a system extension the story is very different. App-provider messages are supported, but they are rarely used. Rather, most products use XPC for their communication. In the sysex, publish a named XPC endpoint by setting the NEMachServiceName property in its Info.plist. Listen for XPC connections on that endpoint using the XPC API of your choice.
Note For more information about the available XPC APIs, see XPC Resources.
In the container app, connect to that named XPC endpoint using the XPC Mach service name API. For example, with NSXPCConnection, initialise the connection with init(machServiceName:options:), passing in the string from NEMachServiceName. To maximise security, set the .privileged flag.
Note XPC Resources has a link to a post that explains why this flag is important.
If the container app is sandboxed — necessary if you ship on the Mac App Store — then the endpoint name must be prefixed by an app group ID that’s accessible to that app, lest the App Sandbox deny the connection. See the app groups documentation for the specifics.
When implementing an XPC listener in your sysex, keep in mind that:
Your sysex’s named XPC endpoint is registered in the global namespace. Any process on the system can open a connection to it [1]. Your XPC listener must be prepared for this. If you want to restrict connections to just your container app, see XPC Resources for a link to a post that explains how to do that.
Even if you restrict access in that way, it’s still possible for multiple instances of your container app to be running simultaneously, each with its own connection to your sysex. This happens, for example, if there are multiple GUI users logged in and different users run your container app. Design your XPC protocol with this in mind.
Your sysex only gets one named XPC endpoint, and thus one XPC listener. If your sysex includes multiple NE providers, take that into account when you design your XPC protocol.
[1] Assuming that connection isn’t blocked by some other mechanism, like the App Sandbox.
Inter-provider Communication
A sysex can include multiple types of NE providers. For example, a single sysex might include a content filter and a DNS proxy provider. In that case the system instantiates all of the NE providers in the same sysex process. These instances can communicate without using IPC, for example, by storing shared state in global variables (with suitable locking, of course).
It’s also possible for a single container app to contain multiple sysexen, each including a single NE provider. In that case the system instantiates the NE providers in separate processes, one for each sysex. If these providers need to communicate, they have to use IPC.
In the appex case, the system instantiates each provider in its own process. If two providers need to communicate, they have to use IPC.
Managing Secrets
An appex runs in a user context and thus can store secrets, like VPN credentials, in the keychain. On macOS this includes both the data protection keychain and the file-based keychain. It can also use a keychain access group to share secrets with its container app. See Sharing access to keychain items among a collection of apps.
Note If you’re not familiar with the different types of keychain available on macOS, see TN3137 On Mac keychain APIs and implementations.
A sysex runs in the global context and thus doesn’t have access to user state. It also doesn’t have access to the data protection keychain. It must use the file-based keychain, and specifically the System keychain. That means there’s no good way to share secrets with the container app.
Instead, do all your keychain operations in the sysex. If the container app needs to work with a secret, have it pass that request to the sysex via IPC. For example, if the user wants to use a digital identity as a VPN credential, have the container app get the PKCS#12 data and password and then pass that to the sysex so that it can import the digital identity into the keychain.
Memory Limits
iOS imposes strict memory limits an NE provider appexen [1]. macOS imposes no memory limits on NE provider appexen or sysexen.
[1] While these limits are not documented officially, you can get a rough handle on the current limits by reading the posts in this thread.
Frameworks
If you want to share code between a Mac app and its embedded appex, use a structure like this:
MyApp.app/
Contents/
MacOS/
MyApp
PlugIns/
MyExtension.appex/
Contents/
MacOS/
MyExtension
…
Frameworks/
MyFramework.framework/
…
There’s one copy of the framework, in the app’s Frameworks directory, and both the app and the appex reference it.
This approach works for an appex because the system always loads the appex from your app’s bundle. It does not work for a sysex. When you activate a sysex, the system copies it to a protected location. If that sysex references a framework in its container app, it will fail to start because that framework isn’t copied along with the sysex.
The solution is to structure your app like this:
MyApp.app/
Contents/
MacOS/
MyApp
Library/
SystemExtensions/
MyExtension.systemextension/
Contents/
MacOS/
MyExtension
Frameworks/
MyFramework.framework/
…
…
That is, have both the app and the sysex load the framework from the sysex’s Frameworks directory. When the system copies the sysex to its protected location, it’ll also copy the framework, allowing the sysex to load it.
To make this work you have to change the default rpath configuration set up by Xcode. Read Dynamic Library Standard Setup for Apps to learn how that works and then tweak things so that:
The framework is embedded in the sysex, not the container app.
The container app has an additional LC_RPATH load command for the sysex’s Frameworks directory (@executable_path/../Library/SystemExtensions/MyExtension.systemextension/Contents/Frameworks).
The sysex’s LC_RPATH load command doesn’t reference the container app’s Frameworks directory (@executable_path/../../../../Frameworks) but instead points to the sysex’s Framweorks directory (@executable_path/../Frameworks).
Entitlements
When you build an app with an embedded NE extension, both the app and the extension must be signed with the com.apple.developer.networking.networkextension entitlement. This is a restricted entitlement, that is, it must be authorised by a provisioning profile.
The value of this entitlement is an array, and the values in that array differ depend on your distribution channel:
If you distribute your app directly with Developer ID signing, use the values with the -systemextension suffix.
Otherwise — including when you distribute the app on the App Store and when signing for development — use the values without that suffix.
Make sure you authorise these values with your provisioning profile. If, for example, you use an App Store distribution profile with a Developer ID signed app, things won’t work because the profile doesn’t authorise the right values.
In general, the easiest option is to use Xcode’s automatic code signing. However, watch out for the pitfall described in Exporting a Developer ID Network Extension.
Revision History
2025-11-06 Added the Entitlements section. Explained that, with sysex packaging, multiple instances of your container app might connect simultaneously with your sysex.
2025-09-17 First posted.
We are experiencing an issue where our iOS app’s network extension (acting as a VPN) is being unexpectedly terminated by the operating system. The termination appears identical to a user-initiated stop, as the extension receives the following call: NEProviderStopReasonUserInitiated.
The issue occurs sporadically but can happen 10–20 times per day on devices with less than 10% free storage.
On one affected device, opening the Camera app (or using the camera within another app like WhatsApp) consistently triggers the issue, making it easily reproducible.
Memory consumption does not seem to be the cause—the extension is stopped while using only ~10MB of memory, well below the 50MB limit.
We noticed a pattern related to swap usage:
• On affected devices, the “Swap Used” column shows very low values (a few MB).
• On unaffected devices, swap usage is significantly higher (hundreds of MB).
• This is the only clear difference we’ve observed.
The issue occurs across different device models and iOS versions (18.2.1 and 17.6.1).
It also happens across different app builds (compiled with Xcode 15.x and Xcode 16.x).
We found a similar report on the Apple Developer Forums:
🔗 https://developer.apple.com/forums/thread/108149
Has anyone else encountered this behavior with Network Extensions? Could low swap usage or system resource constraints be a factor? Any suggestions for debugging or potential workarounds would be greatly appreciated.
Hello,
I’m reviewing the open-source mDNSResponder repository and have a question regarding licensing/provenance in mDNSCore/DNSDigest.c file.
That file contains an embedded notice stating that parts of the MD5/digest implementation were derived from older OpenSSL sources and therefore include the legacy OpenSSL/SSLeay license text, even though OpenSSL itself is now Apache-2.0 starting from version 3.0.
The legacy OpenSSL/SSLeay license is widely understood to impose additional attribution and notice requirements compared to Apache-2.0, and some downstream projects prefer to avoid it when a permissively licensed alternative is available.
Repository: https://github.com/apple-oss-distributions/mDNSResponder
File: https://github.com/apple-oss-distributions/mDNSResponder/blob/main/mDNSCore/DNSDigest.c#L66
I’d like to clarify a few points:
Is the MD5/digest code in DNSDigest.c still based on pre–OpenSSL-3.0 sources, such that retaining the legacy OpenSSL/SSLeay license block is intentional and required?
If the goal were to simplify licensing (Apache-2.0 only), would Apple consider replacing this MD5 implementation with an Apache-2.0–licensed alternative (for example, code derived from OpenSSL 3.x or another permissive implementation)?
Are there any technical or policy reasons (compatibility, crypto policy, platform APIs) that make such a replacement undesirable?
Since GitHub issues and PRs are restricted for this repository, I’m asking here for guidance. If maintainers agree that such an update would be useful, I’d be happy to help by preparing a PR for review.
I've also created a feedback report for this topic, the reference ID is FB21269078.
Thanks for any clarification.
I want to check if the device has a internet connection or not by pinging DNS "8.8.8.8".
connection.send(content: content, completion: .contentProcessed {[weak self] error in
send function is not returning any error even if the host is unreachable.
I am checking if I can receive the data or not but connection.receiveMessage function never returns.
This is the complete code which I am following:
private let networkMonitor = NWPathMonitor()
private var connection: NWConnection
@MainActor var isConnectedToInternet = false
init(host: NWEndpoint.Host = "8.8.8.8",
port: NWEndpoint.Port = 53) {
let endpoint = NWEndpoint.hostPort(host: host, port: port)
connection = NWConnection(to: endpoint, using: .udp)
startMonitoring()
}
private func startMonitoring() {
networkMonitor.pathUpdateHandler = { [weak self] path in
guard let self else { return }
ping(callback: { isSuccess in
print("***** ping status:", isSuccess)
Task { @MainActor in
self.isConnectedToInternet = isSuccess
}
})
}
let queue = DispatchQueue(label: QueueLabel.networkMonitor)
networkMonitor.start(queue: queue)
}
func ping(
host: NWEndpoint.Host = "8.8.8.8",
port: NWEndpoint.Port = 53,
callback: @escaping ((Bool) -> Void)
) {
var didSendState = false
connection.stateUpdateHandler = {[weak self] state in
guard let self = self else { return }
guard !didSendState else {
if state != .cancelled {
cancel(connection)
}
return
}
switch state {
case .ready:
// State is ready now send data
let content = "Ping".data(using: .utf8)
let startTime = Date()
connection.send(content: content, completion: .contentProcessed {[weak self] error in
guard let self = self else { return }
if error != nil {
callback(false)
didSendState = true
cancel(connection)
} else {
print("Ping sent, waiting for response...")
connection.receiveMessage { [weak self] content, _, _, receiveError in
guard let self = self else { return }
if let receiveError {
print("Error receiving ping: \(receiveError.localizedDescription)")
callback(false)
} else if let content = content, String(data: content, encoding: .utf8) == "Ping" {
let roundTripTime = Date().timeIntervalSince(startTime)
print("Ping received! Round-trip time: \(roundTripTime) seconds")
callback(true)
} else {
print("Invalid response received")
callback(true)
}
didSendState = true
cancel(connection)
}
}
})
case .failed( _), .waiting( _), .cancelled:
didSendState = true
callback(false)
case .setup, .preparing:
// No callback because the ping has not yet succeeded or failed
break
@unknown default:
didSendState = true
callback(false)
// We don't know what this unknown default means, so cancel pings to be safe
cancel(connection)
}
}
connection.start(queue: .main)
}
func cancel(_ connection: NWConnection) {
connection.cancel()
}
}
Can anyone please help what I am doing wrong.
I want to add more cipher suites. I use NWConnection to make a connection.
Before I use sec_protocol_options_append_tls_ciphersuite method to add more cipher suites, I found that Apple provided 20 cipher suites shown in the client hello packet. But after I added three more cipher suites, I found that nothing changed, and still original 20 cipher suites shown in the client hello packet when I made a new connection.
The following is the code about connection. I want to add three more cipher suites: tls_ciphersuite_t.ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
tls_ciphersuite_t.ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
tls_ciphersuite_t.ECDHE_RSA_WITH_AES_256_CBC_SHA384
Can you give me some advice about how to add more cipher suites? Thanks.
By the way, I working on a MacOS app.
Xcode version: 16
MacOS version: 15.6
PLATFORM AND VERSION: iOS
Development environment: Xcode 15.4, macOS 14.4
PROBLEM iOS VERSION: iOS 17.2.1 ~ 18.1.1
DEVELOPMENT LANGUAGE: Object-C
Case-ID: 10969723
(Due to privacy concerns, I have hidden part of the URL and included the complete plain text in the email demo project with Case-ID: 10969723)
After our game was launched in Japan, a small number of Japanese users reported that they were unable to enter the game. After our investigation, we confirmed that the request under the yfy-api-oversea.xxxxxxxxxxxxxx.com domain name failed.
iOS NSURLSession API returns the following error:
Error Domain=NSURLErrorDomain Code=-1000 "無効なURL" UserInfo={_kCFStreamErrorCodeKey=22, NSUnderlyingError=0x3019e8030 {Error Domain=kCFErrorDomainCFNetwork Code=-1000 "(null)" UserInfo={_NSURLErrorNWPathKey=satisfied (Path is satisfied), interface: en0[802.11], ipv4, ipv6, dns, proxy, uses wifi, _kCFStreamErrorCodeKey=22, _kCFStreamErrorDomainKey=1}}, _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask .<7>, _NSURLErrorRelatedURLSessionTaskErrorKey=(
"LocalDataTask .<7>"
), NSLocalizedDescription=無効なURL, NSErrorFailingURLStringKey=https://yfy-api-oversea.xxxxxxxxxxxxxx.com/init/info?channel_code=jpxxxxxxxxxxxxxxios×tamp=1735012505&sign=1617e4cf88b58df2aa90a6b3985a8ac2&game_code=XXXXX, NSErrorFailingURLKey=https://yfy-api-oversea.xxxxxxxxxxxxxx.com/init/info?channel_code=jpxxxxxxxxxxxxxxios×tamp=1735012505&sign=1617e4cf88b58df2aa90a6b3985a8ac2&game_code=XXXXX, _kCFStreamErrorDomainKey=1}。
We have tried various methods but cannot reproduce this error (Code=-1000).
I can provide the following clues:
1、We have checked the server and confirmed that the request did not reach the server, but was intercepted by the iOS client and was not sent.
2、This problem does not seem to have much to do with the iOS system version. The system versions where the problem occurred are widely distributed: 17.2.1、17.7.1、17.5.1、17.6.1、17.7、18.0.1、18.1、18.1.1 e.g.
3、This problem seems to have nothing to do with the device model. The following models have experienced problems: iPhone16、iPhone 16 Pro、iPhone 14、iPhone 14 Plus、iPhone 14 Pro Max、iPhone 13、iPhone11 e.g.
4、By tracking the logs, some users who encountered the problem later recovered and the problem did not occur again(The user IP and iOS system restored by yourself have not changed). However, this problem persists for some users. Even if the iOS system is upgraded to the latest version, there are still problems.
5、The following two IPs are the IPs of users who encountered this problem (1.73.13.210, 153.252.131.136). But this problem seems to have nothing to do with IP. For some users who restored themselves, their IPs did not change, but the problem no longer occurred.
6、This problem seems to only occur in Japan. Mainland China, Taiwan, and Hong Kong have never encountered this situation.
7、It doesn't seem to have anything to do with GET requests. Another login request (https://yfy-api-oversea.xxxxxxxxxxxxxx.com/login/c/place) uses a POST request and will also encounter this error.
8、I wonder if it has something to do with the two symbol "-" in the domain name?
I checked Apple documentation and searched online, but couldn't find any more information. This problem cannot be reproduced either. Only technical requests can be initiated.
I provided a demo project (see email for Case-ID: 10969723)
Thanks.
Hello,
I understand that to discover and pair a device or accessory with Wi-Fi Aware, we can use either the DeviceDiscoveryUI or AccessorySetupKitUI frameworks. During the pairing process, both frameworks prompt the user to enter a pairing code. Is this step mandatory?
What alternatives exist for devices or accessories that don't have a way to communicate a pairing code to the user (for example, devices or accessories without a display or voice capability)?
Best regards,
Gishan
Topic:
App & System Services
SubTopic:
Networking
Tags:
iOS
Network
DeviceDiscoveryUI
AccessorySetupKit
Hi all,
I work on a smart product that, for setup, uses a captive portal to allow users to connect and configure the device.
It emits a WiFi network and runs a captive portal - an HTTP server operates at 10.0.0.1, and a DNS server responds to all requests with 10.0.0.1 to direct "any and all" request to the server.
When iOS devices connect, they send a request to captive.apple.com/hotspot-detect.html; if it returns success, that means they're on the internet; if not, the typical behavior in the past has been to assume you're connected to a captive portal and display what's being served.
I serve any requests to /hotspot-detect.html with my captive portal page (index.html).
This has worked reliably on iOS18 for a long time (user selects my products WiFi network, iOS detects portal and opens it).
But almost everyone who's now trying with iOS26 is having the "automatic pop up" behavior fail - usually it says "Error opening page - Hotspot login cannot open the page because the network connection was lost." However, if opening safari and navigating to any URL (or 10.0.0.1) the portal loads - it's just the iOS auto-detect and open that's not working
iOS18 always succeeds; iOS26 always fails.
Anybody have any idea what changes may have been introduced in iOS26 on this front, or anything I can do to help prompt or coax iOS26 into loading the portal? It typically starts reading, but then stops mid-read.
Topic:
App & System Services
SubTopic:
Networking