From 81901b5dae6829054bbe00cd956e6fbb414b4756 Mon Sep 17 00:00:00 2001 From: Nate Brown Date: Tue, 23 May 2023 17:31:07 -0500 Subject: [PATCH] Rework the ios startup flow slightly to avoid crashing on ios 16.5 (#132) --- .../PacketTunnelProvider.swift | 25 ++++--------------- ios/NebulaNetworkExtension/Site.swift | 2 +- ios/Runner/Sites.swift | 10 ++++---- 3 files changed, 11 insertions(+), 26 deletions(-) diff --git a/ios/NebulaNetworkExtension/PacketTunnelProvider.swift b/ios/NebulaNetworkExtension/PacketTunnelProvider.swift index 9f3ae8c..61e131a 100644 --- a/ios/NebulaNetworkExtension/PacketTunnelProvider.swift +++ b/ios/NebulaNetworkExtension/PacketTunnelProvider.swift @@ -13,15 +13,12 @@ class PacketTunnelProvider: NEPacketTunnelProvider { private var didSleep = false private var cachedRouteDescription: String? - // This is the system completionHandler, only set when we expect the UI to ask us to actually start so that errors can flow back to the UI - private var startCompleter: ((Error?) -> Void)? - - override func startTunnel(options: [String : NSObject]?, completionHandler: @escaping (Error?) -> Void) { + override func startTunnel(options: [String : NSObject]?, completionHandler: @escaping (Error?) -> Void) { // There is currently no way to get initialization errors back to the UI via completionHandler here // `expectStart` is sent only via the UI which means we should wait for the real start command which has another completion handler the UI can intercept - // In the end we need to call this completionHandler to inform the system of our state if options?["expectStart"] != nil { - startCompleter = completionHandler + // The system completion handler must be called before IPC will work + completionHandler(nil) return } @@ -175,19 +172,6 @@ class PacketTunnelProvider: NEPacketTunnelProvider { // start command has special treatment due to needing to call two completers if call.command == "start" { self.start() { error in - // Notify the system of our start result - if self.startCompleter != nil { - if error == nil { - // Clean boot, no errors - self.startCompleter!(nil) - - } else { - // We encountered an error, we can just pass NSError() here since ios throws it away - // But we will provide it in the event we can intercept the error without doing this workaround sometime in the future - self.startCompleter!(error!.localizedDescription) - } - } - // Notify the UI if we have a completionHandler if completionHandler != nil { if error == nil { @@ -195,8 +179,9 @@ class PacketTunnelProvider: NEPacketTunnelProvider { completionHandler!(try? JSONEncoder().encode(IPCResponse.init(type: .success, message: nil))) } else { - // Error response has + // We failed, notify and shutdown completionHandler!(try? JSONEncoder().encode(IPCResponse.init(type: .error, message: JSON(error!.localizedDescription)))) + self.cancelTunnelWithError(error) } } } diff --git a/ios/NebulaNetworkExtension/Site.swift b/ios/NebulaNetworkExtension/Site.swift index 0a5653d..5708850 100644 --- a/ios/NebulaNetworkExtension/Site.swift +++ b/ios/NebulaNetworkExtension/Site.swift @@ -97,7 +97,7 @@ struct CertificateValidity: Codable { let statusMap: Dictionary = [ NEVPNStatus.invalid: false, NEVPNStatus.disconnected: false, - NEVPNStatus.connecting: true, + NEVPNStatus.connecting: false, NEVPNStatus.connected: true, NEVPNStatus.reasserting: true, NEVPNStatus.disconnecting: true, diff --git a/ios/Runner/Sites.swift b/ios/Runner/Sites.swift index ebf2b6e..7a8f79f 100644 --- a/ios/Runner/Sites.swift +++ b/ios/Runner/Sites.swift @@ -134,22 +134,22 @@ class SiteUpdater: NSObject, FlutterStreamHandler { } self.notification = NotificationCenter.default.addObserver(forName: NSNotification.Name.NEVPNStatusDidChange, object: site.manager!.connection , queue: nil) { n in - let connected = self.site.connected + let oldConnected = self.site.connected self.site.status = statusString[self.site.manager!.connection.status] self.site.connected = statusMap[self.site.manager!.connection.status] - + // Check to see if we just moved to connected and if we have a start function to call when that happens - if self.site.connected! && connected != self.site.connected && self.startFunc != nil { + if self.site.connected! && oldConnected != self.site.connected && self.startFunc != nil { self.startFunc!() self.startFunc = nil } - + self.update(connected: self.site.connected!) } #endif return nil } - + /// onCancel is called when the flutter listener stops listening func onCancel(withArguments arguments: Any?) -> FlutterError? { if (self.notification != nil) {