summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--ios/MullvadSettings/TunnelSettingsUpdate.swift41
-rw-r--r--ios/MullvadVPN.xcodeproj/project.pbxproj16
-rw-r--r--ios/MullvadVPN/Coordinators/RelayFilterCoordinator.swift2
-rw-r--r--ios/MullvadVPN/Coordinators/SelectLocationCoordinator.swift4
-rw-r--r--ios/MullvadVPN/TunnelManager/TunnelManager.swift42
-rw-r--r--ios/MullvadVPN/View controllers/Preferences/CustomDNSViewController.swift2
-rw-r--r--ios/MullvadVPN/View controllers/Preferences/PreferencesInteractor.swift14
-rw-r--r--ios/MullvadVPN/View controllers/Preferences/PreferencesViewController.swift18
-rw-r--r--ios/MullvadVPNTests/MullvadSettings/TunnelSettingsUpdateTests.swift73
9 files changed, 155 insertions, 57 deletions
diff --git a/ios/MullvadSettings/TunnelSettingsUpdate.swift b/ios/MullvadSettings/TunnelSettingsUpdate.swift
new file mode 100644
index 0000000000..c915e5dc7f
--- /dev/null
+++ b/ios/MullvadSettings/TunnelSettingsUpdate.swift
@@ -0,0 +1,41 @@
+//
+// TunnelSettingsUpdate.swift
+// MullvadSettings
+//
+// Created by Andrew Bulhak on 2024-02-13.
+// Copyright © 2024 Mullvad VPN AB. All rights reserved.
+//
+
+import Foundation
+import MullvadTypes
+
+public enum TunnelSettingsUpdate {
+ case dnsSettings(DNSSettings)
+ case obfuscation(WireGuardObfuscationSettings)
+ case relayConstraints(RelayConstraints)
+ case quantumResistance(TunnelQuantumResistance)
+}
+
+extension TunnelSettingsUpdate {
+ public func apply(to settings: inout LatestTunnelSettings) {
+ switch self {
+ case let .dnsSettings(newDNSSettings):
+ settings.dnsSettings = newDNSSettings
+ case let .obfuscation(newObfuscationSettings):
+ settings.wireGuardObfuscation = newObfuscationSettings
+ case let .relayConstraints(newRelayConstraints):
+ settings.relayConstraints = newRelayConstraints
+ case let .quantumResistance(newQuantumResistance):
+ settings.tunnelQuantumResistance = newQuantumResistance
+ }
+ }
+
+ public var subjectName: String {
+ switch self {
+ case .dnsSettings: "DNS settings"
+ case .obfuscation: "obfuscation settings"
+ case .relayConstraints: "relay constraints"
+ case .quantumResistance: "quantum resistance"
+ }
+ }
+}
diff --git a/ios/MullvadVPN.xcodeproj/project.pbxproj b/ios/MullvadVPN.xcodeproj/project.pbxproj
index b7685c0ad8..8fc4ca5556 100644
--- a/ios/MullvadVPN.xcodeproj/project.pbxproj
+++ b/ios/MullvadVPN.xcodeproj/project.pbxproj
@@ -38,6 +38,8 @@
06799AFC28F98EE300ACD94E /* AddressCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06AC114128F8413A0037AF9A /* AddressCache.swift */; };
0697D6E728F01513007A9E99 /* TransportMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0697D6E628F01513007A9E99 /* TransportMonitor.swift */; };
06AC116228F94C450037AF9A /* ApplicationConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58BFA5CB22A7CE1F00A6173D /* ApplicationConfiguration.swift */; };
+ 449872E12B7BBC5400094DDC /* TunnelSettingsUpdate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 449872E02B7BBC5400094DDC /* TunnelSettingsUpdate.swift */; };
+ 449872E42B7CB96300094DDC /* TunnelSettingsUpdateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 449872E32B7CB96300094DDC /* TunnelSettingsUpdateTests.swift */; };
44DD7D242B6CFFD70005F67F /* StartTunnelOperationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44DD7D232B6CFFD70005F67F /* StartTunnelOperationTests.swift */; };
44DD7D272B6D18FB0005F67F /* MockTunnelInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44DD7D262B6D18FB0005F67F /* MockTunnelInteractor.swift */; };
44DD7D292B7113CA0005F67F /* MockTunnel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44DD7D282B7113CA0005F67F /* MockTunnel.swift */; };
@@ -1250,6 +1252,8 @@
06FAE67A28F83CA50033DD93 /* RESTDevicesProxy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RESTDevicesProxy.swift; sourceTree = "<group>"; };
06FAE67B28F83CA50033DD93 /* REST.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = REST.swift; sourceTree = "<group>"; };
06FAE67D28F83CA50033DD93 /* RESTTransport.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RESTTransport.swift; sourceTree = "<group>"; };
+ 449872E02B7BBC5400094DDC /* TunnelSettingsUpdate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelSettingsUpdate.swift; sourceTree = "<group>"; };
+ 449872E32B7CB96300094DDC /* TunnelSettingsUpdateTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelSettingsUpdateTests.swift; sourceTree = "<group>"; };
44DD7D232B6CFFD70005F67F /* StartTunnelOperationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StartTunnelOperationTests.swift; sourceTree = "<group>"; };
44DD7D262B6D18FB0005F67F /* MockTunnelInteractor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockTunnelInteractor.swift; sourceTree = "<group>"; };
44DD7D282B7113CA0005F67F /* MockTunnel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockTunnel.swift; sourceTree = "<group>"; };
@@ -2119,6 +2123,14 @@
path = MullvadREST;
sourceTree = "<group>";
};
+ 449872E22B7CB91B00094DDC /* MullvadSettings */ = {
+ isa = PBXGroup;
+ children = (
+ 449872E32B7CB96300094DDC /* TunnelSettingsUpdateTests.swift */,
+ );
+ path = MullvadSettings;
+ sourceTree = "<group>";
+ };
44DD7D252B6D18E90005F67F /* Mocks */ = {
isa = PBXGroup;
children = (
@@ -2774,6 +2786,7 @@
isa = PBXGroup;
children = (
44DD7D252B6D18E90005F67F /* Mocks */,
+ 449872E22B7CB91B00094DDC /* MullvadSettings */,
A900E9BF2ACC661900C95F67 /* AccessTokenManager+Stubs.swift */,
7A6F2FA42AFA3CB2006D0856 /* AccountExpiryTests.swift */,
A900E9B72ACC5C2B00C95F67 /* AccountsProxy+Stubs.swift */,
@@ -2873,6 +2886,7 @@
580F8B8228197881002E0998 /* TunnelSettingsV2.swift */,
A988DF282ADE880300D807EF /* TunnelSettingsV3.swift */,
A93181A02B727ED700E341D2 /* TunnelSettingsV4.swift */,
+ 449872E02B7BBC5400094DDC /* TunnelSettingsUpdate.swift */,
A988DF252ADE86ED00D807EF /* WireGuardObfuscationSettings.swift */,
);
path = MullvadSettings;
@@ -4685,6 +4699,7 @@
A9A5FA262ACB05160083449F /* UpdateDeviceDataOperation.swift in Sources */,
A9A5FA272ACB05160083449F /* VPNConnectionProtocol.swift in Sources */,
A9A5FA282ACB05160083449F /* WgKeyRotation.swift in Sources */,
+ 449872E42B7CB96300094DDC /* TunnelSettingsUpdateTests.swift in Sources */,
A9A5FA292ACB05160083449F /* AddressCacheTests.swift in Sources */,
A9B6AC182ADE8F4300F7802A /* MigrationManagerTests.swift in Sources */,
A9A5FA2A2ACB05160083449F /* CoordinatesTests.swift in Sources */,
@@ -4731,6 +4746,7 @@
58B2FDDE2AA71D5C003EB5C6 /* Migration.swift in Sources */,
F0D7FF8F2B31DF5900E0FDE5 /* AccessMethodRepository.swift in Sources */,
58B2FDE12AA71D5C003EB5C6 /* TunnelSettingsV1.swift in Sources */,
+ 449872E12B7BBC5400094DDC /* TunnelSettingsUpdate.swift in Sources */,
58B2FDE72AA71D5C003EB5C6 /* SettingsStore.swift in Sources */,
44DD7D2D2B74E44A0005F67F /* QuantumResistanceSettings.swift in Sources */,
F08827872B318C840020A383 /* ShadowsocksCipherOptions.swift in Sources */,
diff --git a/ios/MullvadVPN/Coordinators/RelayFilterCoordinator.swift b/ios/MullvadVPN/Coordinators/RelayFilterCoordinator.swift
index deb57141e4..39287b3ec2 100644
--- a/ios/MullvadVPN/Coordinators/RelayFilterCoordinator.swift
+++ b/ios/MullvadVPN/Coordinators/RelayFilterCoordinator.swift
@@ -58,7 +58,7 @@ class RelayFilterCoordinator: Coordinator, Presentable, RelayCacheTrackerObserve
var relayConstraints = tunnelManager.settings.relayConstraints
relayConstraints.filter = .only(filter)
- tunnelManager.setRelayConstraints(relayConstraints)
+ tunnelManager.updateSettings([.relayConstraints(relayConstraints)])
didFinish?(self, filter)
}
diff --git a/ios/MullvadVPN/Coordinators/SelectLocationCoordinator.swift b/ios/MullvadVPN/Coordinators/SelectLocationCoordinator.swift
index 59cb2a644a..67e892e3af 100644
--- a/ios/MullvadVPN/Coordinators/SelectLocationCoordinator.swift
+++ b/ios/MullvadVPN/Coordinators/SelectLocationCoordinator.swift
@@ -58,7 +58,7 @@ class SelectLocationCoordinator: Coordinator, Presentable, Presenting, RelayCach
var relayConstraints = tunnelManager.settings.relayConstraints
relayConstraints.location = .only(relay)
- tunnelManager.setRelayConstraints(relayConstraints) {
+ tunnelManager.updateSettings([.relayConstraints(relayConstraints)]) {
self.tunnelManager.startTunnel()
}
@@ -80,7 +80,7 @@ class SelectLocationCoordinator: Coordinator, Presentable, Presenting, RelayCach
var relayConstraints = tunnelManager.settings.relayConstraints
relayConstraints.filter = .only(filter)
- tunnelManager.setRelayConstraints(relayConstraints)
+ tunnelManager.updateSettings([.relayConstraints(relayConstraints)])
}
selectLocationViewController.didFinish = { [weak self] in
diff --git a/ios/MullvadVPN/TunnelManager/TunnelManager.swift b/ios/MullvadVPN/TunnelManager/TunnelManager.swift
index 0d9b1e80c2..3f0e69459f 100644
--- a/ios/MullvadVPN/TunnelManager/TunnelManager.swift
+++ b/ios/MullvadVPN/TunnelManager/TunnelManager.swift
@@ -503,49 +503,19 @@ final class TunnelManager: StorePaymentObserver {
return operation
}
- func setRelayConstraints(
- _ newConstraints: RelayConstraints,
- completionHandler: (() -> Void)? = nil
- ) {
- scheduleSettingsUpdate(
- taskName: "Set relay constraints",
- modificationBlock: { settings in
- settings.relayConstraints = newConstraints
- },
- completionHandler: completionHandler
- )
- }
-
- func setDNSSettings(_ newDNSSettings: DNSSettings, completionHandler: (() -> Void)? = nil) {
+ func updateSettings(_ updates: [TunnelSettingsUpdate], completionHandler: (() -> Void)? = nil) {
+ let taskName = "Set " + updates.map(\.subjectName).joined(separator: ", ")
scheduleSettingsUpdate(
- taskName: "Set DNS settings",
+ taskName: taskName,
modificationBlock: { settings in
- settings.dnsSettings = newDNSSettings
+ for update in updates {
+ update.apply(to: &settings)
+ }
},
completionHandler: completionHandler
)
}
- func setObfuscationSettings(_ newSettings: WireGuardObfuscationSettings) {
- scheduleSettingsUpdate(
- taskName: "Set obfuscation settings",
- modificationBlock: { settings in
- settings.wireGuardObfuscation = newSettings
- },
- completionHandler: nil
- )
- }
-
- func setQuantumResistance(_ newSetting: TunnelQuantumResistance) {
- scheduleSettingsUpdate(
- taskName: "Set quantum resistance",
- modificationBlock: { settings in
- settings.tunnelQuantumResistance = newSetting
- },
- completionHandler: nil
- )
- }
-
func refreshRelayCacheTracker() throws {
try relayCacheTracker.refreshCachedRelays()
}
diff --git a/ios/MullvadVPN/View controllers/Preferences/CustomDNSViewController.swift b/ios/MullvadVPN/View controllers/Preferences/CustomDNSViewController.swift
index d66d749659..f9cc03d503 100644
--- a/ios/MullvadVPN/View controllers/Preferences/CustomDNSViewController.swift
+++ b/ios/MullvadVPN/View controllers/Preferences/CustomDNSViewController.swift
@@ -95,7 +95,7 @@ class CustomDNSViewController: UITableViewController, PreferencesDataSourceDeleg
// MARK: - PreferencesDataSourceDelegate
func didChangeViewModel(_ viewModel: PreferencesViewModel) {
- interactor.setDNSSettings(viewModel.asDNSSettings())
+ interactor.updateSettings([.dnsSettings(viewModel.asDNSSettings())])
}
func showInfo(for item: PreferencesInfoButtonItem) {
diff --git a/ios/MullvadVPN/View controllers/Preferences/PreferencesInteractor.swift b/ios/MullvadVPN/View controllers/Preferences/PreferencesInteractor.swift
index 8efc309536..2c6e06b07c 100644
--- a/ios/MullvadVPN/View controllers/Preferences/PreferencesInteractor.swift
+++ b/ios/MullvadVPN/View controllers/Preferences/PreferencesInteractor.swift
@@ -36,12 +36,8 @@ final class PreferencesInteractor {
})
}
- func setDNSSettings(_ newDNSSettings: DNSSettings, completion: (() -> Void)? = nil) {
- tunnelManager.setDNSSettings(newDNSSettings, completionHandler: completion)
- }
-
- func setObfuscationSettings(_ newSettings: WireGuardObfuscationSettings) {
- tunnelManager.setObfuscationSettings(newSettings)
+ func updateSettings(_ changes: [TunnelSettingsUpdate], completion: (() -> Void)? = nil) {
+ tunnelManager.updateSettings(changes, completionHandler: completion)
}
func setPort(_ port: UInt16?, completion: (() -> Void)? = nil) {
@@ -53,11 +49,7 @@ final class PreferencesInteractor {
relayConstraints.port = .any
}
- tunnelManager.setRelayConstraints(relayConstraints, completionHandler: completion)
- }
-
- func setQuantumResistance(_ newSetting: TunnelQuantumResistance) {
- tunnelManager.setQuantumResistance(newSetting)
+ tunnelManager.updateSettings([.relayConstraints(relayConstraints)], completionHandler: completion)
}
}
diff --git a/ios/MullvadVPN/View controllers/Preferences/PreferencesViewController.swift b/ios/MullvadVPN/View controllers/Preferences/PreferencesViewController.swift
index 7eee1420d7..d7fe22a040 100644
--- a/ios/MullvadVPN/View controllers/Preferences/PreferencesViewController.swift
+++ b/ios/MullvadVPN/View controllers/Preferences/PreferencesViewController.swift
@@ -101,13 +101,18 @@ class PreferencesViewController: UITableViewController, PreferencesDataSourceDel
// MARK: - PreferencesDataSourceDelegate
func didChangeViewModel(_ viewModel: PreferencesViewModel) {
- interactor.setObfuscationSettings(WireGuardObfuscationSettings(
- state: viewModel.obfuscationState,
- port: viewModel.obfuscationPort
- ))
- interactor.setQuantumResistance(viewModel.quantumResistance)
+ interactor.updateSettings(
+ [
+ .obfuscation(WireGuardObfuscationSettings(
+ state: viewModel.obfuscationState,
+ port: viewModel.obfuscationPort
+ )),
+ .quantumResistance(viewModel.quantumResistance),
+ ]
+ )
}
+ // swiftlint:disable:next function_body_length
func showInfo(for item: PreferencesInfoButtonItem) {
var message = ""
@@ -159,7 +164,8 @@ class PreferencesViewController: UITableViewController, PreferencesDataSourceDel
tableName: "QuantumResistance",
value: """
This feature makes the WireGuard tunnel resistant to potential attacks from quantum computers.
- It does this by performing an extra key exchange using a quantum safe algorithm and mixing the result into WireGuard’s regular encryption.
+ It does this by performing an extra key exchange using a quantum safe algorithm and mixing \
+ the result into WireGuard’s regular encryption.
This extra step uses approximately 500 kiB of traffic every time a new tunnel is established.
""",
comment: ""
diff --git a/ios/MullvadVPNTests/MullvadSettings/TunnelSettingsUpdateTests.swift b/ios/MullvadVPNTests/MullvadSettings/TunnelSettingsUpdateTests.swift
new file mode 100644
index 0000000000..3e4860889e
--- /dev/null
+++ b/ios/MullvadVPNTests/MullvadSettings/TunnelSettingsUpdateTests.swift
@@ -0,0 +1,73 @@
+//
+// TunnelSettingsUpdateTests.swift
+// MullvadVPNTests
+//
+// Created by Andrew Bulhak on 2024-02-14.
+// Copyright © 2024 Mullvad VPN AB. All rights reserved.
+//
+
+@testable import MullvadSettings
+import MullvadTypes
+import Network
+import XCTest
+
+final class TunnelSettingsUpdateTests: XCTestCase {
+ func testApplyDNSSettings() {
+ // Given:
+ var settings = LatestTunnelSettings()
+
+ // When:
+ var dnsSettings = DNSSettings()
+ dnsSettings.blockingOptions = [.blockAdvertising, .blockTracking]
+ dnsSettings.enableCustomDNS = true
+ dnsSettings.customDNSDomains = [.ipv4(IPv4Address("1.2.3.4")!)]
+ let update = TunnelSettingsUpdate.dnsSettings(dnsSettings)
+ update.apply(to: &settings)
+
+ // Then:
+ XCTAssertEqual(settings.dnsSettings.blockingOptions, [.blockAdvertising, .blockTracking])
+ XCTAssertEqual(settings.dnsSettings.enableCustomDNS, true)
+ XCTAssertEqual(settings.dnsSettings.customDNSDomains, [.ipv4(IPv4Address("1.2.3.4")!)])
+ }
+
+ func testApplyObfuscation() {
+ // Given:
+ var settings = LatestTunnelSettings()
+
+ // When:
+ let update = TunnelSettingsUpdate.obfuscation(.init(state: .on, port: .port5001))
+ update.apply(to: &settings)
+
+ // Then:
+ XCTAssertEqual(settings.wireGuardObfuscation, WireGuardObfuscationSettings(state: .on, port: .port5001))
+ }
+
+ func testApplyRelayConstraints() {
+ // Given:
+ var settings = LatestTunnelSettings()
+
+ // When:
+ let relayConstraints = RelayConstraints(
+ location: .only(.country("zz")),
+ port: .only(9999),
+ filter: .only(.init(ownership: .rented, providers: .only(["foo", "bar"])))
+ )
+ let update = TunnelSettingsUpdate.relayConstraints(relayConstraints)
+ update.apply(to: &settings)
+
+ // Then:
+ XCTAssertEqual(settings.relayConstraints, relayConstraints)
+ }
+
+ func testApplyQuantumResistance() {
+ // Given:
+ var settings = LatestTunnelSettings()
+
+ // When:
+ let update = TunnelSettingsUpdate.quantumResistance(.on)
+ update.apply(to: &settings)
+
+ // Then:
+ XCTAssertEqual(settings.tunnelQuantumResistance, .on)
+ }
+}