Skip to content

Commit

Permalink
Rework the ios startup flow slightly to avoid crashing on ios 16.5 (#132
Browse files Browse the repository at this point in the history
)
  • Loading branch information
nbrownus committed May 23, 2023
1 parent dcf54b1 commit 81901b5
Show file tree
Hide file tree
Showing 3 changed files with 11 additions and 26 deletions.
25 changes: 5 additions & 20 deletions ios/NebulaNetworkExtension/PacketTunnelProvider.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down Expand Up @@ -175,28 +172,16 @@ 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 {
// No response data, this is expected on a clean start
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)
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion ios/NebulaNetworkExtension/Site.swift
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ struct CertificateValidity: Codable {
let statusMap: Dictionary<NEVPNStatus, Bool> = [
NEVPNStatus.invalid: false,
NEVPNStatus.disconnected: false,
NEVPNStatus.connecting: true,
NEVPNStatus.connecting: false,
NEVPNStatus.connected: true,
NEVPNStatus.reasserting: true,
NEVPNStatus.disconnecting: true,
Expand Down
10 changes: 5 additions & 5 deletions ios/Runner/Sites.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down

0 comments on commit 81901b5

Please sign in to comment.