Skip to content

Commit 9f40be3

Browse files
author
Jon Petersson
committed
Adjust relay selector to support custom lists
1 parent 88fcf98 commit 9f40be3

File tree

6 files changed

+80
-25
lines changed

6 files changed

+80
-25
lines changed

ios/MullvadREST/Relay/RelaySelector.swift

+18-14
Original file line numberDiff line numberDiff line change
@@ -150,24 +150,28 @@ public enum RelaySelector {
150150
}
151151
}
152152

153-
switch constraints.location {
153+
switch constraints.locations {
154154
case .any:
155155
return true
156156
case let .only(relayConstraint):
157-
switch relayConstraint {
158-
case let .country(countryCode):
159-
return relayWithLocation.serverLocation.countryCode == countryCode &&
160-
relayWithLocation.relay.includeInCountry
161-
162-
case let .city(countryCode, cityCode):
163-
return relayWithLocation.serverLocation.countryCode == countryCode &&
164-
relayWithLocation.serverLocation.cityCode == cityCode
165-
166-
case let .hostname(countryCode, cityCode, hostname):
167-
return relayWithLocation.serverLocation.countryCode == countryCode &&
168-
relayWithLocation.serverLocation.cityCode == cityCode &&
169-
relayWithLocation.relay.hostname == hostname
157+
for location in relayConstraint.locations {
158+
switch location {
159+
case let .country(countryCode):
160+
return relayWithLocation.serverLocation.countryCode == countryCode &&
161+
relayWithLocation.relay.includeInCountry
162+
163+
case let .city(countryCode, cityCode):
164+
return relayWithLocation.serverLocation.countryCode == countryCode &&
165+
relayWithLocation.serverLocation.cityCode == cityCode
166+
167+
case let .hostname(countryCode, cityCode, hostname):
168+
return relayWithLocation.serverLocation.countryCode == countryCode &&
169+
relayWithLocation.serverLocation.cityCode == cityCode &&
170+
relayWithLocation.relay.hostname == hostname
171+
}
170172
}
173+
174+
return false
171175
}
172176
}.filter { relayWithLocation -> Bool in
173177
relayWithLocation.relay.active

ios/MullvadTypes/RelayConstraints.swift

+32-5
Original file line numberDiff line numberDiff line change
@@ -21,32 +21,59 @@ public class RelayConstraintsUpdater: ConstraintsPropagation {
2121
}
2222

2323
public struct RelayConstraints: Codable, Equatable, CustomDebugStringConvertible {
24-
public var location: RelayConstraint<RelayLocation>
24+
@available(*, deprecated, renamed: "locations")
25+
private var location: RelayConstraint<RelayLocation> = .only(.country("se"))
2526

2627
// Added in 2023.3
2728
public var port: RelayConstraint<UInt16>
2829
public var filter: RelayConstraint<RelayFilter>
2930

31+
// Added in 2024.1
32+
public var locations: RelayConstraint<RelayLocations>
33+
3034
public var debugDescription: String {
31-
"RelayConstraints { location: \(location), port: \(port) }"
35+
"RelayConstraints { locations: \(locations), port: \(port) }"
3236
}
3337

3438
public init(
35-
location: RelayConstraint<RelayLocation> = .only(.country("se")),
39+
locations: RelayConstraint<RelayLocations> = .only(RelayLocations(locations: [.country("se")])),
3640
port: RelayConstraint<UInt16> = .any,
3741
filter: RelayConstraint<RelayFilter> = .any
3842
) {
39-
self.location = location
43+
self.locations = locations
4044
self.port = port
4145
self.filter = filter
4246
}
4347

4448
public init(from decoder: Decoder) throws {
4549
let container = try decoder.container(keyedBy: CodingKeys.self)
46-
location = try container.decode(RelayConstraint<RelayLocation>.self, forKey: .location)
4750

4851
// Added in 2023.3
4952
port = try container.decodeIfPresent(RelayConstraint<UInt16>.self, forKey: .port) ?? .any
5053
filter = try container.decodeIfPresent(RelayConstraint<RelayFilter>.self, forKey: .filter) ?? .any
54+
55+
// Added in 2024.1
56+
locations = try container.decodeIfPresent(RelayConstraint<RelayLocations>.self, forKey: .locations)
57+
?? Self.migrateLocations(decoder: decoder)
58+
?? .only(RelayLocations(locations: [.country("se")]))
59+
}
60+
}
61+
62+
extension RelayConstraints {
63+
private static func migrateLocations(decoder: Decoder) -> RelayConstraint<RelayLocations>? {
64+
let container = try? decoder.container(keyedBy: CodingKeys.self)
65+
66+
guard
67+
let location = try? container?.decodeIfPresent(RelayConstraint<RelayLocation>.self, forKey: .location)
68+
else {
69+
return nil
70+
}
71+
72+
switch location {
73+
case .any:
74+
return .any
75+
case let .only(location):
76+
return .only(RelayLocations(locations: [location]))
77+
}
5178
}
5279
}

ios/MullvadTypes/RelayLocation.swift

+10
Original file line numberDiff line numberDiff line change
@@ -106,3 +106,13 @@ public enum RelayLocation: Codable, Hashable, CustomDebugStringConvertible {
106106
}
107107
}
108108
}
109+
110+
public struct RelayLocations: Codable, Equatable {
111+
public let locations: [RelayLocation]
112+
public let customListId: UUID?
113+
114+
public init(locations: [RelayLocation], customListId: UUID? = nil) {
115+
self.locations = locations
116+
self.customListId = customListId
117+
}
118+
}

