NWTCPConnection hasbetterpath has been observed as soon as connecting VPN with new network

Hi. I am developing VPN app with NWTCPConnection.


I have implemented switching network ( from WiFi to LTE or LTE to Wifi ) and upgrade connections or create new connections as Apple suggested.


In Apple document for hasBetterPath property, "Evaluates to true if a new connection attempt to the remote endpoint would use a different and preferred path. If the current connection is not viable, this can be used as a hint to try again. If the current connection is still viable, this can indicate that the system or user has a preference for the newly available network path. For example, if the connection is established over a cellular data network and Wi-Fi is now available, then the connection has a better path available and this property is set to true. Use the initWithUpgradeForConnection:initializer to create a new connection with the same parameters as the current connection. Use Key-Value Observing to watch this property".


As Apple documented, hasBetterPath has been observed when switching network or turn off/on network. However, hasBetterPath sometimes has been observed as soon as connecting new network ( new network should be LTE or WiFi ).

For example, if I switch network from LTE to WiFi, I observe "hasBetterPath" which is expected. Then I do upgrade and create new connection. ( we also have tried to create new connection and new tunnel without upgrading. Both are resulting same )

Normally, new connection successfully connect to VPN with new network and I do not observe "hasBetterPath" after connecting if there is no network changes.


However, in some networks ( Vodafone LTE in Europe or WiFi ), I have observed "hasBetterPath" as soon as connecting to VPN with new network ( Normally it occurs within 1 sec after observing “state” and connection.state = .connected ).

If I handle this weird "hasBetterPath" case and upgrade connection again, device's network goes down ( WiFi or LTE icon shows, but can not browse any website with Safari ). Once device’s network has been down, disconnect VPN ( terminate VPN process ) is the only way to come network back.


Moreover, if I do not handle this weird "hasBetterPath" case and keep staying current connection, I get no observation anymore ( NSKeyValueChangeKey : state, isViable and hasBetterPath ) even though I have added those observations.


Our workaround for this weird “hasBetterPath” case, App has to terminate VPN extension (Disconnect) and create new one. Then connect VPN with same settings. If “hasBetterPath” shows up again as soon as connecting to VPN ( Normally within 1 sec ), App keeps terminating extension and creating new connection until we do not get “hasBetterPath” with current network.


This workaround seems to work if App is in foreground; however, we are not able to launch VPN extension when App is in background and terminate VPN extension.


Please let me know if you need more information about unexpected “hasBetterPath” issue.


Thank you.



//// more update on Code level ///////

This hasBetterPath issue doesn't even need to change network. We have observed this issue easily on iPhone6Plus ( IOS 11.3 and 11.4 )

What I observed is that sometimes "hasBetterPath" has been observed as soon as connection gets connected even though no network change.

Moreover, If I upgrade connection or create new connection with new tunnel after getting this hasBetterPath, device's network goes down ( WiFi or LTE icon shows, but can not browse any website with Safari ).

Once device’s network has been down, disconnect VPN ( terminate VPN process ) is the only way to come network back.

Moreover, if I do not handle this weird ( hasBetterPath right after connection gets connected state ) "hasBetterPath" case and keep current connection, I get no observation anymore ( NSKeyValueChangeKey : state, isViable and hasBetterPath ) even though I have added those observations.


STEPS TO REPRODUCE

1. Try to connect to VPN ( SSL VPN with TCPConnection )

2. We Observed key value "state" of our NWTCPConnection instance and connection state changed to .connected.

3. After processing PPP negotiation on the connection, then we call completionHandler from startTunnel(options: [String : NSObject]?, completionHandler: @escaping (Error?) -> Void).

4. Then we observed "hasBetterPath" even though no network change. Normally we do not get this weird hasBetterPath after calling completionHandler from startTunnel(options: [String : NSObject]?, completionHandler: @escaping (Error?) -> Void)

Replies

I’m not sure what’s going on here. At a minimum this seems problematic:

Moreover, if I do not handle this weird

hasBetterPath
case and keep staying current connection, I get no observation anymore (
NSKeyValueChangeKey : state
,
isViable
and
hasBetterPath
) even though I have added those observations.

It should be safe to ignore

hasBetterPath
; it’s intended as an optimisation opportunity, not to indicate that the previous path has broken.

Given that, my recommendation is that you file a bug report about this. Please post your bug number, just for the record.

You seem to have already found your own workaround for this, albeit a pretty ugly one. If you’d like help looking for a less ugly workaround, you should open up a DTS tech support incident so that I can take a proper look at this.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Thank you for replying Eskimo.


We already have fixed this issue with better workaround which is similar to your suggestion.


As you suggested, we are not disconnecting or kill VPN process when we get "hasBetterPath" in current network.


Then we disconnect VPN and create new connection when we get has better path in new network.


It seems to work fine so far.


By the way, We still do not know why iPhone6Plus has received "hasBetterPath" in current network almost every time we connect VPN via WiFi. ( iPhone5, iPodTouch 4th Gen, iPadPro, iPhone7 .. do not have this issue under same environment ).

This happens not only for my iPhone6Plus, but also our customer's iPhone6Plus has this issue.



Thank you

We already have reported this bug ( iPhone6Plus has easily received hasBetterPath in current network ) via bug-report as well.


Bug report

42138240 : NWTCPConnection hasbetterpath has been observed as soon as connecting VPN with new network

and DTS ticket

Case ID: 694957769

Thank you

I was wondering if this issue was ever resolved. Currently we are working on a VPN app using "TunnelKit" and we are seeing delayed reconnects with the exact same hasBetterPath related messages.

All code is opensource. I don't have a precise reproduction flow yet though.