I am looking for a lightweight server that can run inside an app.
The key requirement is that it must support local IP communication over HTTPS.
I have searched Google and found several frameworks, but as far as I know, support for HTTPS in this environment has been discontinued or is no longer available.
If anyone knows a solution that meets these criteria, I would greatly appreciate your guidance.
Thank you in advance!😀
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.
Post
Replies
Boosts
Views
Activity
I recently encountered an issue with incorrect progress reporting and timeout behavior when using NSURLSession to upload small data buffers.
Background
In my app, I split a large video file into smaller 1MB chunk files for upload. This approach facilitates error retries and concurrent uploads. Additionally, I monitor the upload speed for each request, and if the speed is too slow, I switch CDNs to re-upload the chunk.
Issue Description
When using NSURLSessionUploadTask or NSURLSessionDataTask to upload a 1MB HTTP body, I noticed that the progress callbacks are not accurate. I rely on the following callback to track progress:
- (void)URLSession:task:didSendBodyData:totalBytesSent:totalBytesExpectedToSend:
Even when using Network Link Conditioner to restrict bandwidth to a very low level, this callback reports identical values for totalBytesSent and totalBytesExpectedToSend right at the start of the request, indicating 100% upload progress. However, through network traffic inspection, I observed that the upload continues slowly and is far from complete.
Additionally, I noticed that even though the upload is still ongoing, the request times out after the duration specified in - NSURLSessionConfiguration.timeoutIntervalForRequest. According to the documentation:
"The request timeout interval controls how long (in seconds) a task should wait for additional data to arrive before giving up. The timer associated with this value is reset whenever new data arrives."
This behavior suggests that the timeout timer is not reset as the document says during slow uploads, likely because didSendBodyData is not updating as expected.
Consequently, the timer expires prematurely, causing 1MB chunks to frequently timeout under slow network conditions. This also prevents me from accurately calculating the real-time upload speed, making it impossible to implement my CDN switching strategy.
Some Investigation
I have found discussions on this forum regarding similar issues. Apple engineers mentioned that upload progress is reported based on the size of data written to the local buffer rather than the actual amount of data transmitted over the network. This can indeed explain the behaviour mentioned above:
https://developer.apple.com/forums/thread/63548
https://developer.apple.com/forums/thread/746523
Interestingly, I also noticed that progress reporting works correctly when uploading to some certain servers, which I suspect is related to the TCP receive window size configured on those servers. For example:
Accurate progress: https://www.w3schools.com
Inaccurate progress: Most servers, like https://developer.apple.com
I created a sample project to demostrate the progress & timeout issues and different behaviours when uploading to some servers:
https://github.com/Naituw/NSURLSessionUploadProgressTest
Questions
Is there any way to resolve or workaround this issue?
Like adjusting the size of the local send buffer?
or configuring NSURLSession to report progress based on acknowledged TCP packets instead of buffer writes?
Or are there any alternative solutions for implementing more accurate timeout mechanisms and monitoring real-time upload speed?
I have some concerns related to shortening the lifetime of certificates, as per
https://support.apple.com/en-gb/102028
Does this apply to Private CA root certificates?
And if yes:
does it apply if I use ATS and higher level API like URLSession
does it apply it I carry my root CA cert in my app payload and use low level libraries without ATS support?
Hi,
I am working on a use case where I want to read the wifi signal strength data in the terms of RSSI (Received Signal Strength Indicator) values (or) any other way of representation. when my iPhone is connected to the wifi and Move around the house.
Is this use case possible ? If yes, what are all the entitlements that I have to obtain?
My code makes an iPhone use the CBCentralManager to talk to devices peripherals over core bluetooth.
After attempting a connect to a peripheral device, I get a didConnect callback on CBCentralManagerDelegate.
After this I initiate discovery of services using:
peripheral.discoverServices([CBUUID(nsuuid: serviceUUID)])
Since I am only interested in discovering my service of interest and not the others to speed up time to the actual sending of data.
This also gives me the didDiscoverServices callback without error prints in which I do the following:
guard let services = peripheral.services, !services.isEmpty else {
print("Empty services")
centralManager.cancelPeripheralConnection(peripheral)
return
}
And for next steps
if let serviceOfInterest = services.first(where: {$0.uuid == CBUUID(nsuuid: serviceUUID)}) { //double check for service we want
initiateDiscoverCharacteristics(peripheral: peripheral, service: serviceOfInterest)
}
Below is what initiateDiscoverCharacteristics() does. I basically only tries to discover certain characteristics of the selected service:
peripheral.discoverCharacteristics(
[CBUUID(nsuuid: readUUID),
CBUUID(nsuuid: writeUUID)],
for: serviceOfInterest)
For this also we get the didDiscoverCharacteristicsFor callback without error prints.
Here in this callback however we were not doing the serviceOfInterest check to see that we are getting the callback for the service we expect, since our understanding was that we will get didDiscoverCharacteristicsFor callback for the characteristics on the serviceOfInterest because that is what peripheral.discoverCharacteristics() was initiated for.
When we go ahead to write some data/subscribe for notify/read data we have 2 guard statements for services and characteristics of a particular service.
The first guard below passes:
if(peripheral.services == nil) {
print("services yet to be discovered \(peripheral.identifier.uuidString)")
return
}
However the second guard below fails:
let serviceOfInterest = peripheral.services?.first(where: {$0.uuid == CBUUID(nsuuid: serviceUUID})
if((serviceOfInterest?.characteristics == nil) || (serviceOfInterest?.characteristics == [])) {
print("characteristics yet to be discovered \(peripheral.identifier.uuidString)")
return
}
First of all, does the iPhone go ahead and discover other characteristics and services separately even when we explicitly mention the service and the characteristics it should discover?
Now if you say yes and that it maybe the reason of our bug because we didn't do a check for serviceOfInterest in didDiscoverCharacteristicsFor callback, then I have another question.
Why don't we get a second/third print in didDiscoverCharacteristicsFor callback signifying that more characteristics were discovered?
The peripheral device just disconnects after a set timeout (peripheral device used in our testing does this if we are not communicating with it for a certain amount of time).
This issue is extremely rare. We have seen it only twice in our customer base. Both the instances were on the same iPhone 15 Pro. Once a few months back and once recently. Currently, this iPhone is having iOS version 18.1.1 running on it.
I am trying to connect an iPhone 16 (iOS 18.3) to a Wi-Fi device with the SSID "DIRECT-DR_6930_KP201128", but every time, without being able to enter the Wi-Fi password, the message "Unable to join the network 'DIRECT-DR_6930_KP201128'" is displayed. Below are the system logs from the connection failure. Could you please tell me the cause of the connection failure?
By the way, an iPhone SE 2nd (iOS 18.2.1) can connect to the same Wi-Fi device without any issues.
System Logs:
・Jan 31 19:18:14 900-iPhone-16-docomo Preferences(WiFiKit)[351] : {ASSOC-} association finished for DIRECT-DR_6930_KP201128 - success 0
・Jan 31 19:18:14 900-iPhone-16-docomo runningboardd(RunningBoard)[33] : Assertion 33-351-4412 (target:[app<com.apple.Preferences(DE1AB487-615D-473C-A8D6-EAEF07337B18)>:351]) will be created as inactive as start-time-defining assertions exist
・Jan 31 19:18:14 900-iPhone-16-docomo Preferences(WiFiKit)[351] : association failure: (error Error Domain=com.apple.wifikit.error Code=12 "Unknown Error" UserInfo={NSDebugDescription=Unknown Error, NSUnderlyingError=0x303307660 {Error Domain=com.apple.corewifi.error.wifid Code=-3938 "(null)"}})
・Jan 31 19:18:14 900-iPhone-16-docomo Preferences(WiFiKit)[351] : dismissing credentials view controller for DIRECT-DR_6930_KP201128
Hi,
We are working on an app that communicates over a UDP connection on the local network. In our testing, we have a Python UDP client running on the same network, which responds when we send a message to a broadcast IP (255.255.255.255). This setup works as expected on an iOS 15 device.
However, when we test the same scenario on an iOS 18 device, the UDP communication doesn't seem to reach the Python UDP client. We've verified that the UDP client and the iOS device are on the same network, and the Python client is responding correctly.
Has Apple introduced any restrictions or changes regarding UDP broadcast behavior in iOS 18? Is broadcasting to 255.255.255.255 still supported, or has this functionality been limited in recent iOS versions?
The Download is not Working in the background mode even if i entitled all the necessary permission for the application it only works when the app is connected to xcode due to xcode keep the session alive but if try after removing the connection from the xcode the app not able to keep the download after 45 sec what may be the reason
my code
var request = URLRequest(url: url)
request.httpMethod = "GET"
let bearerToken = SyncManager.accessToken
request.setValue("Bearer \(bearerToken)", forHTTPHeaderField: "Authorization")
let uniqueIdentifier = "\(self.vdmsId)_\(UUID().uuidString)"
backgroundTaskID = UIApplication.shared.beginBackgroundTask { [weak self] in
if let taskID = self?.backgroundTaskID {
UIApplication.shared.endBackgroundTask(taskID)
self?.backgroundTaskID = .invalid
}
}
let CursessionConfig = URLSessionConfiguration.background(withIdentifier: uniqueIdentifier)
CursessionConfig.isDiscretionary = false
CursessionConfig.sessionSendsLaunchEvents = true
CursessionConfig.shouldUseExtendedBackgroundIdleMode = true
// Set timeout intervals
CursessionConfig.timeoutIntervalForResource = 24 * 60 * 60 // 24 hours
CursessionConfig.timeoutIntervalForRequest = 60 * 60 // 1 hour
let Cursession = URLSession(configuration: CursessionConfig, delegate: self, delegateQueue: nil)
self.CurInstanceSession = Cursession
self.session = Cursession
if SyncManager.activeSessions == nil {
SyncManager.activeSessions = [URLSession]()
}
SyncManager.activeSessions?.append(Cursession)
self.downloadCompletionHandler = completion
let CurdownloadTask = Cursession.downloadTask(with: request)
CurdownloadTask.resume()
is there any solutions and i have entitled all the neccessary permisssions like background fetch, process and i also tries with the UIApplication.shared.beginBackgroundTask but after 45 sec it gets terminated all of the suden what may be the issue
Hi,
I have been reviewing some previous discussions around networking in macOS, and I’d like to clarify my understanding of the differences between the kernel-space network stack and user-space network stack and validate this understanding based on the information shared in earlier threads.
I’m also curious about how these differences impact macOS applications, particularly those requiring maintaining many simultaneous network connections.
Understanding Kernel-Space vs User-Space Network Stack
Kernel-Space Network Stack (BSD Sockets):
The kernel-space networking stack refers to the traditional networking layer that runs in the kernel and handles network communication via BSD sockets. This stack is lower-level and interacts directly with the operating system's networking drivers and hardware. All network connections managed through this stack require a socket (essentially a file descriptor) to be opened, which places limits on the number of file descriptors that can be used (for example, the default 64K limit for sockets). The kernel network stack is traditionally used on macOS (and other UNIX-based systems) for networking tasks, such as when you use system APIs like BSD sockets.
User-Space Network Stack (Network Framework): The user-space network stack in macOS (via the Network framework) allows applications to handle networking tasks without directly using the kernel. This provides more flexibility and performance benefits for certain types of network operations, as the networking stack is managed in user space rather than kernel space. This approach reduces overhead and allows more control over networking configurations. In theory, with user-space networking, the application wouldn't be bound by kernel-level socket limits, and it could handle many more simultaneous connections efficiently.
In previous posts on that thread, Quinn mentioned that the Network framework in macOS can rely on the user-space stack (by default) for network operations, but there are still cases where macOS falls back to using the kernel stack (i.e., BSD sockets) under certain conditions. One key example is when the built-in firewall is enabled. This prevents user-space networking from functioning as expected, and the system defaults to using the kernel's BSD sockets for network communication.
In the same discussion, it was also highlighted that NECP (Network Extension Control Plane) could place further limitations on user-space networking, and eventually, systems may run into issues like ENOSPC errors due to excessive simultaneous network flows. This suggests that while user-space networking can offer more flexibility, it's not immune to limits imposed by other system resources or configurations.
Given the information above, I wanted to confirm:
Is the above understanding correct and does the macOS Network framework still use the user-space networking stack in macOS 14 and beyond?
Under what conditions would the system fall back to using the kernel stack (BSD sockets) instead of the user-space stack? For example, does enabling the firewall still disable user-space networking?
What is the practical impact of this fallback on applications that require many simultaneous network connections? Specifically, are there any limitations like the 64K socket limit that developers should be aware of when the system uses the user space stack, and what are the best practices to manage large numbers of connections?
I have an issue that causes multiple instances of the push provider to be initialized. And I'd like to ask you what could trigger the instantiation NEAppPushProvider subclass. It seems like it's being triggered excessively. If there's documentation that I have overlooked then just show it to me and I'll be on my way.
Here's the details. But really all I want to know is why is my subclass for NEAppPushProvider keeps getting initialized. If you can answer me that than maybe all these details don't really matter but here they are.
Here's why I believe there's multiple push provider. I see logs for my push provider initializing but I don't see it de-initializing. I also see redundant logs showing multiple instances trying to log into my server. Each time it initializes, an additional log is added for trying to log into my server.
In the app, the system saves it's configuration shortly after initialization, after saving and loading the push configuration, the app doesn't touch config.
Meanwhile in the extension, after 8 or so hours, the extension starts creating a new instance of the push provider. Then a few hours later it does it again. And again. Until the watch dog kills us for wasting too much CPU.
Normally on a fresh install, I'll observe turning off the wifi to call stop on the push provider and later have the push provider de-initialize.
The extension maintains a socket connection to the server, the server can send it messages to display push notifications. The software runs on hospital networks, which will not have access to the internet. It seems like the connection to the server is stable from the logs. I don't detect any disconnections. I'll check with the server to confirm.
In the app I call removeFromPreferences to clear out any extensions before logging in/saving push configurations. And I call saveToPreferences on the NEAppPushManager. I do this to make sure I don't have more than one push configuration saved at one time. I also have many logs looking out for this. I used the sample code from apple as the basis of the my own Push Manager. I can post code if you deem it necessary.
Hope to here from you soon. Thank you.
I added a Content Filter to my app, and when running it in Xcode (Debug/Release), I get the expected permission prompt:
"Would like to filter network content (Allow / Don't Allow)".
However, when I install the app via TestFlight, this prompt doesn’t appear at all, and the feature doesn’t work.
Is there a special configuration required for TestFlight? Has anyone encountered this issue before?
Thanks!
In our iOS networking related app for the app store (with network extension using packet tunnel provider), we are supposed to read the list of nameservers for the network. We use res_ninit function.
This function returns only 3 items (but in reality the network has more dns servers. In my case 5. Some ipv4 and some ipv6)
Looking at the header file at iOS 18.2 -> user/include/resolve.h, it shows that the __res_state struct has a maximum limit of 3 for the nsaddr_list array.
It seems that the reason the res_ninit function returns only 3 values is because of this. For our code to work correctly, it needs to know all the dns servers, but we only get partial results.
Is there any other api that can get us all the dns servers ?
I am unable to apply for Multicast Entitlement at https://developer.apple.com/contact/request/networking-multicast
The reason for this is unclear. I have paid for a developer account and believe I'm up to date with all agreements.
Hi all,
I’m developing a watchOS app that uses a WebSocket API to process voice audio. However, I keep encountering this error when trying to establish the connection:
nw_endpoint_flow_failed_with_error [C1 <server URL>:443 failed parent-flow (unsatisfied (Path was denied by NECP policy), interface: ipsec2, ipv4, ipv6, proxy)] already failing, returning
I’ve read Technical Note TN3135, which outlines an exception for audio streaming apps. My app is an audio streaming app, and I’ve already added background audio mode to the app’s capabilities. However, I’m not sure what else is required to meet the exception described in TN3135.
Questions
How do I meet the exception outlined in TN3135 for WebSocket audio streaming on watchOS?
Does NECP enforce additional restrictions even with background audio enabled, and how can I address this?
Any guidance or examples of implementing WebSocket audio streaming on watchOS would be greatly appreciated.
Thanks!
Hi everyone,
I’m working with the DNSServiceGetAddrInfo API and came across the following statement in the documentation:
If the call succeeds then it initializes the DNSServiceRef, returns kDNSServiceErr_NoError, and the query begins and will last indefinitely until the client terminates the query by passing this DNSServiceRef to DNSServiceRefDeallocate(_)
I’m trying to understand exactly what this means in practice. Specifically, after receiving a response with kDNSServiceFlagsMoreComing, being set to 0 does it imply that the OS itself continues querying the DNS periodically or indefinitely, even after we've already received some results? Or does it only continue fetching additional results related to the initial query until we explicitly terminate it?
Any clarification on the behavior of this query would be greatly appreciated!
Thanks in advance!
Hello, we have noticed a crash in BigSur 11.7.10, 20G1427 libdispatch:
Crashed Thread: 1 Dispatch queue: com.apple.network.connections
Exception Type: EXC_BAD_INSTRUCTION (SIGILL)
Exception Codes: 0x0000000000000001, 0x0000000000000000
Exception Note: EXC_CORPSE_NOTIFY
Termination Signal: Illegal instruction: 4
Termination Reason: Namespace SIGNAL, Code 0x4
Terminating Process: exc handler [94088]
Application Specific Information:
BUG IN CLIENT OF LIBDISPATCH: Release of a suspended object
Thread 0:
0 libsystem_kernel.dylib 0x00007fff20488aea __sigsuspend_nocancel + 10
1 libdispatch.dylib 0x00007fff2031f4e1 _dispatch_sigsuspend + 36
2 libdispatch.dylib 0x00007fff2031f4bd _dispatch_sig_thread + 53
Thread 1 Crashed:: Dispatch queue: com.apple.network.connections
0 libdispatch.dylib 0x00007fff2033cc35 _dispatch_queue_xref_dispose.cold.1 + 24
1 libdispatch.dylib 0x00007fff20313808 _dispatch_queue_xref_dispose + 50
2 libdispatch.dylib 0x00007fff2030e2eb -[OS_dispatch_source _xref_dispose] + 17
3 libnetwork.dylib 0x00007fff24255999 __nw_queue_context_create_source_block_invoke + 41
4 libdispatch.dylib 0x00007fff2030d623 _dispatch_call_block_and_release + 12
5 libdispatch.dylib 0x00007fff2030e806 _dispatch_client_callout + 8
6 libdispatch.dylib 0x00007fff203111b0 _dispatch_continuation_pop + 423
7 libdispatch.dylib 0x00007fff203211f4 _dispatch_source_invoke + 1181
8 libdispatch.dylib 0x00007fff20316318 _dispatch_workloop_invoke + 1784
9 libdispatch.dylib 0x00007fff2031ec0d _dispatch_workloop_worker_thread + 811
10 libsystem_pthread.dylib 0x00007fff204b545d _pthread_wqthread + 314
11 libsystem_pthread.dylib 0x00007fff204b442f start_wqthread + 15
I have seen similar crashes in the forum, but none from com.apple.network.connections queue.
Should we raise a ticket or is this something that was fixed in newer OS versions?
Thanks!
Jakub
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've implemented a custom system extension VPN for macOS using Packet Tunnel Provider.
The VPN is configured with on-demand, and a rule to always connect whenever there's traffic:
onDemandRules = [NEOnDemandRuleConnect()]
As for the tunnel's settings (at the Packet Tunnel Provider), I've configured a split tunnel, so some routes are excluded from the tunnel.
Now I have the following scenario:
The VPN is connected
The Mac enters sleep
The sleep() function is called (at my Packet Tunnel Provider)
The Mac briefly awakes to check emails/push notifications/etc. This traffic is excluded from the tunnel.
What is the expected behavior here? Should the wake function be called because of the on-demand rule? Or should the VPN remain asleep because this traffic is excluded from the tunnel?
Hi,
I would like to confirm if the matchDomains property in NERelayManager operates exclusively at the application layer. Specifically, it seems that adding IPv4 addresses or IPv4 CIDR blocks to the matchDomains list does not work, as the relay manager appears unable to match them.
Relay Configuration
For example, I tried adding the following IPv4 patterns to the matchDomains list:
11.22.33.44
11.22..
11.22.*
In this configuration, I expected traffic to be routed to the relay server as defined by the matchDomains entries. However, the relay manager did not handle these IPv4 patterns as anticipated.
On the other hand, when using only the excludedDomains property, the desired IPv4 traffic is successfully routed to the relay server as expected.
Purpose of Forwarding IPv4 to the Relay Server
The primary reason for forwarding IPv4 traffic to the relay server is to address cases where certain applications—such as those developed with Flutter or React Native—use their own custom network stack. These custom network stacks often do not respect the relay configuration. As a result, even when these applications use domains that are matched by the relay manager’s matchDomains, their TCP connections to DNS-resolved IPv4 addresses bypass the relay server and connect directly to the IPv4 server.
This behavior makes it critical to enable IPv4 matching to ensure all traffic, regardless of the application’s network stack implementation, is routed through the relay server.
Questions
Can IPv4 addresses or IPv4 CIDR blocks be used with matchDomains?
If not, is there an alternative method to enable IPv4 matching while keeping matchDomains enabled?
Thank you for your assistance.
Hi,
I would like to confirm whether the matchDomains property in NERelayManager operates strictly at the Application Layer. Specifically, it seems that adding IPv4 addresses or IPv4 CIDR blocks to the matchDomains list does not work, as the relay manager appears unable to match them.
For example, I tried adding the following IPv4 patterns to the matchDomains list:
11.22.33.44
11.22..
11.22.*
However, these IPv4 addresses or patterns are not routed through my Relay server.
Additionally, I have observed that when using only the excludedDomains property, the desired IPv4 traffic is correctly routed to the relay server as expected.
My question is: Can IPv4 addresses or IPv4 CIDR ranges work with matchDomains? If not, is there an alternative approach to enable IPv4 matching while matchDomains is active?