Skip to content

Commit 080e9aa

Browse files
mojganiikl
authored andcommitted
Show number of available relays in filter view
1 parent d739b82 commit 080e9aa

23 files changed

+485
-327
lines changed

Diff for: ios/CHANGELOG.md

+3
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ Line wrap the file at 100 chars. Th
2525
### Added
2626
- Make account number copyable on welcome screen.
2727

28+
### Changed
29+
- Improve the filter view to display the number of available servers based on selected criteria.
30+
2831
## 2025.2 - 2025-02-08
2932
### Added
3033
- Add different themes for app icons

Diff for: ios/MullvadMockData/MullvadREST/RelaySelectorStub.swift

+18-5
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,14 @@ import WireGuardKitTypes
1414
/// Relay selector stub that accepts a block that can be used to provide custom implementation.
1515
public final class RelaySelectorStub: RelaySelectorProtocol {
1616
var selectedRelaysResult: (UInt) throws -> SelectedRelays
17+
var candidatesResult: (() throws -> RelayCandidates)?
1718

18-
init(selectedRelaysResult: @escaping (UInt) throws -> SelectedRelays) {
19+
init(
20+
selectedRelaysResult: @escaping (UInt) throws -> SelectedRelays,
21+
candidatesResult: (() throws -> RelayCandidates)? = nil
22+
) {
1923
self.selectedRelaysResult = selectedRelaysResult
24+
self.candidatesResult = candidatesResult
2025
}
2126

2227
public func selectRelays(
@@ -25,14 +30,20 @@ public final class RelaySelectorStub: RelaySelectorProtocol {
2530
) throws -> SelectedRelays {
2631
return try selectedRelaysResult(connectionAttemptCount)
2732
}
33+
34+
public func findCandidates(
35+
tunnelSettings: LatestTunnelSettings
36+
) throws -> RelayCandidates {
37+
return try candidatesResult?() ?? RelayCandidates(entryRelays: [], exitRelays: [])
38+
}
2839
}
2940

3041
extension RelaySelectorStub {
3142
/// Returns a relay selector that never fails.
3243
public static func nonFallible() -> RelaySelectorStub {
3344
let publicKey = PrivateKey().publicKey.rawValue
3445

35-
return RelaySelectorStub { _ in
46+
return RelaySelectorStub(selectedRelaysResult: { _ in
3647
let cityRelay = SelectedRelay(
3748
endpoint: MullvadEndpoint(
3849
ipv4Relay: IPv4Endpoint(ip: .loopback, port: 1300),
@@ -56,13 +67,15 @@ extension RelaySelectorStub {
5667
exit: cityRelay,
5768
retryAttempt: 0
5869
)
59-
}
70+
}, candidatesResult: nil)
6071
}
6172

6273
/// Returns a relay selector that cannot satisfy constraints .
6374
public static func unsatisfied() -> RelaySelectorStub {
64-
return RelaySelectorStub { _ in
75+
return RelaySelectorStub(selectedRelaysResult: { _ in
76+
throw NoRelaysSatisfyingConstraintsError(.relayConstraintNotMatching)
77+
}, candidatesResult: {
6578
throw NoRelaysSatisfyingConstraintsError(.relayConstraintNotMatching)
66-
}
79+
})
6780
}
6881
}

Diff for: ios/MullvadREST/Relay/RelayCandidates.swift

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
//
2+
// RelayCandidates.swift
3+
// MullvadVPN
4+
//
5+
// Created by Mojgan on 2025-03-03.
6+
// Copyright © 2025 Mullvad VPN AB. All rights reserved.
7+
//
8+
9+
public struct RelayCandidates {
10+
public let entryRelays: [RelayWithLocation<REST.ServerRelay>]?
11+
public let exitRelays: [RelayWithLocation<REST.ServerRelay>]
12+
public init(
13+
entryRelays: [RelayWithLocation<REST.ServerRelay>]?,
14+
exitRelays: [RelayWithLocation<REST.ServerRelay>]
15+
) {
16+
self.entryRelays = entryRelays
17+
self.exitRelays = exitRelays
18+
}
19+
}

Diff for: ios/MullvadREST/Relay/RelaySelector.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ public enum RelaySelector {
1515
// MARK: - public
1616

1717
/// Determines whether a `REST.ServerRelay` satisfies the given relay filter.
18-
public static func relayMatchesFilter(_ relay: AnyRelay, filter: RelayFilter) -> Bool {
18+
static func relayMatchesFilter(_ relay: AnyRelay, filter: RelayFilter) -> Bool {
1919
if case let .only(providers) = filter.providers, providers.contains(relay.provider) == false {
2020
return false
2121
}

Diff for: ios/MullvadREST/Relay/RelaySelectorProtocol.swift

+4
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ public protocol RelaySelectorProtocol {
1616
tunnelSettings: LatestTunnelSettings,
1717
connectionAttemptCount: UInt
1818
) throws -> SelectedRelays
19+
20+
func findCandidates(
21+
tunnelSettings: LatestTunnelSettings
22+
) throws -> RelayCandidates
1923
}
2024

2125
/// Struct describing the selected relay.

Diff for: ios/MullvadREST/Relay/RelaySelectorWrapper.swift

+39-7
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import MullvadSettings
1010
import MullvadTypes
1111

1212
public final class RelaySelectorWrapper: RelaySelectorProtocol, Sendable {
13-
let relayCache: RelayCacheProtocol
13+
public let relayCache: RelayCacheProtocol
1414

1515
public init(relayCache: RelayCacheProtocol) {
1616
self.relayCache = relayCache
@@ -20,12 +20,7 @@ public final class RelaySelectorWrapper: RelaySelectorProtocol, Sendable {
2020
tunnelSettings: LatestTunnelSettings,
2121
connectionAttemptCount: UInt
2222
) throws -> SelectedRelays {
23-
let obfuscation = try ObfuscatorPortSelector(
24-
relays: try relayCache.read().relays
25-
).obfuscate(
26-
tunnelSettings: tunnelSettings,
27-
connectionAttemptCount: connectionAttemptCount
28-
)
23+
let obfuscation = try prepareObfuscation(for: tunnelSettings, connectionAttemptCount: connectionAttemptCount)
2924

3025
return switch tunnelSettings.tunnelMultihopState {
3126
case .off:
@@ -44,4 +39,41 @@ public final class RelaySelectorWrapper: RelaySelectorProtocol, Sendable {
4439
).pick()
4540
}
4641
}
42+
43+
public func findCandidates(tunnelSettings: LatestTunnelSettings) throws -> RelayCandidates {
44+
let obfuscation = try prepareObfuscation(for: tunnelSettings, connectionAttemptCount: 0)
45+
46+
let findCandidates: (REST.ServerRelaysResponse, Bool) throws
47+
-> [RelayWithLocation<REST.ServerRelay>] = { relays, daitaEnabled in
48+
try RelaySelector.WireGuard.findCandidates(
49+
by: .any,
50+
in: relays,
51+
filterConstraint: tunnelSettings.relayConstraints.filter,
52+
daitaEnabled: daitaEnabled
53+
)
54+
}
55+
56+
if tunnelSettings.daita.isAutomaticRouting || tunnelSettings.tunnelMultihopState.isEnabled {
57+
let entryCandidates = try findCandidates(
58+
tunnelSettings.tunnelMultihopState.isEnabled ? obfuscation.entryRelays : obfuscation.exitRelays,
59+
tunnelSettings.daita.daitaState.isEnabled
60+
)
61+
let exitCandidates = try findCandidates(obfuscation.exitRelays, false)
62+
return RelayCandidates(entryRelays: entryCandidates, exitRelays: exitCandidates)
63+
} else {
64+
let exitCandidates = try findCandidates(obfuscation.exitRelays, tunnelSettings.daita.daitaState.isEnabled)
65+
return RelayCandidates(entryRelays: nil, exitRelays: exitCandidates)
66+
}
67+
}
68+
69+
private func prepareObfuscation(
70+
for tunnelSettings: LatestTunnelSettings,
71+
connectionAttemptCount: UInt
72+
) throws -> ObfuscatorPortSelection {
73+
let relays = try relayCache.read().relays
74+
return try ObfuscatorPortSelector(relays: relays).obfuscate(
75+
tunnelSettings: tunnelSettings,
76+
connectionAttemptCount: connectionAttemptCount
77+
)
78+
}
4779
}

Diff for: ios/MullvadREST/Relay/RelayWithLocation.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import Foundation
1010
import MullvadTypes
1111

1212
public struct RelayWithLocation<T: AnyRelay> {
13-
let relay: T
13+
public let relay: T
1414
public let serverLocation: Location
1515

1616
public func matches(location: RelayLocation) -> Bool {

Diff for: ios/MullvadVPN.xcodeproj/project.pbxproj

+13-5
Original file line numberDiff line numberDiff line change
@@ -976,6 +976,7 @@
976976
F07751572C50F149006E6A12 /* EphemeralPeerExchangingPipelineTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F053F4B92C4A94D300FBD937 /* EphemeralPeerExchangingPipelineTests.swift */; };
977977
F07751582C50F149006E6A12 /* MultiHopEphemeralPeerExchangerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0C4C9BD2C49477B00A79006 /* MultiHopEphemeralPeerExchangerTests.swift */; };
978978
F07751592C50F149006E6A12 /* SingleHopEphemeralPeerExchangerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0A163882C47B46300592300 /* SingleHopEphemeralPeerExchangerTests.swift */; };
979+
F0791F1B2D76377500449F6D /* RelayCandidates.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0791F1A2D76377400449F6D /* RelayCandidates.swift */; };
979980
F07B53572C53B5270024F547 /* LocalNetworkIPs.swift in Sources */ = {isa = PBXBuildFile; fileRef = F07B53562C53B5270024F547 /* LocalNetworkIPs.swift */; };
980981
F07BF2622A26279100042943 /* RedeemVoucherOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = F07BF2612A26279100042943 /* RedeemVoucherOperation.swift */; };
981982
F07C9D952B220C77006F1C5E /* libmullvad_ios.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 01F1FF1D29F0627D007083C3 /* libmullvad_ios.a */; };
@@ -1034,11 +1035,12 @@
10341035
F0B495762D02025200CFEC2A /* ChipContainerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0B495752D02025200CFEC2A /* ChipContainerView.swift */; };
10351036
F0B495782D02038B00CFEC2A /* ChipViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0B495772D02038B00CFEC2A /* ChipViewModelProtocol.swift */; };
10361037
F0B4957A2D02F49200CFEC2A /* ChipFeature.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0B495792D02F41F00CFEC2A /* ChipFeature.swift */; };
1038+
F0B583D42D6DCE12007F5AE4 /* FilterDescriptor.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0B583D32D6DCE0D007F5AE4 /* FilterDescriptor.swift */; };
10371039
F0B894EF2BF751C500817A42 /* RelayWithLocation.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0B894EE2BF751C500817A42 /* RelayWithLocation.swift */; };
10381040
F0B894F12BF751E300817A42 /* RelayWithDistance.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0B894F02BF751E300817A42 /* RelayWithDistance.swift */; };
10391041
F0B894F32BF7526700817A42 /* RelaySelector+Wireguard.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0B894F22BF7526700817A42 /* RelaySelector+Wireguard.swift */; };
10401042
F0B894F52BF7528700817A42 /* RelaySelector+Shadowsocks.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0B894F42BF7528700817A42 /* RelaySelector+Shadowsocks.swift */; };
1041-
F0BE65372B9F136A005CC385 /* LocationSectionHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0BE65362B9F136A005CC385 /* LocationSectionHeaderView.swift */; };
1043+
F0BE65372B9F136A005CC385 /* LocationSectionHeaderFooterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0BE65362B9F136A005CC385 /* LocationSectionHeaderFooterView.swift */; };
10421044
F0C13FE42C64F7CB00BD087D /* DAITASettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0C13FE32C64F7CB00BD087D /* DAITASettings.swift */; };
10431045
F0C13FE62C64FB3400BD087D /* TunnelSettingsV6.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0C13FE52C64FB3400BD087D /* TunnelSettingsV6.swift */; };
10441046
F0C2AEFD2A0BB5CC00986207 /* NotificationProviderIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0C2AEFC2A0BB5CC00986207 /* NotificationProviderIdentifier.swift */; };
@@ -2386,6 +2388,7 @@
23862388
F072D3CE2C07122400906F64 /* SettingsUpdaterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsUpdaterTests.swift; sourceTree = "<group>"; };
23872389
F072D3D12C071AD100906F64 /* ShadowsocksLoaderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShadowsocksLoaderTests.swift; sourceTree = "<group>"; };
23882390
F073FCB22C6617D70062EA1D /* TunnelStore+Stubs.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "TunnelStore+Stubs.swift"; sourceTree = "<group>"; };
2391+
F0791F1A2D76377400449F6D /* RelayCandidates.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelayCandidates.swift; sourceTree = "<group>"; };
23892392
F07B53562C53B5270024F547 /* LocalNetworkIPs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalNetworkIPs.swift; sourceTree = "<group>"; };
23902393
F07BF2572A26112D00042943 /* InputTextFormatterTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InputTextFormatterTests.swift; sourceTree = "<group>"; };
23912394
F07BF2612A26279100042943 /* RedeemVoucherOperation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RedeemVoucherOperation.swift; sourceTree = "<group>"; };
@@ -2421,11 +2424,12 @@
24212424
F0B495752D02025200CFEC2A /* ChipContainerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChipContainerView.swift; sourceTree = "<group>"; };
24222425
F0B495772D02038B00CFEC2A /* ChipViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChipViewModelProtocol.swift; sourceTree = "<group>"; };
24232426
F0B495792D02F41F00CFEC2A /* ChipFeature.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChipFeature.swift; sourceTree = "<group>"; };
2427+
F0B583D32D6DCE0D007F5AE4 /* FilterDescriptor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilterDescriptor.swift; sourceTree = "<group>"; };
24242428
F0B894EE2BF751C500817A42 /* RelayWithLocation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelayWithLocation.swift; sourceTree = "<group>"; };
24252429
F0B894F02BF751E300817A42 /* RelayWithDistance.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelayWithDistance.swift; sourceTree = "<group>"; };
24262430
F0B894F22BF7526700817A42 /* RelaySelector+Wireguard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "RelaySelector+Wireguard.swift"; sourceTree = "<group>"; };
24272431
F0B894F42BF7528700817A42 /* RelaySelector+Shadowsocks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "RelaySelector+Shadowsocks.swift"; sourceTree = "<group>"; };
2428-
F0BE65362B9F136A005CC385 /* LocationSectionHeaderView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LocationSectionHeaderView.swift; sourceTree = "<group>"; };
2432+
F0BE65362B9F136A005CC385 /* LocationSectionHeaderFooterView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LocationSectionHeaderFooterView.swift; sourceTree = "<group>"; };
24292433
F0C13FE32C64F7CB00BD087D /* DAITASettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DAITASettings.swift; sourceTree = "<group>"; };
24302434
F0C13FE52C64FB3400BD087D /* TunnelSettingsV6.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelSettingsV6.swift; sourceTree = "<group>"; };
24312435
F0C2AEFC2A0BB5CC00986207 /* NotificationProviderIdentifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationProviderIdentifier.swift; sourceTree = "<group>"; };
@@ -3118,7 +3122,7 @@
31183122
7A6389F72B864CDF008E77E1 /* LocationNode.swift */,
31193123
7A5468AB2C6A55B100590086 /* LocationRelays.swift */,
31203124
F050AE512B70DFC0003F4EDB /* LocationSection.swift */,
3121-
F0BE65362B9F136A005CC385 /* LocationSectionHeaderView.swift */,
3125+
F0BE65362B9F136A005CC385 /* LocationSectionHeaderFooterView.swift */,
31223126
5888AD86227B17950051EB06 /* LocationViewController.swift */,
31233127
7AB3BEB42BD7A6CB00E34384 /* LocationViewControllerWrapper.swift */,
31243128
F01DAE322C2B032A00521E46 /* RelaySelection.swift */,
@@ -4312,6 +4316,7 @@
43124316
F0ADC3712CD3AD1600A1AD97 /* ChipCollectionView.swift */,
43134317
F0ADC3732CD3C47400A1AD97 /* ChipFlowLayout.swift */,
43144318
7AF9BE962A41C71F00DBFEDB /* ChipViewCell.swift */,
4319+
F0B583D32D6DCE0D007F5AE4 /* FilterDescriptor.swift */,
43154320
7A1A26482A29D48A00B978AA /* RelayFilterCellFactory.swift */,
43164321
7A1A26462A29CF0800B978AA /* RelayFilterDataSource.swift */,
43174322
7AF9BE942A40461100DBFEDB /* RelayFilterView.swift */,
@@ -4621,7 +4626,6 @@
46214626
F0DC779F2B2222D20087F09D /* Relay */ = {
46224627
isa = PBXGroup;
46234628
children = (
4624-
7AFBE38E2D09AB4E002335FC /* RelayPicking */,
46254629
7ADCB2D72B6A6EB300C88F89 /* AnyRelay.swift */,
46264630
585DA87626B024A600B8C587 /* CachedRelays.swift */,
46274631
F0DDE4272B220A15006B57A7 /* Haversine.swift */,
@@ -4633,6 +4637,8 @@
46334637
7AD63A3A2CD5278900445268 /* ObfuscationMethodSelector.swift */,
46344638
7AD63A382CD520FD00445268 /* ObfuscatorPortSelector.swift */,
46354639
5820675A26E6576800655B05 /* RelayCache.swift */,
4640+
7AFBE38E2D09AB4E002335FC /* RelayPicking */,
4641+
F0791F1A2D76377400449F6D /* RelayCandidates.swift */,
46364642
F0DDE4282B220A15006B57A7 /* RelaySelector.swift */,
46374643
F0B894F42BF7528700817A42 /* RelaySelector+Shadowsocks.swift */,
46384644
F0B894F22BF7526700817A42 /* RelaySelector+Wireguard.swift */,
@@ -5682,6 +5688,7 @@
56825688
06799AEC28F98E4800ACD94E /* RESTTaskIdentifier.swift in Sources */,
56835689
7A2E7B712D6C9FE0009EF2C3 /* APIError.swift in Sources */,
56845690
58E7BA192A975DF70068EC3A /* RESTTransportProvider.swift in Sources */,
5691+
F0791F1B2D76377500449F6D /* RelayCandidates.swift in Sources */,
56855692
F0B894F52BF7528700817A42 /* RelaySelector+Shadowsocks.swift in Sources */,
56865693
06799ADE28F98E4800ACD94E /* RESTRequestHandler.swift in Sources */,
56875694
F0DDE4162B220458006B57A7 /* TransportProvider.swift in Sources */,
@@ -6204,7 +6211,7 @@
62046211
7ABE318D2A1CDD4500DF4963 /* UIFont+Weight.swift in Sources */,
62056212
58C774BE29A7A249003A1A56 /* CustomNavigationController.swift in Sources */,
62066213
E1FD0DF528AA7CE400299DB4 /* StatusActivityView.swift in Sources */,
6207-
F0BE65372B9F136A005CC385 /* LocationSectionHeaderView.swift in Sources */,
6214+
F0BE65372B9F136A005CC385 /* LocationSectionHeaderFooterView.swift in Sources */,
62086215
7A2960FD2A964BB700389B82 /* AlertPresentation.swift in Sources */,
62096216
0697D6E728F01513007A9E99 /* TransportMonitor.swift in Sources */,
62106217
58968FAE28743E2000B799DC /* TunnelInteractor.swift in Sources */,
@@ -6439,6 +6446,7 @@
64396446
584592612639B4A200EF967F /* TermsOfServiceContentView.swift in Sources */,
64406447
5875960A26F371FC00BF6711 /* Tunnel+Messaging.swift in Sources */,
64416448
586C0D912B03D8A400E7CDD7 /* AccessMethodHeaderFooterReuseIdentifier.swift in Sources */,
6449+
F0B583D42D6DCE12007F5AE4 /* FilterDescriptor.swift in Sources */,
64426450
7A2960F62A963F7500389B82 /* AlertCoordinator.swift in Sources */,
64436451
F050AE522B70DFC0003F4EDB /* LocationSection.swift in Sources */,
64446452
063687BA28EB234F00BE7161 /* PacketTunnelTransport.swift in Sources */,

Diff for: ios/MullvadVPN/AppDelegate.swift

+2-1
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
5151
private(set) var shadowsocksLoader: ShadowsocksLoaderProtocol!
5252
private(set) var configuredTransportProvider: ProxyConfigurationTransportProvider!
5353
private(set) var ipOverrideRepository = IPOverrideRepository()
54+
private(set) var relaySelector: RelaySelectorWrapper!
5455
private var launchArguments = LaunchArguments()
5556
private var encryptedDNSTransport: EncryptedDNSTransport!
5657

@@ -105,7 +106,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
105106

106107
tunnelStore = TunnelStore(application: backgroundTaskProvider)
107108

108-
let relaySelector = RelaySelectorWrapper(
109+
relaySelector = RelaySelectorWrapper(
109110
relayCache: ipOverrideWrapper
110111
)
111112
tunnelManager = createTunnelManager(

0 commit comments

Comments
 (0)