diff options
| author | Andrej Mihajlov <and@mullvad.net> | 2022-07-28 12:31:45 +0200 |
|---|---|---|
| committer | Andrej Mihajlov <and@mullvad.net> | 2022-07-28 16:26:05 +0200 |
| commit | bb5187e61edcdc14170da484e058dce0e4070820 (patch) | |
| tree | d906dcdc8de116f7225ac0d94fcdea3aedca2169 | |
| parent | 745e27bca514169eea0d1af1ab98088013593ed2 (diff) | |
| download | mullvadvpn-bb5187e61edcdc14170da484e058dce0e4070820.tar.xz mullvadvpn-bb5187e61edcdc14170da484e058dce0e4070820.zip | |
Add option to tell reconnectTunnel to select new relay or keep using current one
| -rw-r--r-- | ios/MullvadVPN.xcodeproj/project.pbxproj | 4 | ||||
| -rw-r--r-- | ios/MullvadVPN/ConnectViewController.swift | 2 | ||||
| -rw-r--r-- | ios/MullvadVPN/SceneDelegate.swift | 2 | ||||
| -rw-r--r-- | ios/MullvadVPN/TunnelManager/MapConnectionStatusOperation.swift | 72 | ||||
| -rw-r--r-- | ios/MullvadVPN/TunnelManager/ReloadTunnelOperation.swift | 32 | ||||
| -rw-r--r-- | ios/MullvadVPN/TunnelManager/TunnelManager.swift | 33 | ||||
| -rw-r--r-- | ios/MullvadVPN/TunnelManager/TunnelManagerError.swift | 2 |
7 files changed, 83 insertions, 64 deletions
diff --git a/ios/MullvadVPN.xcodeproj/project.pbxproj b/ios/MullvadVPN.xcodeproj/project.pbxproj index 7fde39eb6b..467abb4bea 100644 --- a/ios/MullvadVPN.xcodeproj/project.pbxproj +++ b/ios/MullvadVPN.xcodeproj/project.pbxproj @@ -22,6 +22,7 @@ 58095C572760F47900890776 /* api-ip-address.json in Resources */ = {isa = PBXBuildFile; fileRef = 58095C562760F47900890776 /* api-ip-address.json */; }; 58095C592762155700890776 /* RESTRetryStrategy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58095C582762155700890776 /* RESTRetryStrategy.swift */; }; 580CBFB82848D503007878F0 /* OperationConditionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 580CBFB72848D503007878F0 /* OperationConditionTests.swift */; }; + 580D9C5E289298FD00B77A26 /* TunnelMonitorDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58E072A428814C28008902F8 /* TunnelMonitorDelegate.swift */; }; 580EE22424B3243100F9D8A1 /* AsyncBlockOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 580EE22324B3243100F9D8A1 /* AsyncBlockOperation.swift */; }; 580F8B8328197881002E0998 /* TunnelSettingsV2.swift in Sources */ = {isa = PBXBuildFile; fileRef = 580F8B8228197881002E0998 /* TunnelSettingsV2.swift */; }; 580F8B8428197884002E0998 /* TunnelSettingsV2.swift in Sources */ = {isa = PBXBuildFile; fileRef = 580F8B8228197881002E0998 /* TunnelSettingsV2.swift */; }; @@ -257,11 +258,9 @@ 58DF5B7C28521A9F00E92647 /* ResultOperation+Output.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58059DDF2846823E002B1049 /* ResultOperation+Output.swift */; }; 58DF5B7D28521AAC00E92647 /* OutputOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58059DDD28468158002B1049 /* OutputOperation.swift */; }; 58DF5B7F2852778600E92647 /* OperationSmokeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58DF5B7E2852778600E92647 /* OperationSmokeTests.swift */; }; - 58E07299288031D5008902F8 /* WireGuardAdapterError+Localization.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58E07298288031D5008902F8 /* WireGuardAdapterError+Localization.swift */; }; 58E0729D28814AAE008902F8 /* PacketTunnelConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58E0729C28814AAE008902F8 /* PacketTunnelConfiguration.swift */; }; 58E0729F28814ACC008902F8 /* WireGuardLogLevel+Logging.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58E0729E28814ACC008902F8 /* WireGuardLogLevel+Logging.swift */; }; 58E072A128814B0E008902F8 /* MullvadEndpoint+WgEndpoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58E072A028814B0E008902F8 /* MullvadEndpoint+WgEndpoint.swift */; }; - 58E072A528814C28008902F8 /* TunnelMonitorDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58E072A428814C28008902F8 /* TunnelMonitorDelegate.swift */; }; 58E0A98827C8F46300FE6BDD /* Tunnel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58E0A98727C8F46300FE6BDD /* Tunnel.swift */; }; 58E20771274672CA00DE5D77 /* LaunchViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58E20770274672CA00DE5D77 /* LaunchViewController.swift */; }; 58E25F812837BBBB002CFB2C /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58E25F802837BBBB002CFB2C /* SceneDelegate.swift */; }; @@ -1517,6 +1516,7 @@ 58F840B32464491D0044E708 /* ChainedError.swift in Sources */, 58D67A0A26D7AE3300557C3C /* OSLogHandler.swift in Sources */, 5820675626E6528A00655B05 /* RESTError.swift in Sources */, + 580D9C5E289298FD00B77A26 /* TunnelMonitorDelegate.swift in Sources */, 58561C9A239A5D1500BD6B5E /* IPEndpoint.swift in Sources */, 58781CCE22AE8918009B9D8E /* RelayConstraints.swift in Sources */, 581503A024D6F01E00C9C50E /* LogRotation.swift in Sources */, diff --git a/ios/MullvadVPN/ConnectViewController.swift b/ios/MullvadVPN/ConnectViewController.swift index d25d5dfd9b..4dbde5d2c2 100644 --- a/ios/MullvadVPN/ConnectViewController.swift +++ b/ios/MullvadVPN/ConnectViewController.swift @@ -391,7 +391,7 @@ class ConnectViewController: UIViewController, MKMapViewDelegate, RootContainmen } @objc func handleReconnect(_ sender: Any) { - TunnelManager.shared.reconnectTunnel() + TunnelManager.shared.reconnectTunnel(selectNewRelay: true) } @objc func handleSelectLocation(_ sender: Any) { diff --git a/ios/MullvadVPN/SceneDelegate.swift b/ios/MullvadVPN/SceneDelegate.swift index 56e6d1e8bc..19ce61eb36 100644 --- a/ios/MullvadVPN/SceneDelegate.swift +++ b/ios/MullvadVPN/SceneDelegate.swift @@ -211,7 +211,7 @@ extension SceneDelegate: RootContainerViewControllerDelegate { switch TunnelManager.shared.tunnelState { case .connected, .connecting, .reconnecting: - TunnelManager.shared.reconnectTunnel() + TunnelManager.shared.reconnectTunnel(selectNewRelay: true) case .disconnecting, .disconnected: TunnelManager.shared.startTunnel() case .pendingReconnect: diff --git a/ios/MullvadVPN/TunnelManager/MapConnectionStatusOperation.swift b/ios/MullvadVPN/TunnelManager/MapConnectionStatusOperation.swift index 927c27f10e..dee1ef6d6b 100644 --- a/ios/MullvadVPN/TunnelManager/MapConnectionStatusOperation.swift +++ b/ios/MullvadVPN/TunnelManager/MapConnectionStatusOperation.swift @@ -51,58 +51,21 @@ class MapConnectionStatusOperation: AsyncOperation { state.tunnelStatus.state = .connecting(nil) } - let session = TunnelIPC.Session(tunnel: tunnel) - - request = session.getTunnelStatus { [weak self] completion in - guard let self = self else { return } - - self.dispatchQueue.async { - if case .success(let packetTunnelStatus) = completion, !self.isCancelled { - self.state.tunnelStatus.update(from: packetTunnelStatus) { relay in - return .connecting(relay) - } - } - - self.finish() - } + updateTunnelRelayAndFinish(tunnel: tunnel) { relay in + return relay.map { .connecting($0) } } + return case .reasserting: - let session = TunnelIPC.Session(tunnel: tunnel) - - request = session.getTunnelStatus { [weak self] completion in - guard let self = self else { return } - - self.dispatchQueue.async { - if case .success(let packetTunnelStatus) = completion, !self.isCancelled { - self.state.tunnelStatus.update(from: packetTunnelStatus) { relay in - return relay.map { .reconnecting($0) } - } - } - - self.finish() - } + updateTunnelRelayAndFinish(tunnel: tunnel) { relay in + return relay.map { .reconnecting($0) } } - return case .connected: - let session = TunnelIPC.Session(tunnel: tunnel) - - request = session.getTunnelStatus { [weak self] completion in - guard let self = self else { return } - - self.dispatchQueue.async { - if case .success(let packetTunnelStatus) = completion, !self.isCancelled { - self.state.tunnelStatus.update(from: packetTunnelStatus) { relay in - return relay.map { .connected($0) } - } - } - - self.finish() - } + updateTunnelRelayAndFinish(tunnel: tunnel) { relay in + return relay.map { .connected($0) } } - return case .disconnected: @@ -143,4 +106,25 @@ class MapConnectionStatusOperation: AsyncOperation { override func operationDidCancel() { request?.cancel() } + + private func updateTunnelRelayAndFinish( + tunnel: Tunnel, + mapRelayToState: @escaping (PacketTunnelRelay?) -> TunnelState? + ) + { + request = tunnel.getTunnelStatus { [weak self] completion in + guard let self = self else { return } + + self.dispatchQueue.async { + if case .success(let packetTunnelStatus) = completion, !self.isCancelled { + self.state.tunnelStatus.update( + from: packetTunnelStatus, + mappingRelayToState: mapRelayToState + ) + } + + self.finish() + } + } + } } diff --git a/ios/MullvadVPN/TunnelManager/ReloadTunnelOperation.swift b/ios/MullvadVPN/TunnelManager/ReloadTunnelOperation.swift index e1d6429d6f..492e105b55 100644 --- a/ios/MullvadVPN/TunnelManager/ReloadTunnelOperation.swift +++ b/ios/MullvadVPN/TunnelManager/ReloadTunnelOperation.swift @@ -10,26 +10,46 @@ import Foundation class ReloadTunnelOperation: ResultOperation<(), TunnelManager.Error> { private let state: TunnelManager.State + private let selectNewRelay: Bool private var task: Cancellable? - init(dispatchQueue: DispatchQueue, state: TunnelManager.State) { + init( + dispatchQueue: DispatchQueue, + state: TunnelManager.State, + selectNewRelay: Bool + ) + { self.state = state + self.selectNewRelay = selectNewRelay super.init(dispatchQueue: dispatchQueue) } override func main() { - guard let tunnel = self.state.tunnel else { + guard let tunnel = self.state.tunnel, + let relayConstraints = state.tunnelSettings?.relayConstraints else { finish(completion: .failure(.unsetTunnel)) return } - let session = TunnelIPC.Session(tunnel: tunnel) + do { + var selectorResult: RelaySelectorResult? - task = session.reloadTunnelSettings { [weak self] completion in - guard let self = self else { return } + if selectNewRelay { + let cachedRelays = try RelayCache.Tracker.shared.getCachedRelays() + selectorResult = try RelaySelector.evaluate( + relays: cachedRelays.relays, + constraints: relayConstraints + ) + } - self.finish(completion: completion.mapError { .reloadTunnel($0) }) + task = tunnel.reconnectTunnel( + relaySelectorResult: selectorResult + ) { [weak self] completion in + self?.finish(completion: completion.mapError { .reloadTunnel($0) }) + } + } catch { + finish(completion: .failure(.reloadTunnel(error))) } } diff --git a/ios/MullvadVPN/TunnelManager/TunnelManager.swift b/ios/MullvadVPN/TunnelManager/TunnelManager.swift index ff74c6213e..9c451b0109 100644 --- a/ios/MullvadVPN/TunnelManager/TunnelManager.swift +++ b/ios/MullvadVPN/TunnelManager/TunnelManager.swift @@ -62,7 +62,7 @@ final class TunnelManager: TunnelManagerStateDelegate { private let stateQueue = DispatchQueue(label: "TunnelManager.stateQueue") private let operationQueue = AsyncOperationQueue() - private var statusObserver: Tunnel.StatusBlockObserver? + private var statusObserver: TunnelStatusBlockObserver? private var lastMapConnectionStatusOperation: Operation? private let observerList = ObserverList<TunnelObserver>() @@ -328,8 +328,16 @@ final class TunnelManager: TunnelManagerStateDelegate { operationQueue.addOperation(operation) } - func reconnectTunnel(completionHandler: ((OperationCompletion<(), TunnelManager.Error>) -> Void)? = nil) { - let operation = ReloadTunnelOperation(dispatchQueue: stateQueue, state: state) + func reconnectTunnel( + selectNewRelay: Bool, + completionHandler: ((OperationCompletion<(), TunnelManager.Error>) -> Void)? = nil + ) + { + let operation = ReloadTunnelOperation( + dispatchQueue: stateQueue, + state: state, + selectNewRelay: selectNewRelay + ) operation.completionHandler = { [weak self] completion in guard let self = self else { return } @@ -485,7 +493,7 @@ final class TunnelManager: TunnelManagerStateDelegate { switch completion { case .success: - self.reconnectTunnel { _ in + self.reconnectTunnel(selectNewRelay: true) { _ in completionHandler(completion) } @@ -682,18 +690,25 @@ final class TunnelManager: TunnelManagerStateDelegate { let operation = ResultBlockOperation<Void, TunnelManager.Error>( dispatchQueue: stateQueue ) { operation in - guard var tunnelSettings = self.tunnelSettings else { + guard let currentSettings = self.tunnelSettings else { operation.finish(completion: .failure(.unsetAccount)) return } do { - modificationBlock(&tunnelSettings) + var updatedSettings = currentSettings + + modificationBlock(&updatedSettings) + + // Select new relay only when relay constraints change. + let currentConstraints = currentSettings.relayConstraints + let updatedConstraints = updatedSettings.relayConstraints + let selectNewRelay = currentConstraints != updatedConstraints - try SettingsManager.writeSettings(tunnelSettings) + try SettingsManager.writeSettings(updatedSettings) - self.state.tunnelSettings = tunnelSettings - self.reconnectTunnel(completionHandler: nil) + self.state.tunnelSettings = updatedSettings + self.reconnectTunnel(selectNewRelay: selectNewRelay, completionHandler: nil) operation.finish(completion: .success(())) } catch { diff --git a/ios/MullvadVPN/TunnelManager/TunnelManagerError.swift b/ios/MullvadVPN/TunnelManager/TunnelManagerError.swift index 48ea2f97b1..fa1d095057 100644 --- a/ios/MullvadVPN/TunnelManager/TunnelManagerError.swift +++ b/ios/MullvadVPN/TunnelManager/TunnelManagerError.swift @@ -69,7 +69,7 @@ extension TunnelManager { case rotateKey(REST.Error) /// Failure to reload tunnel. - case reloadTunnel(TunnelIPC.Error) + case reloadTunnel(Swift.Error) var errorDescription: String? { switch self { |
