summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAndrej Mihajlov <and@mullvad.net>2022-07-28 12:31:45 +0200
committerAndrej Mihajlov <and@mullvad.net>2022-07-28 16:26:05 +0200
commitbb5187e61edcdc14170da484e058dce0e4070820 (patch)
treed906dcdc8de116f7225ac0d94fcdea3aedca2169
parent745e27bca514169eea0d1af1ab98088013593ed2 (diff)
downloadmullvadvpn-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.pbxproj4
-rw-r--r--ios/MullvadVPN/ConnectViewController.swift2
-rw-r--r--ios/MullvadVPN/SceneDelegate.swift2
-rw-r--r--ios/MullvadVPN/TunnelManager/MapConnectionStatusOperation.swift72
-rw-r--r--ios/MullvadVPN/TunnelManager/ReloadTunnelOperation.swift32
-rw-r--r--ios/MullvadVPN/TunnelManager/TunnelManager.swift33
-rw-r--r--ios/MullvadVPN/TunnelManager/TunnelManagerError.swift2
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 {