summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAndrej Mihajlov <and@mullvad.net>2023-03-03 14:26:04 +0100
committerAndrej Mihajlov <and@mullvad.net>2023-03-03 14:26:04 +0100
commitaec8afe49a2de81a6e17ba1105264d83fc46685a (patch)
treed92c4ee3ccf3106bef3dc701666c74755de5405c
parent4d37537a6ea57d40d891df7ae65272a97bc3e927 (diff)
parent639e362cb00eaaf12855de00eecad01898722ed7 (diff)
downloadmullvadvpn-aec8afe49a2de81a6e17ba1105264d83fc46685a.tar.xz
mullvadvpn-aec8afe49a2de81a6e17ba1105264d83fc46685a.zip
Merge branch 'use-default-path'
-rw-r--r--ios/MullvadVPN.xcodeproj/project.pbxproj2
-rw-r--r--ios/MullvadVPN.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved2
-rw-r--r--ios/PacketTunnel/PacketTunnelProvider.swift6
-rw-r--r--ios/PacketTunnel/TunnelMonitor/TunnelMonitor.swift106
4 files changed, 58 insertions, 58 deletions
diff --git a/ios/MullvadVPN.xcodeproj/project.pbxproj b/ios/MullvadVPN.xcodeproj/project.pbxproj
index a5bc1234df..937a3ae636 100644
--- a/ios/MullvadVPN.xcodeproj/project.pbxproj
+++ b/ios/MullvadVPN.xcodeproj/project.pbxproj
@@ -3620,7 +3620,7 @@
repositoryURL = "https://github.com/mullvad/wireguard-apple.git";
requirement = {
kind = revision;
- revision = 309bb8d58a3ed25ff11c4630b88bbe883e53e835;
+ revision = 68e84fb1083637d90c6a9ef41193f940569af0f3;
};
};
/* End XCRemoteSwiftPackageReference section */
diff --git a/ios/MullvadVPN.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/ios/MullvadVPN.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
index d47178827b..685bd558b2 100644
--- a/ios/MullvadVPN.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
+++ b/ios/MullvadVPN.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
@@ -14,7 +14,7 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/mullvad/wireguard-apple.git",
"state" : {
- "revision" : "309bb8d58a3ed25ff11c4630b88bbe883e53e835"
+ "revision" : "68e84fb1083637d90c6a9ef41193f940569af0f3"
}
}
],
diff --git a/ios/PacketTunnel/PacketTunnelProvider.swift b/ios/PacketTunnel/PacketTunnelProvider.swift
index 4a7e10e471..c388b1519d 100644
--- a/ios/PacketTunnel/PacketTunnelProvider.swift
+++ b/ios/PacketTunnel/PacketTunnelProvider.swift
@@ -160,7 +160,11 @@ class PacketTunnelProvider: NEPacketTunnelProvider, TunnelMonitorDelegate {
}
)
- tunnelMonitor = TunnelMonitor(delegateQueue: dispatchQueue, adapter: adapter)
+ tunnelMonitor = TunnelMonitor(
+ delegateQueue: dispatchQueue,
+ packetTunnelProvider: self,
+ adapter: adapter
+ )
tunnelMonitor.delegate = self
}
diff --git a/ios/PacketTunnel/TunnelMonitor/TunnelMonitor.swift b/ios/PacketTunnel/TunnelMonitor/TunnelMonitor.swift
index d1ceddad40..f47ecaf98f 100644
--- a/ios/PacketTunnel/TunnelMonitor/TunnelMonitor.swift
+++ b/ios/PacketTunnel/TunnelMonitor/TunnelMonitor.swift
@@ -55,7 +55,7 @@ final class TunnelMonitor: PingerDelegate {
case stopped
/// Preparing to start.
- /// Intermediate state before recieving the first path update.
+ /// Intermediate state before receiving the first path update.
case pendingStart
/// Establishing connection.
@@ -228,7 +228,8 @@ final class TunnelMonitor: PingerDelegate {
private let delegateQueue: DispatchQueue
private let pinger: Pinger
- private var pathMonitor: NWPathMonitor?
+ private weak var packetTunnelProvider: NEPacketTunnelProvider?
+ private var defaultPathObserver: NSKeyValueObservation?
private var timer: DispatchSourceTimer?
private var state = State()
@@ -252,11 +253,16 @@ final class TunnelMonitor: PingerDelegate {
}
}
- init(delegateQueue: DispatchQueue, adapter anAdapter: WireGuardAdapter) {
+ init(
+ delegateQueue: DispatchQueue,
+ packetTunnelProvider: NEPacketTunnelProvider,
+ adapter: WireGuardAdapter
+ ) {
self.delegateQueue = delegateQueue
- adapter = anAdapter
+ self.packetTunnelProvider = packetTunnelProvider
+ self.adapter = adapter
- pinger = Pinger(delegateQueue: delegateQueue)
+ pinger = Pinger(delegateQueue: eventQueue)
pinger.delegate = self
}
@@ -278,7 +284,7 @@ final class TunnelMonitor: PingerDelegate {
self.probeAddress = probeAddress
state.connectionState = .pendingStart
- startPathMonitor()
+ addDefaultPathObserver()
}
func stop() {
@@ -297,10 +303,10 @@ final class TunnelMonitor: PingerDelegate {
switch state.connectionState {
case .connecting, .connected:
startConnectivityCheckTimer()
- startPathMonitor()
+ addDefaultPathObserver()
case .waitingConnectivity, .pendingStart:
- startPathMonitor()
+ addDefaultPathObserver()
case .stopped, .recovering:
break
@@ -314,7 +320,7 @@ final class TunnelMonitor: PingerDelegate {
logger.trace("Prepare to sleep.")
stopConnectivityCheckTimer()
- stopPathMonitor()
+ removeDefaultPathObserver()
}
// MARK: - PingerDelegate
@@ -347,41 +353,53 @@ final class TunnelMonitor: PingerDelegate {
probeAddress = nil
- stopPathMonitor()
+ removeDefaultPathObserver()
stopMonitoring(resetRetryAttempt: !forRestart)
state.connectionState = .stopped
}
- private func startPathMonitor() {
- let pathMonitor = NWPathMonitor()
- pathMonitor.pathUpdateHandler = { [weak self] path in
- self?.handleNetworkPathUpdate(path)
- }
- pathMonitor.start(queue: eventQueue)
+ private func addDefaultPathObserver() {
+ guard let packetTunnelProvider = packetTunnelProvider else { return }
+
+ defaultPathObserver?.invalidate()
- self.pathMonitor?.cancel()
- self.pathMonitor = pathMonitor
+ logger.trace("Add default path observer.")
- logger.trace("Start path monitor.")
+ defaultPathObserver = packetTunnelProvider
+ .observe(\.defaultPath, options: [.new]) { [weak self] _, change in
+ guard let self = self else { return }
+
+ self.nslock.lock()
+ defer { self.nslock.unlock() }
+
+ let newValue = change.newValue.flatMap { $0 }
+ if let newPath = newValue {
+ self.handleNetworkPathUpdate(newPath)
+ }
+ }
+
+ if let currentPath = packetTunnelProvider.defaultPath {
+ handleNetworkPathUpdate(currentPath)
+ }
}
- private func stopPathMonitor() {
- guard let pathMonitor = pathMonitor else { return }
+ private func removeDefaultPathObserver() {
+ guard let defaultPathObserver = defaultPathObserver else { return }
- logger.trace("Stop path monitor.")
+ logger.trace("Remove default path observer.")
- pathMonitor.cancel()
- self.pathMonitor = nil
+ defaultPathObserver.invalidate()
+ self.defaultPathObserver = nil
}
private func checkConnectivity() {
nslock.lock()
defer { nslock.unlock() }
- guard let probeAddress = probeAddress, let newStats = getStats() else {
- return
- }
+ guard let probeAddress = probeAddress, let newStats = getStats(),
+ state.connectionState == .connecting || state.connectionState == .connected
+ else { return }
// Check if counters were reset.
let isStatsReset = newStats.bytesReceived < state.netStats.bytesReceived ||
@@ -444,7 +462,7 @@ final class TunnelMonitor: PingerDelegate {
#endif
private func startConnectionRecovery() {
- stopPathMonitor()
+ removeDefaultPathObserver()
stopMonitoring(resetRetryAttempt: false)
state.retryAttempt = state.retryAttempt.saturatingAddition(1)
@@ -465,25 +483,13 @@ final class TunnelMonitor: PingerDelegate {
}
}
- private func handleNetworkPathUpdate(_ networkPath: Network.NWPath) {
- nslock.lock()
- defer { nslock.unlock() }
-
+ private func handleNetworkPathUpdate(_ networkPath: NetworkExtension.NWPath) {
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
- }
-
- lazy var isRoutableViaUtun = isTunnelInterfaceUp(networkPath) &&
- hasPhysicalNetworkInterface && isReachable
+ let isReachable = pathStatus == .satisfiable || pathStatus == .satisfied
switch state.connectionState {
case .pendingStart:
- // Wait for tunnel interface to appear first.
- guard isTunnelInterfaceUp(networkPath) else { return }
-
- if isReachable, hasPhysicalNetworkInterface {
+ if isReachable {
logger.debug("Start monitoring connection.")
startMonitoring()
sendDelegateNetworkStatusChange(true)
@@ -494,14 +500,14 @@ final class TunnelMonitor: PingerDelegate {
}
case .waitingConnectivity:
- guard isRoutableViaUtun else { return }
+ guard isReachable else { return }
logger.debug("Network is reachable. Resume monitoring.")
startMonitoring()
sendDelegateNetworkStatusChange(true)
case .connecting, .connected:
- guard !isRoutableViaUtun else { return }
+ guard !isReachable else { return }
logger.debug("Network is unreachable. Pause monitoring.")
state.connectionState = .waitingConnectivity
@@ -664,14 +670,4 @@ final class TunnelMonitor: PingerDelegate {
return newStats
}
-
- private func isTunnelInterfaceUp(_ networkPath: Network.NWPath) -> Bool {
- guard let tunName = adapter.interfaceName else { return false }
-
- let utunUp = networkPath.availableInterfaces.contains { interface in
- return interface.name == tunName
- }
-
- return utunUp
- }
}