summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAndrej Mihajlov <and@mullvad.net>2022-11-28 15:05:32 +0100
committerAndrej Mihajlov <and@mullvad.net>2022-11-30 13:09:42 +0100
commit3a79afbca1c1b12a372ede2d88ef16cbcf94f3b8 (patch)
treef506922cb88234eb2088581d88517d828a32f1b8
parenta72dc54bb561175bf5bf10391b4200e9b0b6ebdc (diff)
downloadmullvadvpn-3a79afbca1c1b12a372ede2d88ef16cbcf94f3b8.tar.xz
mullvadvpn-3a79afbca1c1b12a372ede2d88ef16cbcf94f3b8.zip
Wait for utun to appear before reporting network status
-rw-r--r--ios/PacketTunnel/TunnelMonitor/TunnelMonitor.swift65
1 files changed, 31 insertions, 34 deletions
diff --git a/ios/PacketTunnel/TunnelMonitor/TunnelMonitor.swift b/ios/PacketTunnel/TunnelMonitor/TunnelMonitor.swift
index eac8d21d0e..b13659127e 100644
--- a/ios/PacketTunnel/TunnelMonitor/TunnelMonitor.swift
+++ b/ios/PacketTunnel/TunnelMonitor/TunnelMonitor.swift
@@ -437,30 +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, .pendingStart):
- logger.debug("Start monitoring connection.")
- startMonitoring()
- sendDelegateNetworkStatusChange(isReachable)
+ lazy var isRoutableViaUtun = isTunnelInterfaceUp(networkPath) &&
+ hasPhysicalNetworkInterface && isReachable
- case (false, .pendingStart):
- logger.debug("Wait for network to become reachable before starting monitoring.")
- state.connectionState = .waitingConnectivity
- sendDelegateNetworkStatusChange(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 }
- case (true, .waitingConnectivity):
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
@@ -637,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
}
}