summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAndrej Mihajlov <and@mullvad.net>2022-07-27 15:43:42 +0200
committerAndrej Mihajlov <and@mullvad.net>2022-07-27 15:43:42 +0200
commitfca8b08effbab2025507c70cb46c7d94c5b06b17 (patch)
treebf1b702e35fd1fde047f20674f2fc45ac463c553
parent469efb8d3d0a395a3ddbf9a1506d457256a94f45 (diff)
parentf9b8734dfb15b265e1404d0427ed50f6de350142 (diff)
downloadmullvadvpn-fca8b08effbab2025507c70cb46c7d94c5b06b17.tar.xz
mullvadvpn-fca8b08effbab2025507c70cb46c7d94c5b06b17.zip
Merge branch 'relay-erase-errors'
-rw-r--r--ios/MullvadVPN.xcodeproj/project.pbxproj6
-rw-r--r--ios/MullvadVPN/AppDelegate.swift2
-rw-r--r--ios/MullvadVPN/RelayCache/RelayCacheError.swift43
-rw-r--r--ios/MullvadVPN/RelayCache/RelayCacheIO.swift82
-rw-r--r--ios/MullvadVPN/RelayCache/RelayCacheTracker.swift63
-rw-r--r--ios/MullvadVPN/RelaySelector.swift12
-rw-r--r--ios/MullvadVPN/SceneDelegate.swift2
-rw-r--r--ios/MullvadVPN/SimulatorTunnelProviderHost.swift4
-rw-r--r--ios/MullvadVPN/TunnelManager/StartTunnelOperation.swift8
-rw-r--r--ios/MullvadVPNTests/RelaySelectorTests.swift18
-rw-r--r--ios/PacketTunnel/PacketTunnelProvider.swift2
11 files changed, 90 insertions, 152 deletions
diff --git a/ios/MullvadVPN.xcodeproj/project.pbxproj b/ios/MullvadVPN.xcodeproj/project.pbxproj
index a3b3440984..75009f9de2 100644
--- a/ios/MullvadVPN.xcodeproj/project.pbxproj
+++ b/ios/MullvadVPN.xcodeproj/project.pbxproj
@@ -45,7 +45,6 @@
5819C2172729595500D6EC38 /* SettingsAddDNSEntryCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5819C2162729595500D6EC38 /* SettingsAddDNSEntryCell.swift */; };
5820674E26E6510200655B05 /* REST.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5820674D26E6510200655B05 /* REST.swift */; };
5820675026E6514100655B05 /* HTTP.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5820674F26E6514100655B05 /* HTTP.swift */; };
- 5820675526E6528200655B05 /* RelayCacheError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 585DA87926B024F900B8C587 /* RelayCacheError.swift */; };
5820675626E6528A00655B05 /* RESTError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 585DA88626B0277200B8C587 /* RESTError.swift */; };
5820675726E652A600655B05 /* REST.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5820674D26E6510200655B05 /* REST.swift */; };
5820675826E652AF00655B05 /* RelayCacheIO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 585DA87C26B0254000B8C587 /* RelayCacheIO.swift */; };
@@ -131,7 +130,6 @@
585CA70F25F8C44600B47C62 /* UIMetrics.swift in Sources */ = {isa = PBXBuildFile; fileRef = 585CA70E25F8C44600B47C62 /* UIMetrics.swift */; };
585DA87726B024A600B8C587 /* CachedRelays.swift in Sources */ = {isa = PBXBuildFile; fileRef = 585DA87626B024A600B8C587 /* CachedRelays.swift */; };
585DA87826B024A900B8C587 /* CachedRelays.swift in Sources */ = {isa = PBXBuildFile; fileRef = 585DA87626B024A600B8C587 /* CachedRelays.swift */; };
- 585DA87A26B024F900B8C587 /* RelayCacheError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 585DA87926B024F900B8C587 /* RelayCacheError.swift */; };
585DA87D26B0254000B8C587 /* RelayCacheIO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 585DA87C26B0254000B8C587 /* RelayCacheIO.swift */; };
585DA88426B0270700B8C587 /* ServerRelaysResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 585DA88326B0270700B8C587 /* ServerRelaysResponse.swift */; };
585DA88526B0270700B8C587 /* ServerRelaysResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 585DA88326B0270700B8C587 /* ServerRelaysResponse.swift */; };
@@ -440,7 +438,6 @@
5857F24624C882D700CF6F47 /* SelectLocationNavigationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectLocationNavigationController.swift; sourceTree = "<group>"; };
585CA70E25F8C44600B47C62 /* UIMetrics.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIMetrics.swift; sourceTree = "<group>"; };
585DA87626B024A600B8C587 /* CachedRelays.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CachedRelays.swift; sourceTree = "<group>"; };
- 585DA87926B024F900B8C587 /* RelayCacheError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelayCacheError.swift; sourceTree = "<group>"; };
585DA87C26B0254000B8C587 /* RelayCacheIO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelayCacheIO.swift; sourceTree = "<group>"; };
585DA88326B0270700B8C587 /* ServerRelaysResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerRelaysResponse.swift; sourceTree = "<group>"; };
585DA88626B0277200B8C587 /* RESTError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RESTError.swift; sourceTree = "<group>"; };
@@ -746,7 +743,6 @@
children = (
585DA87626B024A600B8C587 /* CachedRelays.swift */,
5820675A26E6576800655B05 /* RelayCache.swift */,
- 585DA87926B024F900B8C587 /* RelayCacheError.swift */,
585DA87C26B0254000B8C587 /* RelayCacheIO.swift */,
58FB865926EA214400F188BC /* RelayCacheObserver.swift */,
58BFA5C522A7C97F00A6173D /* RelayCacheTracker.swift */,
@@ -1355,7 +1351,6 @@
5846227326E22A160035F7C2 /* AppStorePaymentObserver.swift in Sources */,
58F2E146276A2C9900A79513 /* StopTunnelOperation.swift in Sources */,
58DF5B762852108E00E92647 /* InputInjectionBuilder.swift in Sources */,
- 585DA87A26B024F900B8C587 /* RelayCacheError.swift in Sources */,
5856D13727450A8A00DFD627 /* UIImage+TintColor.swift in Sources */,
58CB0EE024B86751001EF0D8 /* RESTAPIProxy.swift in Sources */,
58095C532760EEC700890776 /* RESTNetworkOperation.swift in Sources */,
@@ -1530,7 +1525,6 @@
58F840B32464491D0044E708 /* ChainedError.swift in Sources */,
58D67A0A26D7AE3300557C3C /* OSLogHandler.swift in Sources */,
5820675626E6528A00655B05 /* RESTError.swift in Sources */,
- 5820675526E6528200655B05 /* RelayCacheError.swift in Sources */,
58561C9A239A5D1500BD6B5E /* IPEndpoint.swift in Sources */,
58781CCE22AE8918009B9D8E /* RelayConstraints.swift in Sources */,
581503A024D6F01E00C9C50E /* LogRotation.swift in Sources */,
diff --git a/ios/MullvadVPN/AppDelegate.swift b/ios/MullvadVPN/AppDelegate.swift
index bfdd04f016..95a32e0ffd 100644
--- a/ios/MullvadVPN/AppDelegate.swift
+++ b/ios/MullvadVPN/AppDelegate.swift
@@ -112,7 +112,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
}
}
- let updateRelaysOperation = ResultBlockOperation<RelayCache.FetchResult, RelayCache.Error>
+ let updateRelaysOperation = ResultBlockOperation<RelayCache.FetchResult, Error>
{ operation in
let handle = RelayCache.Tracker.shared.updateRelays { completion in
operation.finish(completion: completion)
diff --git a/ios/MullvadVPN/RelayCache/RelayCacheError.swift b/ios/MullvadVPN/RelayCache/RelayCacheError.swift
deleted file mode 100644
index fe75cf2d4e..0000000000
--- a/ios/MullvadVPN/RelayCache/RelayCacheError.swift
+++ /dev/null
@@ -1,43 +0,0 @@
-//
-// RelayCacheError.swift
-// RelayCacheError
-//
-// Created by pronebird on 27/07/2021.
-// Copyright © 2021 Mullvad VPN AB. All rights reserved.
-//
-
-import Foundation
-
-extension RelayCache {
-
- /// Error emitted by RelayCache cluster.
- enum Error: ChainedError {
- case readCache(Swift.Error)
- case readPrebundledRelays(Swift.Error)
- case decodePrebundledRelays(Swift.Error)
- case writeCache(Swift.Error)
- case encodeCache(Swift.Error)
- case decodeCache(Swift.Error)
- case rest(REST.Error)
-
- var errorDescription: String? {
- switch self {
- case .encodeCache:
- return "Encode cache error."
- case .decodeCache:
- return "Decode cache error."
- case .readCache:
- return "Read cache error."
- case .readPrebundledRelays:
- return "Read pre-bundled relays error."
- case .decodePrebundledRelays:
- return "Decode pre-bundled relays error."
- case .writeCache:
- return "Write cache error."
- case .rest:
- return "REST error."
- }
- }
- }
-
-}
diff --git a/ios/MullvadVPN/RelayCache/RelayCacheIO.swift b/ios/MullvadVPN/RelayCache/RelayCacheIO.swift
index 20cbe90f6a..6a2a4deb13 100644
--- a/ios/MullvadVPN/RelayCache/RelayCacheIO.swift
+++ b/ios/MullvadVPN/RelayCache/RelayCacheIO.swift
@@ -31,31 +31,26 @@ extension RelayCache.IO {
/// Safely read the cache file from disk using file coordinator.
static func read(cacheFileURL: URL) throws -> RelayCache.CachedRelays {
- var result: Result<RelayCache.CachedRelays, RelayCache.Error>?
+ var result: Result<RelayCache.CachedRelays, Error>?
let fileCoordinator = NSFileCoordinator(filePresenter: nil)
- let accessor = { (fileURLForReading: URL) -> Void in
- // Decode data from disk
- do {
+ let accessor = { (fileURLForReading: URL) in
+ result = Result {
let data = try Data(contentsOf: fileURLForReading)
- let relays = try JSONDecoder().decode(RelayCache.CachedRelays.self, from: data)
-
- result = .success(relays)
- } catch let error as DecodingError {
- result = .failure(.decodeCache(error))
- } catch {
- result = .failure(.readCache(error))
+ return try JSONDecoder().decode(RelayCache.CachedRelays.self, from: data)
}
}
var error: NSError?
- fileCoordinator.coordinate(readingItemAt: cacheFileURL,
- options: [.withoutChanges],
- error: &error,
- byAccessor: accessor)
+ fileCoordinator.coordinate(
+ readingItemAt: cacheFileURL,
+ options: [.withoutChanges],
+ error: &error,
+ byAccessor: accessor
+ )
if let error = error {
- result = .failure(.readCache(error))
+ result = .failure(error)
}
return try result!.get()
@@ -69,12 +64,9 @@ extension RelayCache.IO {
do {
return try Self.read(cacheFileURL: cacheFileURL)
} catch {
- let error = error as! RelayCache.Error
-
- switch error {
- case .decodeCache, .readCache(CocoaError.fileReadNoSuchFile):
- return try RelayCache.IO.readPrebundledRelays(fileURL: preBundledRelaysFileURL)
- default:
+ if error is DecodingError || (error as? CocoaError)?.code == .fileReadNoSuchFile {
+ return try Self.readPrebundledRelays(fileURL: preBundledRelaysFileURL)
+ } else {
throw error
}
}
@@ -82,46 +74,40 @@ extension RelayCache.IO {
/// Read pre-bundled relays file from disk.
static func readPrebundledRelays(fileURL: URL) throws -> RelayCache.CachedRelays {
- do {
- let data = try Data(contentsOf: fileURL)
- let relays = try REST.Coding.makeJSONDecoder()
- .decode(REST.ServerRelaysResponse.self, from: data)
+ let data = try Data(contentsOf: fileURL)
+ let relays = try REST.Coding.makeJSONDecoder()
+ .decode(REST.ServerRelaysResponse.self, from: data)
- return RelayCache.CachedRelays(
- relays: relays,
- updatedAt: Date(timeIntervalSince1970: 0)
- )
- } catch let error as DecodingError {
- throw RelayCache.Error.decodePrebundledRelays(error)
- } catch {
- throw RelayCache.Error.readPrebundledRelays(error)
- }
+ return RelayCache.CachedRelays(
+ relays: relays,
+ updatedAt: Date(timeIntervalSince1970: 0)
+ )
}
/// Safely write the cache file on disk using file coordinator.
static func write(cacheFileURL: URL, record: RelayCache.CachedRelays) throws {
- var resultError: RelayCache.Error?
+ var result: Result<(), Error>?
let fileCoordinator = NSFileCoordinator(filePresenter: nil)
- let accessor = { (fileURLForWriting: URL) -> Void in
- do {
+ let accessor = { (fileURLForWriting: URL) in
+ result = Result {
let data = try JSONEncoder().encode(record)
try data.write(to: fileURLForWriting)
- } catch let error as EncodingError {
- resultError = .encodeCache(error)
- } catch {
- resultError = .writeCache(error)
}
}
var error: NSError?
- fileCoordinator.coordinate(writingItemAt: cacheFileURL,
- options: [.forReplacing],
- error: &error,
- byAccessor: accessor)
+ fileCoordinator.coordinate(
+ writingItemAt: cacheFileURL,
+ options: [.forReplacing],
+ error: &error,
+ byAccessor: accessor
+ )
- if let resultError = resultError {
- throw resultError
+ if let error = error {
+ result = .failure(error)
}
+
+ try result?.get()
}
}
diff --git a/ios/MullvadVPN/RelayCache/RelayCacheTracker.swift b/ios/MullvadVPN/RelayCache/RelayCacheTracker.swift
index f7ffcf2f72..702e5b9273 100644
--- a/ios/MullvadVPN/RelayCache/RelayCacheTracker.swift
+++ b/ios/MullvadVPN/RelayCache/RelayCacheTracker.swift
@@ -35,6 +35,12 @@ extension RelayCache {
}
}
+ struct NoCachedRelaysError: LocalizedError {
+ var errorDescription: String? {
+ return "Relay cache is empty."
+ }
+ }
+
class Tracker {
/// Relay update interval (in seconds).
static let relayUpdateInterval: TimeInterval = 60 * 60
@@ -134,14 +140,14 @@ extension RelayCache {
func updateRelays(
completionHandler: (
- (OperationCompletion<RelayCache.FetchResult, RelayCache.Error>) -> Void
+ (OperationCompletion<RelayCache.FetchResult, Error>) -> Void
)? = nil
) -> Cancellable
{
- let operation = ResultBlockOperation<RelayCache.FetchResult, RelayCache.Error>(
+ let operation = ResultBlockOperation<RelayCache.FetchResult, Error>(
dispatchQueue: nil
) { operation in
- let cachedRelays = self.getCachedRelays()
+ let cachedRelays = try? self.getCachedRelays()
if self.getNextUpdateDate() > Date() {
operation.finish(completion: .success(.throttled))
@@ -174,11 +180,15 @@ extension RelayCache {
return operation
}
- func getCachedRelays() -> CachedRelays? {
+ func getCachedRelays() throws -> CachedRelays {
nslock.lock()
defer { nslock.unlock() }
- return cachedRelays
+ if let cachedRelays = cachedRelays {
+ return cachedRelays
+ } else {
+ throw NoCachedRelaysError()
+ }
}
func getNextUpdateDate() -> Date {
@@ -214,28 +224,23 @@ extension RelayCache {
private func handleResponse(
completion: OperationCompletion<REST.ServerRelaysCacheResponse, REST.Error>
- ) -> OperationCompletion<FetchResult, RelayCache.Error>
+ ) -> OperationCompletion<FetchResult, Error>
{
- let mappedCompletion = completion
- .mapError { error -> RelayCache.Error in
- return .rest(error)
- }
- .tryMap { response -> FetchResult in
- switch response {
- case .newContent(let etag, let relays):
- try self.storeResponse(etag: etag, relays: relays)
+ let mappedCompletion = completion.tryMap { response -> FetchResult in
+ switch response {
+ case .newContent(let etag, let relays):
+ try self.storeResponse(etag: etag, relays: relays)
- return .newContent
+ return .newContent
- case .notModified:
- return .sameContent
- }
+ case .notModified:
+ return .sameContent
}
- .assertFailure(RelayCache.Error.self)
+ }
if let error = mappedCompletion.error {
logger.error(
- chainedError: error,
+ chainedError: AnyChainedError(error),
message: "Failed to update relays."
)
}
@@ -258,24 +263,16 @@ extension RelayCache {
cachedRelays = newCachedRelays
nslock.unlock()
+ try RelayCache.IO.write(
+ cacheFileURL: cacheFileURL,
+ record: newCachedRelays
+ )
+
DispatchQueue.main.async {
self.observerList.forEach { observer in
observer.relayCache(self, didUpdateCachedRelays: newCachedRelays)
}
}
-
- do {
- try RelayCache.IO.write(
- cacheFileURL: cacheFileURL,
- record: newCachedRelays
- )
- } catch {
- logger.error(
- chainedError: AnyChainedError(error),
- message: "Failed to store downloaded relays."
- )
- throw error
- }
}
diff --git a/ios/MullvadVPN/RelaySelector.swift b/ios/MullvadVPN/RelaySelector.swift
index 5e7492ca16..c29c8ccef5 100644
--- a/ios/MullvadVPN/RelaySelector.swift
+++ b/ios/MullvadVPN/RelaySelector.swift
@@ -32,17 +32,23 @@ extension RelaySelectorResult {
}
}
+struct NoRelaysSatisfyingConstraintsError: LocalizedError {
+ var errorDescription: String? {
+ return "No relays satisfying constraints."
+ }
+}
+
enum RelaySelector {}
extension RelaySelector {
- static func evaluate(relays: REST.ServerRelaysResponse, constraints: RelayConstraints) -> RelaySelectorResult? {
+ static func evaluate(relays: REST.ServerRelaysResponse, constraints: RelayConstraints) throws -> RelaySelectorResult {
let filteredRelays = applyConstraints(constraints, relays: Self.parseRelaysResponse(relays))
guard let relayWithLocation = pickRandomRelay(relays: filteredRelays),
let port = pickRandomPort(rawPortRanges: relays.wireguard.portRanges) else {
- return nil
- }
+ throw NoRelaysSatisfyingConstraintsError()
+ }
let endpoint = MullvadEndpoint(
ipv4Relay: IPv4Endpoint(
diff --git a/ios/MullvadVPN/SceneDelegate.swift b/ios/MullvadVPN/SceneDelegate.swift
index 00c8a2ce3e..56e6d1e8bc 100644
--- a/ios/MullvadVPN/SceneDelegate.swift
+++ b/ios/MullvadVPN/SceneDelegate.swift
@@ -324,7 +324,7 @@ extension SceneDelegate {
let selectLocationController = SelectLocationViewController()
selectLocationController.delegate = self
- if let cachedRelays = RelayCache.Tracker.shared.getCachedRelays() {
+ if let cachedRelays = try? RelayCache.Tracker.shared.getCachedRelays() {
selectLocationController.setCachedRelays(cachedRelays)
}
diff --git a/ios/MullvadVPN/SimulatorTunnelProviderHost.swift b/ios/MullvadVPN/SimulatorTunnelProviderHost.swift
index 975eb98ab4..d523e499fb 100644
--- a/ios/MullvadVPN/SimulatorTunnelProviderHost.swift
+++ b/ios/MullvadVPN/SimulatorTunnelProviderHost.swift
@@ -83,7 +83,7 @@ class SimulatorTunnelProviderHost: SimulatorTunnelProviderDelegate {
}
private func pickRelay() -> RelaySelectorResult? {
- guard let cachedRelays = RelayCache.Tracker.shared.getCachedRelays() else {
+ guard let cachedRelays = try? RelayCache.Tracker.shared.getCachedRelays() else {
providerLogger.error("Failed to obtain relays when picking relay.")
return nil
}
@@ -91,7 +91,7 @@ class SimulatorTunnelProviderHost: SimulatorTunnelProviderDelegate {
do {
let tunnelSettings = try SettingsManager.readSettings()
- return RelaySelector.evaluate(
+ return try RelaySelector.evaluate(
relays: cachedRelays.relays,
constraints: tunnelSettings.relayConstraints
)
diff --git a/ios/MullvadVPN/TunnelManager/StartTunnelOperation.swift b/ios/MullvadVPN/TunnelManager/StartTunnelOperation.swift
index 9723e29863..2ffa3cb9d6 100644
--- a/ios/MullvadVPN/TunnelManager/StartTunnelOperation.swift
+++ b/ios/MullvadVPN/TunnelManager/StartTunnelOperation.swift
@@ -45,7 +45,7 @@ class StartTunnelOperation: ResultOperation<(), TunnelManager.Error> {
finish(completion: .success(()))
case .disconnected, .pendingReconnect:
- guard let cachedRelays = RelayCache.Tracker.shared.getCachedRelays() else {
+ guard let cachedRelays = try? RelayCache.Tracker.shared.getCachedRelays() else {
finish(completion: .failure(.readRelays))
return
}
@@ -62,12 +62,10 @@ class StartTunnelOperation: ResultOperation<(), TunnelManager.Error> {
}
private func didReceiveRelays(tunnelSettings: TunnelSettingsV2, cachedRelays: RelayCache.CachedRelays) {
- let selectorResult = RelaySelector.evaluate(
+ guard let selectorResult = try? RelaySelector.evaluate(
relays: cachedRelays.relays,
constraints: tunnelSettings.relayConstraints
- )
-
- guard let selectorResult = selectorResult else {
+ ) else {
finish(completion: .failure(.cannotSatisfyRelayConstraints))
return
}
diff --git a/ios/MullvadVPNTests/RelaySelectorTests.swift b/ios/MullvadVPNTests/RelaySelectorTests.swift
index 10dcb8502e..8f997289db 100644
--- a/ios/MullvadVPNTests/RelaySelectorTests.swift
+++ b/ios/MullvadVPNTests/RelaySelectorTests.swift
@@ -11,27 +11,27 @@ import Network
class RelaySelectorTests: XCTestCase {
- func testCountryConstraint() {
+ func testCountryConstraint() throws {
let constraints = RelayConstraints(location: .only(.country("es")))
- let result = RelaySelector.evaluate(relays: sampleRelays, constraints: constraints)
+ let result = try RelaySelector.evaluate(relays: sampleRelays, constraints: constraints)
- XCTAssertEqual(result?.relay.hostname, "es1-wireguard")
+ XCTAssertEqual(result.relay.hostname, "es1-wireguard")
}
- func testCityConstraint() {
+ func testCityConstraint() throws {
let constraints = RelayConstraints(location: .only(.city("se", "got")))
- let result = RelaySelector.evaluate(relays: sampleRelays, constraints: constraints)
+ let result = try RelaySelector.evaluate(relays: sampleRelays, constraints: constraints)
- XCTAssertEqual(result?.relay.hostname, "se10-wireguard")
+ XCTAssertEqual(result.relay.hostname, "se10-wireguard")
}
- func testHostnameConstraint() {
+ func testHostnameConstraint() throws {
let constraints = RelayConstraints(location: .only(.hostname("se", "sto", "se6-wireguard")))
- let result = RelaySelector.evaluate(relays: sampleRelays, constraints: constraints)
+ let result = try RelaySelector.evaluate(relays: sampleRelays, constraints: constraints)
- XCTAssertEqual(result?.relay.hostname, "se6-wireguard")
+ XCTAssertEqual(result.relay.hostname, "se6-wireguard")
}
}
diff --git a/ios/PacketTunnel/PacketTunnelProvider.swift b/ios/PacketTunnel/PacketTunnelProvider.swift
index 2e917eb5b1..126ed7b6ae 100644
--- a/ios/PacketTunnel/PacketTunnelProvider.swift
+++ b/ios/PacketTunnel/PacketTunnelProvider.swift
@@ -420,7 +420,7 @@ class PacketTunnelProvider: NEPacketTunnelProvider, TunnelMonitorDelegate {
throw PacketTunnelProviderError.readRelayCache(error)
}
- if let selectorResult = RelaySelector.evaluate(
+ if let selectorResult = try? RelaySelector.evaluate(
relays: cachedRelayList.relays,
constraints: relayConstraints
) {