diff --git a/ios/MullvadREST/Relay/RelaySelectorWrapper.swift b/ios/MullvadREST/Relay/RelaySelectorWrapper.swift index 38dd42e72022..78f3ae18adbe 100644 --- a/ios/MullvadREST/Relay/RelaySelectorWrapper.swift +++ b/ios/MullvadREST/Relay/RelaySelectorWrapper.swift @@ -11,11 +11,15 @@ import MullvadTypes public final class RelaySelectorWrapper: RelaySelectorProtocol { let relayCache: RelayCacheProtocol - let tunnelSettingsUpdater: SettingsUpdater private var tunnelSettings = LatestTunnelSettings() private var observer: SettingsObserverBlock! + // TODO: Remove, Jon + func setDaita(state: MultihopState) { + daitaState = state + } + deinit { self.tunnelSettingsUpdater.removeObserver(observer) } diff --git a/ios/MullvadVPN.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/ios/MullvadVPN.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved new file mode 100644 index 000000000000..8f79a7a39c60 --- /dev/null +++ b/ios/MullvadVPN.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -0,0 +1,23 @@ +{ + "originHash" : "c15149b2d59d9e9c72375f65339c04f41a19943e1117e682df27fc9f943fdc56", + "pins" : [ + { + "identity" : "swift-log", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-log.git", + "state" : { + "revision" : "173f567a2dfec11d74588eea82cecea555bdc0bc", + "version" : "1.4.0" + } + }, + { + "identity" : "wireguard-apple", + "kind" : "remoteSourceControl", + "location" : "https://github.com/mullvad/wireguard-apple.git", + "state" : { + "revision" : "3c55cc305d30a02f87af5d6228ff416d3901d8dd" + } + } + ], + "version" : 3 +} diff --git a/ios/MullvadVPNTests/MullvadREST/Relay/RelaySelectorWrapperTests.swift b/ios/MullvadVPNTests/MullvadREST/Relay/RelaySelectorWrapperTests.swift index 95b33883e831..fca5d7956ec9 100644 --- a/ios/MullvadVPNTests/MullvadREST/Relay/RelaySelectorWrapperTests.swift +++ b/ios/MullvadVPNTests/MullvadREST/Relay/RelaySelectorWrapperTests.swift @@ -138,4 +138,74 @@ class RelaySelectorWrapperTests: XCTestCase { let selectedRelays = try wrapper.selectRelays(connectionAttemptCount: 0) XCTAssertNotNil(selectedRelays.entry) } + + func testCanSelectRelayWithMultihopOnAndDaitaOn() throws { + let wrapper = RelaySelectorWrapper( + relayCache: relayCache, + multihopUpdater: multihopUpdater + ) + + multihopStateListener.onNewMultihop?(.on) + wrapper.setDaita(state: .on) + + let constraints = RelayConstraints( + entryLocations: .only(UserSelectedRelays(locations: [.country("es")])), // Relay with DAITA. + exitLocations: .only(UserSelectedRelays(locations: [.country("us")])) + ) + + XCTAssertNoThrow(try wrapper.selectRelays(with: constraints, connectionAttemptCount: 0)) + } + + func testCannotSelectRelayWithMultihopOnAndDaitaOn() throws { + let wrapper = RelaySelectorWrapper( + relayCache: relayCache, + multihopUpdater: multihopUpdater + ) + + multihopStateListener.onNewMultihop?(.on) + wrapper.setDaita(state: .on) + + let constraints = RelayConstraints( + entryLocations: .only(UserSelectedRelays(locations: [.country("se")])), // Relay without DAITA. + exitLocations: .only(UserSelectedRelays(locations: [.country("us")])) + ) + + XCTAssertThrowsError(try wrapper.selectRelays(with: constraints, connectionAttemptCount: 0)) + } + + func testCanSelectRelayWithMultihopOffAndDaitaOn() throws { + let wrapper = RelaySelectorWrapper( + relayCache: relayCache, + multihopUpdater: multihopUpdater + ) + + multihopStateListener.onNewMultihop?(.off) + wrapper.setDaita(state: .on) + + let constraints = RelayConstraints( + exitLocations: .only(UserSelectedRelays(locations: [.country("es")])) // Relay with DAITA. + ) + + let selectedRelays = try wrapper.selectRelays(with: constraints, connectionAttemptCount: 0) + XCTAssertNil(selectedRelays.entry) + } + + // If DAITA is enabled and no supported relays are found, we should try to find the nearest + // available relay that supports DAITA and use it as entry in a multihop selection. + func testCanSelectRelayWithMultihopOffAndDaitaOnThroughMultihop() throws { + let wrapper = RelaySelectorWrapper( + relayCache: relayCache, + multihopUpdater: multihopUpdater + ) + + multihopStateListener.onNewMultihop?(.off) + wrapper.setDaita(state: .on) + + let constraints = RelayConstraints( + exitLocations: .only(UserSelectedRelays(locations: [.country("se")])) // Relay without DAITA. + ) + + let selectedRelays = try wrapper.selectRelays(with: constraints, connectionAttemptCount: 0) + XCTAssertNotNil(selectedRelays.entry) + } }