diff options
| author | Jon Petersson <jon.petersson@mullvad.net> | 2025-10-07 12:37:55 +0200 |
|---|---|---|
| committer | Jon Petersson <jon.petersson@mullvad.net> | 2025-10-14 09:54:28 +0200 |
| commit | 0cc99647448b899b9f39c31e36620f4d42b464c4 (patch) | |
| tree | 45dc23c90695080045f3a999657cb9b6d284a6dc | |
| parent | fe1844b2c887cace39aeac0f57c41d7e8b2d7d09 (diff) | |
| download | mullvadvpn-0cc99647448b899b9f39c31e36620f4d42b464c4.tar.xz mullvadvpn-0cc99647448b899b9f39c31e36620f4d42b464c4.zip | |
Fix quantum exchange hot loop
3 files changed, 13 insertions, 6 deletions
diff --git a/ios/PacketTunnel/PacketTunnelProvider/PacketTunnelProvider.swift b/ios/PacketTunnel/PacketTunnelProvider/PacketTunnelProvider.swift index 063d8f681d..9852e4a4e4 100644 --- a/ios/PacketTunnel/PacketTunnelProvider/PacketTunnelProvider.swift +++ b/ios/PacketTunnel/PacketTunnelProvider/PacketTunnelProvider.swift @@ -28,6 +28,7 @@ class PacketTunnelProvider: NEPacketTunnelProvider, @unchecked Sendable { private var relaySelector: RelaySelectorWrapper! private var ephemeralPeerExchangingPipeline: EphemeralPeerExchangingPipeline! private let tunnelSettingsUpdater: SettingsUpdater! + private let pathObserver: PacketTunnelPathObserver! private var encryptedDNSTransport: EncryptedDNSTransport! private var migrationManager: MigrationManager! let migrationFailureIterator = REST.RetryStrategy.failedMigrationRecovery.makeDelayIterator() @@ -57,6 +58,8 @@ class PacketTunnelProvider: NEPacketTunnelProvider, @unchecked Sendable { tunnelSettingsUpdater = SettingsUpdater(listener: tunnelSettingsListener) migrationManager = MigrationManager(cacheDirectory: containerURL) + pathObserver = PacketTunnelPathObserver(eventQueue: internalQueue) + super.init() performSettingsMigration() @@ -102,7 +105,7 @@ class PacketTunnelProvider: NEPacketTunnelProvider, @unchecked Sendable { timings: PacketTunnelActorTimings(), tunnelAdapter: adapter, tunnelMonitor: tunnelMonitor, - defaultPathObserver: PacketTunnelPathObserver(eventQueue: internalQueue), + defaultPathObserver: pathObserver, blockedStateErrorMapper: BlockedStateErrorMapper(), relaySelector: relaySelector, settingsReader: TunnelSettingsManager(settingsReader: SettingsReader()) { [weak self] settings in @@ -446,8 +449,12 @@ extension PacketTunnelProvider: EphemeralPeerReceiving { } func ephemeralPeerExchangeFailed() { - // Do not try reconnecting to the `.current` relay, else the actor's `State` equality check will fail - // and it will not try to reconnect - actor.reconnect(to: .random, reconnectReason: .connectionLoss) + // Do not retry connection unless there's network reachability. Doing so will lead to a hot loop where + // connections are retried every time peer exchange fails, which it will if reachability is not satisfied. + if pathObserver.currentPathStatus.networkReachability == .reachable { + // Do not try reconnecting to the `.current` relay, else the actor's `State` equality check will fail + // and it will not try to reconnect + actor.reconnect(to: .random, reconnectReason: .connectionLoss) + } } } diff --git a/ios/PacketTunnelCore/Actor/NetworkPath+NetworkReachability.swift b/ios/PacketTunnelCore/Actor/NetworkPath+NetworkReachability.swift index 4c4cd719f8..1566d98744 100644 --- a/ios/PacketTunnelCore/Actor/NetworkPath+NetworkReachability.swift +++ b/ios/PacketTunnelCore/Actor/NetworkPath+NetworkReachability.swift @@ -11,7 +11,7 @@ import Network extension Network.NWPath.Status { /// Converts `NetworkPath.status` into `NetworkReachability`. - var networkReachability: NetworkReachability { + public var networkReachability: NetworkReachability { switch self { case .satisfied: .reachable diff --git a/ios/PacketTunnelCore/TunnelMonitor/TunnelMonitor.swift b/ios/PacketTunnelCore/TunnelMonitor/TunnelMonitor.swift index 89cbe5e810..a286471562 100644 --- a/ios/PacketTunnelCore/TunnelMonitor/TunnelMonitor.swift +++ b/ios/PacketTunnelCore/TunnelMonitor/TunnelMonitor.swift @@ -123,7 +123,7 @@ public final class TunnelMonitor: TunnelMonitorProtocol, @unchecked Sendable { public func handleNetworkPathUpdate(_ networkPath: Network.NWPath.Status) { nslock.withLock { - let isReachable = networkPath == .satisfied || networkPath == .requiresConnection + let isReachable = networkPath.networkReachability == .reachable switch state.connectionState { case .pendingStart: |
