Post

Replies

Boosts

Views

Activity

Observers observe NEVPNStatusDidChange multiple times when loading NEPacketTunnelProvider more than once
I have an app that implements my own Packet Tunnel Provider, and to my knowledge everything I do is working as intended. However, I came across an issue with NEVPNStatusDidChange NotificationCentre observations when calling the following function multiple times:NETunnelProviderManager:loadAllFromPreferences(completionHandler:) From the documentation: You must call loadFromPreferences(completionHandler:): at least once before calling this method the first time after your app launches. As a result of this note, an early implementation I had took a very conservative approach; calling loadFromPreferences(completionHandler:): every time before operating on my NEPacketTunnelProvider. This was done by a helper function which was run as a precursor to any operation done to the manager, ensuring that the latest manager was being used every time. This looked something like:func myStartVPN() { 		loadHelper { (manager: NEPacketTunnelProvider, error: Error?) in /* handle errors */ startVPN(withManager: manager) } } When using this approach, I noticed that observers that look for NEVPNStatusDidChange events got triggered multiple times for these events, with the number of times it being triggered machine the number of times I called loadAllFromPreferences(). Chronologically speaking I was experiencing something along the lines of Appendix 1. As a result of this issue, my production equivalent of loadHelper(), above, only calls load once the first time a manager is requied, and then subsequent operations on the manager use a cached value - a bit like a standard lazy field. Obviously this is not a big issue as I have a working solution, however I haven't been able to work out what causes this behaviour - does anyone have any ideas? Could it be a general Swift/Objective C pitfall with KVO that I am not aware of? Could it be some sort of issue with NetworkExtension/my approach? (I'm thinking some references might not be being cleaned up every time I load?) Appendix 1 Previously set up NEPacketTunnelProvider* loadAllFromPreferences() followed by saveManager() Recieve NEVPNStatusDidChange - Disconnected loadAllFromPreferences() followed by startVPNTunnel() Recieve NEVPNStatusDidChange - Connecting x2 Recieve NEVPNStatusDidChange - Connected x2 loadAllFromPreferences() followed by stopVPNTunnel() Recieve NEVPNStatusDidChange - Disconnecting x3 Recieve NEVPNStatusDidChange - Disconnected x3 loadAllFromPreferences() followed by startVPNTunnel() Recieve NEVPNStatusDidChange - Connecting x4 Recieve NEVPNStatusDidChange - Connected x4 loadAllFromPreferences() followed by stopVPNTunnel() Recieve NEVPNStatusDidChange - Disconnecting x5 Recieve NEVPNStatusDidChange - Disconnected x5
7
0
2.1k
Nov ’20
CXProvider.reportNewIncomingVoIPPushPayload resulting in NSXPCConnectionInterrupted
We have just been granted access to the com.apple.developer.usernotifications.filtering entitlement, and are following the documented steps for handled E2EE VOIP notifications listed here: https://developer.apple.com/documentation/callkit/sending-end-to-end-encrypted-voip-calls 1 - A user initiates a VoIP call on their app. Their app then sends an encrypted VoIP call request to your server. We do exactly this, Alice calls Bob from her app, sending a notification to our servers. 2 - Your server sends the encrypted data to the receiver’s device using a regular remote notification. Be sure to set the apns-push-type header field to alert. We do exactly this, our server send on a notification to APNS with the apns-push-type header set to alert, destined for Bob. 3 - On the receiver’s device, the notification service extension processes the incoming notification and decrypts it. If it’s an incoming VoIP call, the extension calls reportNewIncomingVoIPPushPayload(_:completion:) to initiate the call. It then silences the push notification (see com.apple.developer.usernotifications.filtering). I try to do exactly this. The notification is received by the NSE on Bob's device, which decrypts it and then notices it is a VOIP call from Alice. It prepares a dictionaryPayload with the decrypted data and then calls reportNewIncomingVoIPPushPayload(_:) async throws. This throws an NSXPCConnectionInterrupted error, which when logged shows as below: Error Domain=NSCocoaErrorDomain Code=4097 "connection to service named com.apple.callkit.notificationserviceextension.voip" UserInfo={NSDebugDescription=connection to service named com.apple.callkit.notificationserviceextension.voip} The only difference I can see to the documentation is that I am working in an asynchronous context so am using the asynchronous version of the method, but I don't imagine this should cause an issue? I then supress the notification as documented and this works correctly. Does anyone have any ideas why I am getting this error when calling reportNewIncomingVoIPPushPayload(_:) async throws?
1
0
451
Jan ’25