diff options
| author | Andrej Mihajlov <and@mullvad.net> | 2022-11-30 14:40:28 +0100 |
|---|---|---|
| committer | Andrej Mihajlov <and@mullvad.net> | 2022-11-30 14:40:28 +0100 |
| commit | 4c83a396fda3c70bfa872e4b0d88dac1297d21dc (patch) | |
| tree | f506922cb88234eb2088581d88517d828a32f1b8 /ios | |
| parent | 4bf5b1c5df0776d18e7a31f40c0d840e508b4b22 (diff) | |
| parent | 3a79afbca1c1b12a372ede2d88ef16cbcf94f3b8 (diff) | |
| download | mullvadvpn-4c83a396fda3c70bfa872e4b0d88dac1297d21dc.tar.xz mullvadvpn-4c83a396fda3c70bfa872e4b0d88dac1297d21dc.zip | |
Merge branch 'improve-network-path-status-reporting'
Diffstat (limited to 'ios')
| -rw-r--r-- | ios/MullvadTypes/PacketTunnelStatus.swift | 1 | ||||
| -rw-r--r-- | ios/PacketTunnel/TunnelMonitor/TunnelMonitor.swift | 83 |
2 files changed, 43 insertions, 41 deletions
diff --git a/ios/MullvadTypes/PacketTunnelStatus.swift b/ios/MullvadTypes/PacketTunnelStatus.swift index 1e4cbf18ba..2b5a1abf91 100644 --- a/ios/MullvadTypes/PacketTunnelStatus.swift +++ b/ios/MullvadTypes/PacketTunnelStatus.swift @@ -42,6 +42,7 @@ public struct PacketTunnelStatus: Codable, Equatable { /// Last performed device check. public var deviceCheck: DeviceCheck? + /// Current relay. public var tunnelRelay: PacketTunnelRelay? diff --git a/ios/PacketTunnel/TunnelMonitor/TunnelMonitor.swift b/ios/PacketTunnel/TunnelMonitor/TunnelMonitor.swift index 4614c8e733..b13659127e 100644 --- a/ios/PacketTunnel/TunnelMonitor/TunnelMonitor.swift +++ b/ios/PacketTunnel/TunnelMonitor/TunnelMonitor.swift @@ -54,6 +54,10 @@ final class TunnelMonitor: PingerDelegate { /// Initialized and doing nothing. case stopped + /// Preparing to start. + /// Intermediate state before recieving the first path update. + case pendingStart + /// Establishing connection. case connecting @@ -167,7 +171,7 @@ final class TunnelMonitor: PingerDelegate { return maxEstablishTimeout } - case .connected, .waitingConnectivity, .stopped: + case .pendingStart, .connected, .waitingConnectivity, .stopped: return pingTimeout } } @@ -305,6 +309,7 @@ final class TunnelMonitor: PingerDelegate { } self.probeAddress = probeAddress + state.connectionState = .pendingStart let pathMonitor = NWPathMonitor() pathMonitor.pathUpdateHandler = { [weak self] path in @@ -312,16 +317,6 @@ final class TunnelMonitor: PingerDelegate { } pathMonitor.start(queue: internalQueue) self.pathMonitor = pathMonitor - - if isNetworkPathReachable(pathMonitor.currentPath) { - logger.debug("Start monitoring connection.") - - startMonitoring() - } else { - logger.debug("Wait for network to become reachable before starting monitoring.") - - state.connectionState = .waitingConnectivity - } } private func stopNoQueue(forRestart: Bool = false) { @@ -423,7 +418,7 @@ final class TunnelMonitor: PingerDelegate { case .connecting, .connected: self.startConnectivityCheckTimer() - case .stopped, .waitingConnectivity: + case .pendingStart, .stopped, .waitingConnectivity: break } } @@ -442,21 +437,44 @@ final class TunnelMonitor: PingerDelegate { } private func handleNetworkPathUpdate(_ networkPath: Network.NWPath) { - let isReachable = isNetworkPathReachable(networkPath) + let pathStatus = networkPath.status + let isReachable = pathStatus == .requiresConnection || pathStatus == .satisfied + let hasPhysicalNetworkInterface = networkPath.availableInterfaces.contains { nw in + return nw.type == .wifi || nw.type == .cellular || nw.type == .wiredEthernet + } - switch (isReachable, state.connectionState) { - case (true, .waitingConnectivity): - logger.debug("Network is reachable. Resume monitoring.") + lazy var isRoutableViaUtun = isTunnelInterfaceUp(networkPath) && + hasPhysicalNetworkInterface && isReachable + + switch state.connectionState { + case .pendingStart: + // Wait for tunnel interface to appear first. + guard isTunnelInterfaceUp(networkPath) else { return } + if isReachable, hasPhysicalNetworkInterface { + logger.debug("Start monitoring connection.") + startMonitoring() + sendDelegateNetworkStatusChange(true) + } else { + logger.debug("Wait for network to become reachable before starting monitoring.") + state.connectionState = .waitingConnectivity + sendDelegateNetworkStatusChange(false) + } + + case .waitingConnectivity: + guard isRoutableViaUtun else { return } + + logger.debug("Network is reachable. Resume monitoring.") startMonitoring() - sendDelegateNetworkStatusChange(isReachable) + sendDelegateNetworkStatusChange(true) - case (false, .connecting), (false, .connected): - logger.debug("Network is unreachable. Pause monitoring.") + case .connecting, .connected: + guard !isRoutableViaUtun else { return } + logger.debug("Network is unreachable. Pause monitoring.") state.connectionState = .waitingConnectivity stopMonitoring(resetRetryAttempt: true) - sendDelegateNetworkStatusChange(isReachable) + sendDelegateNetworkStatusChange(false) default: break @@ -552,7 +570,7 @@ final class TunnelMonitor: PingerDelegate { case .connecting, .connected: startConnectivityCheckTimer() - case .stopped, .waitingConnectivity: + case .pendingStart, .stopped, .waitingConnectivity: break } } @@ -564,7 +582,7 @@ final class TunnelMonitor: PingerDelegate { case .connecting, .connected: stopConnectivityCheckTimer() - case .stopped, .waitingConnectivity: + case .pendingStart, .stopped, .waitingConnectivity: break } } @@ -633,30 +651,13 @@ final class TunnelMonitor: PingerDelegate { return newStats } - private func isNetworkPathReachable(_ networkPath: Network.NWPath) -> Bool { + private func isTunnelInterfaceUp(_ networkPath: Network.NWPath) -> Bool { guard let tunName = adapter.interfaceName else { return false } - // Check if utun is up. let utunUp = networkPath.availableInterfaces.contains { interface in return interface.name == tunName } - guard utunUp else { - return false - } - - // Return false if utun is the only available interface. - if networkPath.availableInterfaces.count == 1 { - return false - } - - switch networkPath.status { - case .requiresConnection, .satisfied: - return true - case .unsatisfied: - return false - @unknown default: - return false - } + return utunUp } } |
