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?
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
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