diff options
| author | Jon Petersson <jon.petersson@mullvad.net> | 2025-05-28 15:31:56 +0200 |
|---|---|---|
| committer | Jon Petersson <jon.petersson@mullvad.net> | 2025-06-16 09:11:54 +0200 |
| commit | e08db1c726913cc7fe78afadb84d7cbd7d3d5614 (patch) | |
| tree | 6b658e8a1d7e3d9e88ee0789ea08eeed86db655c | |
| parent | c6dcd53ffd6e7bb484740bc9bb7d8892c0736b37 (diff) | |
| download | mullvadvpn-e08db1c726913cc7fe78afadb84d7cbd7d3d5614.tar.xz mullvadvpn-e08db1c726913cc7fe78afadb84d7cbd7d3d5614.zip | |
Combine DAITA and Multihop to one pill when smart routing is active
17 files changed, 138 insertions, 40 deletions
diff --git a/ios/MullvadREST/Relay/RelayPicking/SinglehopPicker.swift b/ios/MullvadREST/Relay/RelayPicking/SinglehopPicker.swift index 68ebec446d..cf51578031 100644 --- a/ios/MullvadREST/Relay/RelayPicking/SinglehopPicker.swift +++ b/ios/MullvadREST/Relay/RelayPicking/SinglehopPicker.swift @@ -22,22 +22,21 @@ struct SinglehopPicker: RelayPicking { // If DAITA is on, Direct only is off and obfuscation is on, and no supported relays are found, we should see if // the obfuscated subset of exit relays is the cause of this. We can do this by checking if relay selection would // have been successful with all relays available. If that's the case, throw error and point to obfuscation. - do { - _ = try pick(from: obfuscation.unfilteredRelays) + if (try? pick(from: obfuscation.unfilteredRelays)) != nil { throw NoRelaysSatisfyingConstraintsError(.noObfuscatedRelaysFound) - } catch let error as NoRelaysSatisfyingConstraintsError where error.reason == .noDaitaRelaysFound { - // If DAITA is on, Direct only is off and obfuscation has been ruled out, 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. - if daitaSettings.isAutomaticRouting { - return try MultihopPicker( - obfuscation: obfuscation, - constraints: constraints, - connectionAttemptCount: connectionAttemptCount, - daitaSettings: daitaSettings - ).pick() - } else { - throw error - } + } + + // If DAITA is on, Direct only is off and obfuscation has been ruled out, 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. + if daitaSettings.isAutomaticRouting { + return try MultihopPicker( + obfuscation: obfuscation, + constraints: constraints, + connectionAttemptCount: connectionAttemptCount, + daitaSettings: daitaSettings + ).pick() + } else { + throw error } } } diff --git a/ios/MullvadVPN.xcodeproj/project.pbxproj b/ios/MullvadVPN.xcodeproj/project.pbxproj index 7f27111634..47b1b7f97f 100644 --- a/ios/MullvadVPN.xcodeproj/project.pbxproj +++ b/ios/MullvadVPN.xcodeproj/project.pbxproj @@ -518,6 +518,7 @@ 7A45CFC62C05FF6A00D80B21 /* ScreenshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A45CFC22C05FF2F00D80B21 /* ScreenshotTests.swift */; }; 7A45CFC72C071DD400D80B21 /* SnapshotHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58D0C79D23F1CEBA00FE9BA7 /* SnapshotHelper.swift */; }; 7A4D849E2C0F289800687980 /* RelaySelectorProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5824037F2A827DF300163DE8 /* RelaySelectorProtocol.swift */; }; + 7A5110D72DE734DE00686850 /* Color+Mullvad.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9394EEB2DBF56AA009595EA /* Color+Mullvad.swift */; }; 7A516C2E2B6D357500BBD33D /* URL+Scoping.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A516C2D2B6D357500BBD33D /* URL+Scoping.swift */; }; 7A516C3A2B7111A700BBD33D /* IPOverrideWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A516C392B7111A700BBD33D /* IPOverrideWrapper.swift */; }; 7A516C3C2B712F0B00BBD33D /* IPOverrideWrapperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A516C3B2B712F0B00BBD33D /* IPOverrideWrapperTests.swift */; }; @@ -685,6 +686,7 @@ 7AF10EB42ADE85BC00C090B9 /* RelayFilterCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AF10EB32ADE85BC00C090B9 /* RelayFilterCoordinator.swift */; }; 7AF36A9A2CA2964200E1D497 /* AnyIPAddressTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AF36A992CA2964000E1D497 /* AnyIPAddressTests.swift */; }; 7AF6E5F02A95051E00F2679D /* RouterBlockDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AF6E5EF2A95051E00F2679D /* RouterBlockDelegate.swift */; }; + 7AF822C72DF0664700BA4255 /* DAITAMultihopNotice.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AF822C62DF0663B00BA4255 /* DAITAMultihopNotice.swift */; }; 7AF84F462D12C5B000C72690 /* SelectedRelaysStub+Stubs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AF84F452D12C59F00C72690 /* SelectedRelaysStub+Stubs.swift */; }; 7AF9BE882A30C62100DBFEDB /* SelectableSettingsCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A1A264A2A29D65E00B978AA /* SelectableSettingsCell.swift */; }; 7AF9BE8C2A321D1F00DBFEDB /* RelayFilter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AF9BE8A2A321BEF00DBFEDB /* RelayFilter.swift */; }; @@ -2234,6 +2236,7 @@ 7AF10EB32ADE85BC00C090B9 /* RelayFilterCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RelayFilterCoordinator.swift; sourceTree = "<group>"; }; 7AF36A992CA2964000E1D497 /* AnyIPAddressTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnyIPAddressTests.swift; sourceTree = "<group>"; }; 7AF6E5EF2A95051E00F2679D /* RouterBlockDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RouterBlockDelegate.swift; sourceTree = "<group>"; }; + 7AF822C62DF0663B00BA4255 /* DAITAMultihopNotice.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DAITAMultihopNotice.swift; sourceTree = "<group>"; }; 7AF84F452D12C59F00C72690 /* SelectedRelaysStub+Stubs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SelectedRelaysStub+Stubs.swift"; sourceTree = "<group>"; }; 7AF9BE8A2A321BEF00DBFEDB /* RelayFilter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelayFilter.swift; sourceTree = "<group>"; }; 7AF9BE8D2A331C7B00DBFEDB /* RelayFilterViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelayFilterViewModel.swift; sourceTree = "<group>"; }; @@ -4375,6 +4378,7 @@ 7A8A19082CE5FFD7000BCB5B /* DAITA */ = { isa = PBXGroup; children = ( + 7AF822C62DF0663B00BA4255 /* DAITAMultihopNotice.swift */, 7A95B67C2D5F7C5B00687524 /* DAITASettingsCoordinator.swift */, F041BE4E2C983C2B0083EC28 /* DAITASettingsPromptItem.swift */, 7A8A19132CEF2527000BCB5B /* DAITATunnelSettingsViewModel.swift */, @@ -6484,6 +6488,7 @@ 7AB2B6712BA1EB8C00B03E3B /* ListCustomListCoordinator.swift in Sources */, 582BB1AF229566420055B6EF /* SettingsCell.swift in Sources */, 7AF9BE8E2A331C7B00DBFEDB /* RelayFilterViewModel.swift in Sources */, + 7AF822C72DF0664700BA4255 /* DAITAMultihopNotice.swift in Sources */, 7A8A191E2CEF5CF2000BCB5B /* TunnelSettingsObservable.swift in Sources */, 58F3C0A4249CB069003E76BE /* HeaderBarView.swift in Sources */, 5864AF0829C78849005B0CD9 /* CellFactoryProtocol.swift in Sources */, diff --git a/ios/MullvadVPN/Coordinators/LoginCoordinator.swift b/ios/MullvadVPN/Coordinators/LoginCoordinator.swift index a7dd9dc999..b6f69f95d8 100644 --- a/ios/MullvadVPN/Coordinators/LoginCoordinator.swift +++ b/ios/MullvadVPN/Coordinators/LoginCoordinator.swift @@ -107,11 +107,9 @@ final class LoginCoordinator: Coordinator, Presenting, @preconcurrency DeviceMan } private func returnToLogin(repeatLogin: Bool) { - guard let loginController else { return } - - navigationController.dismiss(animated: true) { - if let lastLoginAction = self.lastLoginAction, repeatLogin { - self.loginController?.start(action: lastLoginAction) + navigationController.dismiss(animated: true) { [weak self] in + if let lastLoginAction = self?.lastLoginAction, repeatLogin { + self?.loginController?.start(action: lastLoginAction) } } } diff --git a/ios/MullvadVPN/Coordinators/Settings/DAITA/DAITAMultihopNotice.swift b/ios/MullvadVPN/Coordinators/Settings/DAITA/DAITAMultihopNotice.swift new file mode 100644 index 0000000000..007fd22cba --- /dev/null +++ b/ios/MullvadVPN/Coordinators/Settings/DAITA/DAITAMultihopNotice.swift @@ -0,0 +1,34 @@ +// +// DAITAMultihopNotice.swift +// MullvadVPN +// +// Created by Jon Petersson on 2025-06-04. +// Copyright © 2025 Mullvad VPN AB. All rights reserved. +// + +import SwiftUI + +struct DAITAMultihopNotice: View { + var body: some View { + HStack(spacing: 8) { + Image(.iconInfo) + .resizable() + .frame(width: 18, height: 18) + .foregroundStyle(Color(.primaryTextColor).opacity(0.6)) + Text(NSLocalizedString( + "SETTINGS_DAITA_MULTIHOP_ENABLED", + tableName: "Settings", + value: "Multihop is being used to enable DAITA for your selected location.", + comment: "" + )) + .font(.mullvadTinySemiBold) + .foregroundColor(Color(.primaryTextColor).opacity(0.6)) + } + } +} + +#Preview { + SettingsInfoContainerView { + DAITAMultihopNotice() + } +} diff --git a/ios/MullvadVPN/Coordinators/Settings/DAITA/DAITATunnelSettingsViewModel.swift b/ios/MullvadVPN/Coordinators/Settings/DAITA/DAITATunnelSettingsViewModel.swift index 4bfa8a06c6..6c900b228f 100644 --- a/ios/MullvadVPN/Coordinators/Settings/DAITA/DAITATunnelSettingsViewModel.swift +++ b/ios/MullvadVPN/Coordinators/Settings/DAITA/DAITATunnelSettingsViewModel.swift @@ -15,6 +15,8 @@ class DAITATunnelSettingsViewModel: TunnelSettingsObserver, ObservableObject { let tunnelManager: TunnelManager var tunnelObserver: TunnelObserver? + var isAutomaticRoutingActive: Bool + var didFailDAITAValidation: (((item: DAITASettingsPromptItem, setting: DAITASettings)) -> Void)? var value: DAITASettings { @@ -30,9 +32,20 @@ class DAITATunnelSettingsViewModel: TunnelSettingsObserver, ObservableObject { self.tunnelManager = tunnelManager value = tunnelManager.settings.daita - tunnelObserver = TunnelBlockObserver(didUpdateTunnelSettings: { [weak self] _, newSettings in - self?.value = newSettings.daita + var isAutomaticRoutingActive: Bool { + tunnelManager.tunnelStatus.state.isMultihop && !tunnelManager.settings.tunnelMultihopState.isEnabled + } + self.isAutomaticRoutingActive = isAutomaticRoutingActive + + let tunnelObserver = TunnelBlockObserver(didUpdateTunnelStatus: { [weak self] _, _ in + if isAutomaticRoutingActive != self?.isAutomaticRoutingActive { + self?.isAutomaticRoutingActive = isAutomaticRoutingActive + self?.objectWillChange.send() + } }) + self.tunnelObserver = tunnelObserver + + tunnelManager.addObserver(tunnelObserver) } func evaluate(setting: DAITASettings) { diff --git a/ios/MullvadVPN/Coordinators/Settings/DAITA/SettingsDAITAView.swift b/ios/MullvadVPN/Coordinators/Settings/DAITA/SettingsDAITAView.swift index 492eab5619..57f6be62cd 100644 --- a/ios/MullvadVPN/Coordinators/Settings/DAITA/SettingsDAITAView.swift +++ b/ios/MullvadVPN/Coordinators/Settings/DAITA/SettingsDAITAView.swift @@ -15,6 +15,16 @@ struct SettingsDAITAView<ViewModel>: View where ViewModel: TunnelSettingsObserva var body: some View { SettingsInfoContainerView { VStack(alignment: .leading, spacing: 8) { + if isAutomaticRoutingActive { + DAITAMultihopNotice() + .padding(EdgeInsets( + top: -UIMetrics.contentInsets.top, + leading: UIMetrics.contentInsets.toEdgeInsets.leading, + bottom: 8, + trailing: UIMetrics.contentInsets.toEdgeInsets.trailing + )) + } + SettingsInfoView(viewModel: dataViewModel) VStack { @@ -93,6 +103,11 @@ extension SettingsDAITAView { } ) } + + var isAutomaticRoutingActive: Bool { + let viewModel = tunnelViewModel as? DAITATunnelSettingsViewModel + return viewModel?.isAutomaticRoutingActive ?? false + } } extension SettingsDAITAView { diff --git a/ios/MullvadVPN/View controllers/InAppPurchase/InAppPurchaseViewController.swift b/ios/MullvadVPN/View controllers/InAppPurchase/InAppPurchaseViewController.swift index 283073bf37..03cd30bf64 100644 --- a/ios/MullvadVPN/View controllers/InAppPurchase/InAppPurchaseViewController.swift +++ b/ios/MullvadVPN/View controllers/InAppPurchase/InAppPurchaseViewController.swift @@ -68,7 +68,7 @@ class InAppPurchaseViewController: UIViewController, StorePaymentObserver { self.errorPresenter.showAlertForError(failure, context: .purchase) { self.didFinish?() } - case let .failure(failure): + case .failure: self.didFinish?() } } @@ -87,7 +87,7 @@ class InAppPurchaseViewController: UIViewController, StorePaymentObserver { self.errorPresenter.showAlertForError(failure, context: .restoration) { self.didFinish?() } - case let .failure(failure): + case .failure: self.didFinish?() } } diff --git a/ios/MullvadVPN/View controllers/OutOfTime/OutOfTimeViewController.swift b/ios/MullvadVPN/View controllers/OutOfTime/OutOfTimeViewController.swift index 40e4291445..19260838ab 100644 --- a/ios/MullvadVPN/View controllers/OutOfTime/OutOfTimeViewController.swift +++ b/ios/MullvadVPN/View controllers/OutOfTime/OutOfTimeViewController.swift @@ -31,7 +31,7 @@ class OutOfTimeViewController: UIViewController, RootContainment { .lightContent } - nonisolated(unsafe) var preferredHeaderBarPresentation: HeaderBarPresentation { + nonisolated var preferredHeaderBarPresentation: HeaderBarPresentation { let tunnelState = interactor.tunnelStatus.state return HeaderBarPresentation( diff --git a/ios/MullvadVPN/View controllers/RelayFilter/ChipViewCell.swift b/ios/MullvadVPN/View controllers/RelayFilter/ChipViewCell.swift index b5d1ae32c0..fda13fdb48 100644 --- a/ios/MullvadVPN/View controllers/RelayFilter/ChipViewCell.swift +++ b/ios/MullvadVPN/View controllers/RelayFilter/ChipViewCell.swift @@ -110,7 +110,7 @@ struct ChipConfiguration: UIContentConfiguration { var group: Group var title: String - var accessibilityId: AccessibilityIdentifier? = nil + var accessibilityId: AccessibilityIdentifier? var textColor: UIColor = .white var font = UIFont.preferredFont(forTextStyle: .caption1) var backgroundColor: UIColor = .primaryColor diff --git a/ios/MullvadVPN/View controllers/Tunnel/ConnectionView/ChipView/ChipFeature.swift b/ios/MullvadVPN/View controllers/Tunnel/ConnectionView/ChipView/ChipFeature.swift index 02cc17f5e7..b9016064b4 100644 --- a/ios/MullvadVPN/View controllers/Tunnel/ConnectionView/ChipView/ChipFeature.swift +++ b/ios/MullvadVPN/View controllers/Tunnel/ConnectionView/ChipView/ChipFeature.swift @@ -31,18 +31,28 @@ enum FeatureType { struct DaitaFeature: ChipFeature { let id: FeatureType = .daita let state: TunnelState + let settings: LatestTunnelSettings var isEnabled: Bool { state.isDaita ?? false } var name: String { - NSLocalizedString( - "FEATURE_INDICATORS_CHIP_DAITA", - tableName: "FeatureIndicatorsChip", - value: "DAITA", - comment: "" - ) + // When multihop is enabled via DAITA without being explicitly enabled + // by the user, display combined indicator instead. + state.isMultihop && !settings.tunnelMultihopState.isEnabled + ? NSLocalizedString( + "FEATURE_INDICATORS_CHIP_DAITA_MULTIHOP", + tableName: "FeatureIndicatorsChip", + value: "DAITA: Multihop", + comment: "" + ) + : NSLocalizedString( + "FEATURE_INDICATORS_CHIP_DAITA", + tableName: "FeatureIndicatorsChip", + value: "DAITA", + comment: "" + ) } } @@ -67,8 +77,12 @@ struct QuantumResistanceFeature: ChipFeature { struct MultihopFeature: ChipFeature { let id: FeatureType = .multihop let state: TunnelState + let settings: LatestTunnelSettings + var isEnabled: Bool { - state.isMultihop + // Multihop indicator should only be visible when user has explicitly turned on + // multihop, not when using multihop via DAITA. + state.isMultihop && settings.tunnelMultihopState.isEnabled } var name: String { diff --git a/ios/MullvadVPN/View controllers/Tunnel/ConnectionView/FeatureIndicatorsViewModel.swift b/ios/MullvadVPN/View controllers/Tunnel/ConnectionView/FeatureIndicatorsViewModel.swift index 5b2ca87561..59a1b6ae74 100644 --- a/ios/MullvadVPN/View controllers/Tunnel/ConnectionView/FeatureIndicatorsViewModel.swift +++ b/ios/MullvadVPN/View controllers/Tunnel/ConnectionView/FeatureIndicatorsViewModel.swift @@ -34,9 +34,9 @@ class FeatureIndicatorsViewModel: ChipViewModelProtocol { case .connecting, .reconnecting, .negotiatingEphemeralPeer, .connected, .pendingReconnect: let features: [any ChipFeature] = [ - DaitaFeature(state: tunnelState), + DaitaFeature(state: tunnelState, settings: tunnelSettings), QuantumResistanceFeature(state: tunnelState), - MultihopFeature(state: tunnelState), + MultihopFeature(state: tunnelState, settings: tunnelSettings), ObfuscationFeature(settings: tunnelSettings, state: observedState), DNSFeature(settings: tunnelSettings), IPOverrideFeature(state: tunnelState, overrides: ipOverrides), diff --git a/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsViewController.swift b/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsViewController.swift index 377cd76247..053b2188b6 100644 --- a/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsViewController.swift +++ b/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsViewController.swift @@ -180,8 +180,8 @@ extension VPNSettingsViewController: @preconcurrency VPNSettingsDataSourceDelega enable ? "Enabling" : "Disabling" - ) “Local network sharing” requires restarting the VPN connection, which will disconnect you and briefly expose your traffic. - To prevent this, manually enable Airplane Mode and turn off Wi-Fi before continuing. + ) “Local network sharing” requires restarting the VPN connection, which will disconnect you and briefly expose your traffic. + To prevent this, manually enable Airplane Mode and turn off Wi-Fi before continuing. Would you like to continue to enable “Local network sharing”? """, comment: "" diff --git a/ios/MullvadVPN/Views/List/MullvadList.swift b/ios/MullvadVPN/Views/List/MullvadList.swift index 51b9fe808b..c951292fb5 100644 --- a/ios/MullvadVPN/Views/List/MullvadList.swift +++ b/ios/MullvadVPN/Views/List/MullvadList.swift @@ -12,7 +12,7 @@ struct MullvadList<Content: View, Data: RandomAccessCollection<ID>, ID: Hashable @State var itemHeight: CGFloat = 0 var maxListHeight: CGFloat { - var height = itemHeight * CGFloat(data.count) + let height = itemHeight * CGFloat(data.count) return height > 0 ? height : .infinity } diff --git a/ios/MullvadVPNUITests/Pages/TunnelControlPage.swift b/ios/MullvadVPNUITests/Pages/TunnelControlPage.swift index 89d1d8ee07..b671be2234 100644 --- a/ios/MullvadVPNUITests/Pages/TunnelControlPage.swift +++ b/ios/MullvadVPNUITests/Pages/TunnelControlPage.swift @@ -199,12 +199,24 @@ class TunnelControlPage: Page { return self } + /// Verify that the app attempts to connect over Multihop. + @discardableResult func verifyNotConnectingOverMultihop() -> Self { + XCTAssertFalse(app.buttons["Multihop"].exists) + return self + } + /// Verify that the app attempts to connect using DAITA. @discardableResult func verifyConnectingUsingDAITA() -> Self { XCTAssertTrue(app.buttons["DAITA"].exists) return self } + /// Verify that the app attempts to connect using DAITA. + @discardableResult func verifyConnectingUsingDAITAThroughMultihop() -> Self { + XCTAssertTrue(app.buttons["DAITA: Multihop"].exists) + return self + } + func getInIPAddressFromConnectionStatus() -> String { let inAddressRow = app.staticTexts[.connectionPanelInAddressRow] return inAddressRow.label.components(separatedBy: ":")[0] diff --git a/ios/MullvadVPNUITests/RelayTests.swift b/ios/MullvadVPNUITests/RelayTests.swift index f1d3c6a501..0decdb1b01 100644 --- a/ios/MullvadVPNUITests/RelayTests.swift +++ b/ios/MullvadVPNUITests/RelayTests.swift @@ -509,6 +509,14 @@ class RelayTests: LoggedInWithTimeUITestCase { TunnelControlPage(app) .waitForConnectedLabel() + .verifyConnectingUsingDAITAThroughMultihop() + .verifyNotConnectingOverMultihop() + .tapSelectLocationButton() + + SelectLocationPage(app) + .tapLocationCell(withName: BaseUITestCase.testsDefaultQuicCountryName) + + TunnelControlPage(app) .verifyConnectingUsingDAITA() .tapDisconnectButton() } diff --git a/ios/PacketTunnel/PacketTunnelProvider/PacketTunnelProvider.swift b/ios/PacketTunnel/PacketTunnelProvider/PacketTunnelProvider.swift index 8be5f883b9..68b09095a8 100644 --- a/ios/PacketTunnel/PacketTunnelProvider/PacketTunnelProvider.swift +++ b/ios/PacketTunnel/PacketTunnelProvider/PacketTunnelProvider.swift @@ -446,4 +446,4 @@ extension PacketTunnelProvider: EphemeralPeerReceiving { // and it will not try to reconnect actor.reconnect(to: .random, reconnectReason: .connectionLoss) } -} +} // swiftlint:disable:this file_length diff --git a/ios/PacketTunnelCoreTests/MultiHopEphemeralPeerExchangerTests.swift b/ios/PacketTunnelCoreTests/MultiHopEphemeralPeerExchangerTests.swift index 7221e72a55..c77211b5fa 100644 --- a/ios/PacketTunnelCoreTests/MultiHopEphemeralPeerExchangerTests.swift +++ b/ios/PacketTunnelCoreTests/MultiHopEphemeralPeerExchangerTests.swift @@ -160,7 +160,7 @@ final class MultiHopEphemeralPeerExchangerTests: XCTestCase { keyExchanger: peerExchangeActor, enablePostQuantum: false, enableDaita: true - ) { params in + ) { _ in reconfigurationExpectation.fulfill() } onFinish: { negotiationSuccessful.fulfill() |
