From b2ab6b91a1fc8133c839ef4af0146e3bed25ea6c Mon Sep 17 00:00:00 2001 From: Roopesh Chander Date: Wed, 31 Oct 2018 16:42:29 +0530 Subject: VPN: Retry startTunnel based on error conditions Signed-off-by: Roopesh Chander --- WireGuard/WireGuard/VPN/TunnelsManager.swift | 69 +++++++++++++++++++++++----- 1 file changed, 58 insertions(+), 11 deletions(-) (limited to 'WireGuard/WireGuard') diff --git a/WireGuard/WireGuard/VPN/TunnelsManager.swift b/WireGuard/WireGuard/VPN/TunnelsManager.swift index 79d5ae8..5a5c5d5 100644 --- a/WireGuard/WireGuard/VPN/TunnelsManager.swift +++ b/WireGuard/WireGuard/VPN/TunnelsManager.swift @@ -333,20 +333,66 @@ class TunnelContainer: NSObject { case .name(_, _): return false } }) + + os_log("startActivation: Entering", log: OSLog.default, type: .debug) + + guard (tunnelProvider.isEnabled) else { + // In case the tunnel had gotten disabled, re-enable and save it, + // then call this function again. + os_log("startActivation: Tunnel is disabled. Re-enabling and saving.", log: OSLog.default, type: .info) + tunnelProvider.isEnabled = true + tunnelProvider.saveToPreferences { [weak self] (error) in + if (error != nil) { + os_log("Error saving tunnel after re-enabling: %{public}@", log: OSLog.default, type: .error, "\(error!)") + completionHandler(error) + return + } + os_log("startActivation: Tunnel saved after re-enabling.", log: OSLog.default, type: .info) + os_log("startActivation: Invoking startActivation", log: OSLog.default, type: .debug) + self?.startActivation(tunnelConfiguration: tunnelConfiguration, resolvedEndpoints: resolvedEndpoints, completionHandler: completionHandler) + } + return + } + // Start the tunnel - self.tunnelProvider.loadFromPreferences { [weak self] (error) in - guard let s = self else { return } - s.startObservingTunnelStatus() - let session = (s.tunnelProvider.connection as! NETunnelProviderSession) - do { - let tunnelOptions = PacketTunnelOptionsGenerator.generateOptions( - from: tunnelConfiguration, withResolvedEndpoints: resolvedEndpoints) - try session.startTunnel(options: tunnelOptions) - completionHandler(nil) - } catch (let error) { + startObservingTunnelStatus() + let session = (tunnelProvider.connection as! NETunnelProviderSession) + do { + os_log("startActivation: Generating options", log: OSLog.default, type: .debug) + let tunnelOptions = PacketTunnelOptionsGenerator.generateOptions( + from: tunnelConfiguration, withResolvedEndpoints: resolvedEndpoints) + os_log("startActivation: Starting tunnel", log: OSLog.default, type: .debug) + try session.startTunnel(options: tunnelOptions) + os_log("startActivation: Success", log: OSLog.default, type: .debug) + completionHandler(nil) + } catch (let error) { + os_log("startActivation: Error starting tunnel. Examining error.", log: OSLog.default, type: .debug) + guard let vpnError = error as? NEVPNError else { os_log("Failed to activate tunnel: %{public}@", log: OSLog.default, type: .debug, "\(error)") - s.status = .inactive + status = .inactive completionHandler(error) + return + } + guard (vpnError.code == NEVPNError.configurationInvalid || vpnError.code == NEVPNError.configurationStale) else { + os_log("Failed to activate tunnel: %{public}@", log: OSLog.default, type: .debug, "\(error)") + status = .inactive + completionHandler(error) + return + } + assert(vpnError.code == NEVPNError.configurationInvalid || vpnError.code == NEVPNError.configurationStale) + os_log("startActivation: Error says: %{public}@", log: OSLog.default, type: .debug, + vpnError.code == NEVPNError.configurationInvalid ? "Configuration invalid" : "Configuration stale") + os_log("startActivation: Will reload tunnel and then try to start it. ", log: OSLog.default, type: .info) + tunnelProvider.loadFromPreferences { [weak self] (error) in + if (error != nil) { + os_log("Failed to activate tunnel: %{public}@", log: OSLog.default, type: .debug, "\(error!)") + self?.status = .inactive + completionHandler(error) + return + } + os_log("startActivation: Tunnel reloaded.", log: OSLog.default, type: .info) + os_log("startActivation: Invoking startActivation", log: OSLog.default, type: .debug) + self?.startActivation(tunnelConfiguration: tunnelConfiguration, resolvedEndpoints: resolvedEndpoints, completionHandler: completionHandler) } } } @@ -359,6 +405,7 @@ class TunnelContainer: NSObject { } private func startObservingTunnelStatus() { + if (statusObservationToken != nil) { return } let connection = tunnelProvider.connection statusObservationToken = NotificationCenter.default.addObserver( forName: .NEVPNStatusDidChange, -- cgit v1.2.3-59-g8ed1b