ios/MullvadVPN.xcodeproj/project.pbxproj

+12-2
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,10 @@
3838
06799AFC28F98EE300ACD94E /* AddressCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06AC114128F8413A0037AF9A /* AddressCache.swift */; };
3939
0697D6E728F01513007A9E99 /* TransportMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0697D6E628F01513007A9E99 /* TransportMonitor.swift */; };
4040
06AC116228F94C450037AF9A /* ApplicationConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58BFA5CB22A7CE1F00A6173D /* ApplicationConfiguration.swift */; };
41-
44DD7D2D2B74E44A0005F67F /* QuantumResistanceSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44DD7D2C2B74E44A0005F67F /* QuantumResistanceSettings.swift */; };
4241
44DD7D242B6CFFD70005F67F /* StartTunnelOperationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44DD7D232B6CFFD70005F67F /* StartTunnelOperationTests.swift */; };
4342
44DD7D272B6D18FB0005F67F /* MockTunnelInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44DD7D262B6D18FB0005F67F /* MockTunnelInteractor.swift */; };
4443
44DD7D292B7113CA0005F67F /* MockTunnel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44DD7D282B7113CA0005F67F /* MockTunnel.swift */; };
44+
44DD7D2D2B74E44A0005F67F /* QuantumResistanceSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44DD7D2C2B74E44A0005F67F /* QuantumResistanceSettings.swift */; };
4545
5803B4B02940A47300C23744 /* TunnelConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5803B4AF2940A47300C23744 /* TunnelConfiguration.swift */; };
4646
5803B4B22940A48700C23744 /* TunnelStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5803B4B12940A48700C23744 /* TunnelStore.swift */; };
4747
5807E2C02432038B00F5FF30 /* String+Split.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5807E2BF2432038B00F5FF30 /* String+Split.swift */; };
@@ -1243,10 +1243,10 @@
12431243
06FAE67A28F83CA50033DD93 /* RESTDevicesProxy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RESTDevicesProxy.swift; sourceTree = "<group>"; };
12441244
06FAE67B28F83CA50033DD93 /* REST.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = REST.swift; sourceTree = "<group>"; };
12451245
06FAE67D28F83CA50033DD93 /* RESTTransport.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RESTTransport.swift; sourceTree = "<group>"; };
1246-
44DD7D2C2B74E44A0005F67F /* QuantumResistanceSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuantumResistanceSettings.swift; sourceTree = "<group>"; };
12471246
44DD7D232B6CFFD70005F67F /* StartTunnelOperationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StartTunnelOperationTests.swift; sourceTree = "<group>"; };
12481247
44DD7D262B6D18FB0005F67F /* MockTunnelInteractor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockTunnelInteractor.swift; sourceTree = "<group>"; };
12491248
44DD7D282B7113CA0005F67F /* MockTunnel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockTunnel.swift; sourceTree = "<group>"; };
1249+
44DD7D2C2B74E44A0005F67F /* QuantumResistanceSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuantumResistanceSettings.swift; sourceTree = "<group>"; };
12501250
5802EBC42A8E44AC00E5CE4C /* AppRoutes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppRoutes.swift; sourceTree = "<group>"; };
12511251
5802EBC62A8E457A00E5CE4C /* AppRouteProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppRouteProtocol.swift; sourceTree = "<group>"; };
12521252
5802EBC82A8E45BA00E5CE4C /* ApplicationRouterDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApplicationRouterDelegate.swift; sourceTree = "<group>"; };
@@ -1658,6 +1658,7 @@
16581658
58FF9FEF2B07C4D300E4C97D /* PersistentAccessMethod+ViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PersistentAccessMethod+ViewModel.swift"; sourceTree = "<group>"; };
16591659
58FF9FF32B07C61B00E4C97D /* AccessMethodValidationError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccessMethodValidationError.swift; sourceTree = "<group>"; };
16601660
7A02D4EA2A9CEC7A00C19E31 /* MullvadVPNScreenshots.xctestplan */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = MullvadVPNScreenshots.xctestplan; sourceTree = "<group>"; };
1661+
7A038FDB2B7A17EA00950251 /* TunnelSettingsV4.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelSettingsV4.swift; sourceTree = "<group>"; };
16611662
7A09C98029D99215000C2CAC /* String+FuzzyMatch.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+FuzzyMatch.swift"; sourceTree = "<group>"; };
16621663
7A0B311D2B303A0D004B12E0 /* AccessbilityIdentifier.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccessbilityIdentifier.swift; sourceTree = "<group>"; };
16631664
7A0C0F622A979C4A0058EFCE /* Coordinator+Router.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Coordinator+Router.swift"; sourceTree = "<group>"; };
@@ -2997,6 +2998,7 @@
29972998
7A88DCDD2A8FABBE00D2FF0E /* RoutingTests */,
29982999
58CE5E61224146200008646E /* Products */,
29993000
584F991F2902CBDD001F858D /* Frameworks */,
3001+
7A038FDD2B7A56CF00950251 /* Recovered References */,
30003002
);
30013003
sourceTree = "<group>";
30023004
};
@@ -3300,6 +3302,14 @@
33003302
path = Edit;
33013303
sourceTree = "<group>";
33023304
};
3305+
7A038FDD2B7A56CF00950251 /* Recovered References */ = {
3306+
isa = PBXGroup;
3307+
children = (
3308+
7A038FDB2B7A17EA00950251 /* TunnelSettingsV4.swift */,
3309+
);
3310+
name = "Recovered References";
3311+
sourceTree = "<group>";
3312+
};
33033313
7A2960F72A964A3500389B82 /* Alert */ = {
33043314
isa = PBXGroup;
33053315
children = (

ios/MullvadVPN/Coordinators/SelectLocationCoordinator.swift

+6-2
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,10 @@ class SelectLocationCoordinator: Coordinator, Presentable, Presenting, RelayCach
5656
guard let self else { return }
5757

5858
var relayConstraints = tunnelManager.settings.relayConstraints
59-
relayConstraints.location = .only(relay)
59+
relayConstraints.locations = .only(RelayLocations(
60+
locations: [relay],
61+
customListId: nil
62+
))
6063

6164
tunnelManager.setRelayConstraints(relayConstraints) {
6265
self.tunnelManager.startTunnel()
@@ -96,7 +99,8 @@ class SelectLocationCoordinator: Coordinator, Presentable, Presenting, RelayCach
9699
selectLocationViewController.setCachedRelays(cachedRelays, filter: relayFilter)
97100
}
98101

99-
selectLocationViewController.relayLocation = tunnelManager.settings.relayConstraints.location.value
102+
selectLocationViewController.relayLocation =
103+
tunnelManager.settings.relayConstraints.locations.value?.locations.first
100104

101105
navigationController.pushViewController(selectLocationViewController, animated: false)
102106
}

ios/MullvadVPNTests/StartTunnelOperationTests.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ class StartTunnelOperationTests: XCTestCase {
7575
let operation = StartTunnelOperation(
7676
dispatchQueue: testQueue,
7777
interactor: interactor
78-
) { result in
78+
) { _ in
7979
XCTAssertEqual(tunnelStatus.state, .disconnecting(.reconnect))
8080
expectation.fulfill()
8181
}
@@ -89,7 +89,7 @@ class StartTunnelOperationTests: XCTestCase {
8989
let operation = StartTunnelOperation(
9090
dispatchQueue: testQueue,
9191
interactor: interactor
92-
) { result in
92+
) { _ in
9393
XCTAssertNotNil(interactor.tunnel)
9494
XCTAssertNotNil(interactor.tunnel?.startDate)
9595
expectation.fulfill()

0 commit comments

Comments
 (0)