Post

Replies

Boosts

Views

Activity

Reply to Local Push Connectivity - Unreliable Connection
@DTS Engineer Hi Kevin! I am looking to test the sample project and will get back to you on that. Ruling an issue out, how frequently is the server emitting its keep-alive? One slightly less obvious detail here is that in a naive implementation where one device emits a keep-alive "every 5s" and the other requires a keep-alive "every 5s", you can create a situation where what you're actually depending on/measuring is the consistency of latency between the devices, NOT the reliability of the connection itself. The server emits a keep-alive every 1s. Every time the app extension receives an event/keep-alive, it stores the last system time indicating when we last received communication. Then every 12s (sorry I forgot we updated from 5 -> 12s), we check "Has the extension received any communication within the previous 12s." So I do not believe we would run into the scenario you are describing. What component actually sent that push? More specifically: Is your push provider extension still running, as it's the component that sent the push? Did some other component/mechanism send that push based on detecting that the extension was not longer running? The push notifications are sent by our app extension, which is a class conforming to NEAppPushProvider. With the problem we are seeing, the extension is alive the entire time, as we also log when it stops for any reason. The problem is the extension, which has a TCP connection with the server, will fail to receive any of the events/keep-alives, which are sent every 1s. Once it hits >12s with no data, it terminates the connection and reconnects. This entire time, the extension is still alive. The strange part is on my busy home network on a TP-Link router, this logic will never fail. If tested on an identical router with only the server and phone, it will start failing after 1min of the phone being locked. The article "Maintaining a Reliable Network Connection" explicitly states that you should be using the Network framework: Yes, we are using the Network framework. Our implementation uses Swift-NIO Transport Services (NIOTSConnectionBootstrap), which is Apple's official bridge that provides Swift-NIO's API while using the Network framework underneath for the actual networking operations. Specifically: We use NIOTSConnectionBootstrap which leverages the Network framework We directly configure Network framework parameters like NWParameters, NWProtocolTCP.Options, and NWProtocolTLS.Options We use NWEndpoint.url() for endpoint creation From what we understand, Swift-NIO Transport Services is Apple's recommended approach when you need Network framework's reliability and system integration but also require the advanced features that Swift-NIO provides (like our SSE parsing capabilities). So while we're using Swift-NIO's API for convenience, the Network framework is handling all the underlying transport operations as recommended. And what happened? What did both sides of the connection see? And have you tried monitoring traffic on both the WiFi and Ethernet links? When doing an ethernet link capture of the server, we can reliably see the keep-alives getting sent every 1s. When doing a monitor mode capture, we know the keep-alives are being sent because the app is parsing them, counting them, and logging the count every 60s. However, we were unable to see the packets for these. Under the assumption that it was due to the size and/or encryption of the connection. While I will test the sample project, I think it is still relevant to understand: What does the phone's Wi-Fi radio do when the device is locked? Given we only have this problem when the device is locked and not connected to power. You previously mentioned that this framework tends to only work properly on "high quality networks." Could you elaborate on what makes a high quality network?
Jul ’25
Reply to Local Push Connectivity - Unreliable Connection
Hi @DTS Engineer ! As we've taken some time to deep-dive into this, we're running into a dead-end here and are hoping to seek further guidance. To clarify, when our test iPhones (iPhone 15 on iOS 18.5, and iPhone 16 Pro on iOS 18.4) are locked and the app is backgrounded, the app extension will stop receiving the keep-alive messages over the SSE connection. Given our solution supports first responders, it is critical that the connection is stable to allow critical notifications to arrive as quick as possible. If the app does not receive the keep-alives from our local server within 5s, it tears down the connection and establishes a new one. While testing at home on an Eero router and TP Link Deco XE75 Pro, I have been unable to reproduce any issues with it. I will leave the phone, unplugged, with the app running in the background and it works as expected. Given this, we determined our issue was likely with the vendor who supplies our customer routers, which are Cradlepoint IBR900s. We have been working with the Cradlepoint engineering team to investigate a possible root cause. However, to help debug, Cradlepoint also purchased a TP-Link XE75 Pro in their lab to test with, along with our local server and they are able to replicate the issue within 1min of locking their iPhone. I ended up changing my wi-fi name to kick all devices off the network except for my iPhone 16 Pro (cellular and wifi connections) and the server connected via LAN to the TP-Link. Now, every time I lock the phone, within 1min it sends a push notification indicating it lost connection and then immediately reconnects. Given this, it seems like the behavior is not unique to a particular router after all, but has something to do with the iPhone's power saving mechanism given it's only when the phone is locked and not on power. We have tested with iPhone 13 on iOS 16.7 (wifi only and no other apps), iPhone 15 on iOS 18.5 (wifi only and no other apps), iPhone 16 Pro on iOS 18.5 (cellular, many apps, and wifi assist turned on/off), and iPhone 14 Pro on iOS 18.5 (cellular, many apps, and wifi assist turned on/off). I am suspecting that the small keep-alive packets going from the server to the phone every second are too small to keep the phone from powering down the wifi radio, yet there is some other device, or traffic, on my home network that presumably keeps the phones active that has no other applications installed but our app from testflight. For our implementation, we were originally using URLSession to establish the connection and parse the SSE events, but have since moved to a custom solution leveraging Apple's Swift-NIO library. Though SSE is uni-directional connection, we also tried enabling keep-alives from the phone, with the thought that it would help generate traffic to keep the phone active. Do you have any ideas as to what might be keeping the wifi radio active when the phone is locked? Do you have any information around how the phone's power saving mechanism works? You seemed to indicate before that this framework tends to only work properly on "high quality networks." Could you elaborate on what makes a high quality network? Are there specific network settings recommended by Apple for this framework to work right? Do you know of a router that you have tested with in the lab that works reliably? Do you suggest we open up a code-level support request via our developer account to get further assistance on this? Is there anything else you haven't already mentioned that might be relevant here with our setup? Thank you again for all of your support on this. Our partners at Cradlepoint are eager to collaborate with our company to find a solution to this as well, so please let us know if there is any other information we can provide on this.
Jul ’25