diff options
| author | Bug Magnet <marco.nikic@mullvad.net> | 2024-02-14 16:29:53 +0100 |
|---|---|---|
| committer | Bug Magnet <marco.nikic@mullvad.net> | 2024-02-14 16:29:53 +0100 |
| commit | e2c4fb47f4352cf1eb1200fbb29b9539c86b73e3 (patch) | |
| tree | 86df3c801647f74c6d8019d46f172c379920ee63 | |
| parent | 2105a49803c58b76c1b2e512344d2b24faee75ec (diff) | |
| parent | e3293284bda8bae5aa0af4c5d4ffa1ee3a5998c7 (diff) | |
| download | mullvadvpn-e2c4fb47f4352cf1eb1200fbb29b9539c86b73e3.tar.xz mullvadvpn-e2c4fb47f4352cf1eb1200fbb29b9539c86b73e3.zip | |
Merge branch 'deduplicate-tunnel-manager-changes-from-preferences-view-ios-510'
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) + } +} |
