diff --git a/Coder Desktop/Coder Desktop/VPNService.swift b/Coder Desktop/Coder Desktop/VPNService.swift index 95aff95..1fbaa50 100644 --- a/Coder Desktop/Coder Desktop/VPNService.swift +++ b/Coder Desktop/Coder Desktop/VPNService.swift @@ -70,8 +70,6 @@ final class CoderVPNService: NSObject, VPNService { Task { await loadNetworkExtensionConfig() } - xpc.connect() - xpc.getPeerState() NotificationCenter.default.addObserver( self, selector: #selector(vpnDidUpdate(_:)), @@ -93,8 +91,6 @@ final class CoderVPNService: NSObject, VPNService { } await startTunnel() - xpc.connect() - xpc.ping() logger.debug("network extension enabled") } @@ -162,12 +158,16 @@ final class CoderVPNService: NSObject, VPNService { } extension CoderVPNService { + // The number of NETunnelProviderSession states makes the excessive branching + // necessary. + // swiftlint:disable:next cyclomatic_complexity @objc private func vpnDidUpdate(_ notification: Notification) { guard let connection = notification.object as? NETunnelProviderSession else { return } - switch connection.status { - case .disconnected: + switch (tunnelState, connection.status) { + // Any -> Disconnected: Update UI w/ error if present + case (_, .disconnected): connection.fetchLastDisconnectError { err in self.tunnelState = if let err { .failed(.internalError(err.localizedDescription)) @@ -175,15 +175,30 @@ extension CoderVPNService { .disabled } } - case .connecting: + // Connecting -> Connecting: no-op + case (.connecting, .connecting): + break + // Connected -> Connected: no-op + case (.connected, .connected): + break + // Non-connecting -> Connecting: Establish XPC + case (_, .connecting): + xpc.connect() + xpc.ping() tunnelState = .connecting - case .connected: + // Non-connected -> Connected: Retrieve Peers + case (_, .connected): + xpc.connect() + xpc.getPeerState() tunnelState = .connected - case .reasserting: + // Any -> Reasserting + case (_, .reasserting): tunnelState = .connecting - case .disconnecting: + // Any -> Disconnecting + case (_, .disconnecting): tunnelState = .disconnecting - case .invalid: + // Any -> Invalid + case (_, .invalid): tunnelState = .failed(.networkExtensionError(.unconfigured)) @unknown default: tunnelState = .disabled