summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAndrej Mihajlov <and@mullvad.net>2022-10-25 08:51:29 +0200
committerAndrej Mihajlov <and@mullvad.net>2022-10-25 08:51:29 +0200
commit7ab6519535c90087e4edc2aa70a15a133c0cb1f2 (patch)
tree55667723ac6792210f5360c56363ee895c1fc5aa
parentf9553b7a2695f0e2c5794e13ac021f518d947e63 (diff)
parent220749af09f1943eb5b73e395361c801a4d00d1d (diff)
downloadmullvadvpn-7ab6519535c90087e4edc2aa70a15a133c0cb1f2.tar.xz
mullvadvpn-7ab6519535c90087e4edc2aa70a15a133c0cb1f2.zip
Merge branch 'relay-cache-instance'
-rw-r--r--ios/MullvadVPN.xcodeproj/project.pbxproj8
-rw-r--r--ios/MullvadVPN/RelayCache/RelayCacheTracker.swift48
-rw-r--r--ios/MullvadVPN/RelayCache/RelayCacheTrackerObserver.swift (renamed from ios/MullvadVPN/RelayCache/RelayCacheObserver.swift)10
-rw-r--r--ios/MullvadVPN/SceneDelegate.swift8
-rw-r--r--ios/PacketTunnel/PacketTunnelProvider.swift18
-rw-r--r--ios/RelayCache/RelayCache.swift113
6 files changed, 90 insertions, 115 deletions
diff --git a/ios/MullvadVPN.xcodeproj/project.pbxproj b/ios/MullvadVPN.xcodeproj/project.pbxproj
index 5d8832ca44..bf46a635ec 100644
--- a/ios/MullvadVPN.xcodeproj/project.pbxproj
+++ b/ios/MullvadVPN.xcodeproj/project.pbxproj
@@ -287,7 +287,7 @@
58F7CA882692E34000FC59FD /* WireguardKeysContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58F7CA872692E34000FC59FD /* WireguardKeysContentView.swift */; };
58F8AC0E25D3F8CE002BE0ED /* ProblemReportReviewViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58F8AC0D25D3F8CE002BE0ED /* ProblemReportReviewViewController.swift */; };
58FB865526E8BF3100F188BC /* AppStorePaymentManagerError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58FB865426E8BF3100F188BC /* AppStorePaymentManagerError.swift */; };
- 58FB865A26EA214400F188BC /* RelayCacheObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58FB865926EA214400F188BC /* RelayCacheObserver.swift */; };
+ 58FB865A26EA214400F188BC /* RelayCacheTrackerObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58FB865926EA214400F188BC /* RelayCacheTrackerObserver.swift */; };
58FC040A27B3EE03001C21F0 /* TunnelMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58FC040927B3EE03001C21F0 /* TunnelMonitor.swift */; };
58FD5BE724192A2C00112C88 /* AppStoreReceipt.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58FD5BE624192A2B00112C88 /* AppStoreReceipt.swift */; };
58FD5BF024238EB300112C88 /* SKProduct+Formatting.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58FD5BEF24238EB300112C88 /* SKProduct+Formatting.swift */; };
@@ -753,7 +753,7 @@
58F7D26427EB50A300E4D821 /* ResultOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResultOperation.swift; sourceTree = "<group>"; };
58F8AC0D25D3F8CE002BE0ED /* ProblemReportReviewViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProblemReportReviewViewController.swift; sourceTree = "<group>"; };
58FB865426E8BF3100F188BC /* AppStorePaymentManagerError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppStorePaymentManagerError.swift; sourceTree = "<group>"; };
- 58FB865926EA214400F188BC /* RelayCacheObserver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelayCacheObserver.swift; sourceTree = "<group>"; };
+ 58FB865926EA214400F188BC /* RelayCacheTrackerObserver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelayCacheTrackerObserver.swift; sourceTree = "<group>"; };
58FC040927B3EE03001C21F0 /* TunnelMonitor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelMonitor.swift; sourceTree = "<group>"; };
58FD5BE624192A2B00112C88 /* AppStoreReceipt.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppStoreReceipt.swift; sourceTree = "<group>"; };
58FD5BEF24238EB300112C88 /* SKProduct+Formatting.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SKProduct+Formatting.swift"; sourceTree = "<group>"; };
@@ -1059,7 +1059,7 @@
585DA87526B0249A00B8C587 /* RelayCache */ = {
isa = PBXGroup;
children = (
- 58FB865926EA214400F188BC /* RelayCacheObserver.swift */,
+ 58FB865926EA214400F188BC /* RelayCacheTrackerObserver.swift */,
58BFA5C522A7C97F00A6173D /* RelayCacheTracker.swift */,
);
path = RelayCache;
@@ -2060,7 +2060,7 @@
584D26C2270C8542004EA533 /* SettingsStaticTextFooterView.swift in Sources */,
587B7536266528A200DEF7E9 /* NotificationManager.swift in Sources */,
5820EDA9288FE064006BF4E4 /* DeviceManagementInteractor.swift in Sources */,
- 58FB865A26EA214400F188BC /* RelayCacheObserver.swift in Sources */,
+ 58FB865A26EA214400F188BC /* RelayCacheTrackerObserver.swift in Sources */,
58ACF64D26567A5000ACE4B7 /* CustomSwitch.swift in Sources */,
58F2E14C276A61C000A79513 /* RotateKeyOperation.swift in Sources */,
5871FB96254ADE4E0051A0A4 /* ConsolidatedApplicationLog.swift in Sources */,
diff --git a/ios/MullvadVPN/RelayCache/RelayCacheTracker.swift b/ios/MullvadVPN/RelayCache/RelayCacheTracker.swift
index b003ae6868..c6d0b64ef0 100644
--- a/ios/MullvadVPN/RelayCache/RelayCacheTracker.swift
+++ b/ios/MullvadVPN/RelayCache/RelayCacheTracker.swift
@@ -21,11 +21,10 @@ class RelayCacheTracker {
/// Tracker log.
private let logger = Logger(label: "RelayCacheTracker")
- /// The cache location used by the class instance.
- private let cacheFileURL: URL
-
- /// The location of prebundled `relays.json`.
- private let prebundledRelaysFileURL: URL
+ /// Relay cache.
+ private let cache = RelayCache(
+ securityGroupIdentifier: ApplicationConfiguration.securityGroupIdentifier
+ )!
/// Lock used for synchronization.
private let nslock = NSLock()
@@ -47,35 +46,17 @@ class RelayCacheTracker {
private let apiProxy = REST.ProxyFactory.shared.createAPIProxy()
/// Observers.
- private let observerList = ObserverList<RelayCacheObserver>()
+ private let observerList = ObserverList<RelayCacheTrackerObserver>()
/// Memory cache.
private var cachedRelays: CachedRelays?
- /// A shared instance of `RelayCache`
- static let shared: RelayCacheTracker = {
- let cacheFileURL = RelayCache
- .defaultCacheFileURL(
- forSecurityApplicationGroupIdentifier: ApplicationConfiguration
- .securityGroupIdentifier
- )!
- let prebundledRelaysFileURL = RelayCache.preBundledRelaysFileURL!
-
- return RelayCacheTracker(
- cacheFileURL: cacheFileURL,
- prebundledRelaysFileURL: prebundledRelaysFileURL
- )
- }()
-
- private init(cacheFileURL: URL, prebundledRelaysFileURL: URL) {
- self.cacheFileURL = cacheFileURL
- self.prebundledRelaysFileURL = prebundledRelaysFileURL
+ /// A shared instance of `RelayCacheTracker`.
+ static let shared = RelayCacheTracker()
+ private init() {
do {
- cachedRelays = try RelayCache.readWithFallback(
- cacheFileURL: cacheFileURL,
- preBundledRelaysFileURL: prebundledRelaysFileURL
- )
+ cachedRelays = try cache.read()
} catch {
logger.error(
error: error,
@@ -180,11 +161,11 @@ class RelayCacheTracker {
// MARK: - Observation
- func addObserver(_ observer: RelayCacheObserver) {
+ func addObserver(_ observer: RelayCacheTrackerObserver) {
observerList.append(observer)
}
- func removeObserver(_ observer: RelayCacheObserver) {
+ func removeObserver(_ observer: RelayCacheTrackerObserver) {
observerList.remove(observer)
}
@@ -242,14 +223,11 @@ class RelayCacheTracker {
cachedRelays = newCachedRelays
nslock.unlock()
- try RelayCache.write(
- cacheFileURL: cacheFileURL,
- record: newCachedRelays
- )
+ try cache.write(record: newCachedRelays)
DispatchQueue.main.async {
self.observerList.forEach { observer in
- observer.relayCache(self, didUpdateCachedRelays: newCachedRelays)
+ observer.relayCacheTracker(self, didUpdateCachedRelays: newCachedRelays)
}
}
}
diff --git a/ios/MullvadVPN/RelayCache/RelayCacheObserver.swift b/ios/MullvadVPN/RelayCache/RelayCacheTrackerObserver.swift
index 4b109340f0..fcb38b55d6 100644
--- a/ios/MullvadVPN/RelayCache/RelayCacheObserver.swift
+++ b/ios/MullvadVPN/RelayCache/RelayCacheTrackerObserver.swift
@@ -1,6 +1,6 @@
//
-// RelayCacheObserver.swift
-// RelayCacheObserver
+// RelayCacheTrackerObserver.swift
+// RelayCacheTrackerObserver
//
// Created by pronebird on 09/09/2021.
// Copyright © 2021 Mullvad VPN AB. All rights reserved.
@@ -9,9 +9,9 @@
import Foundation
import RelayCache
-protocol RelayCacheObserver: AnyObject {
- func relayCache(
- _ relayCache: RelayCacheTracker,
+protocol RelayCacheTrackerObserver: AnyObject {
+ func relayCacheTracker(
+ _ tracker: RelayCacheTracker,
didUpdateCachedRelays cachedRelays: CachedRelays
)
}
diff --git a/ios/MullvadVPN/SceneDelegate.swift b/ios/MullvadVPN/SceneDelegate.swift
index 6a8a136f4a..df8b629b92 100644
--- a/ios/MullvadVPN/SceneDelegate.swift
+++ b/ios/MullvadVPN/SceneDelegate.swift
@@ -931,11 +931,11 @@ extension SceneDelegate: TunnelObserver {
}
}
-// MARK: - RelayCacheObserver
+// MARK: - RelayCacheTrackerObserver
-extension SceneDelegate: RelayCacheObserver {
- func relayCache(
- _ relayCache: RelayCacheTracker,
+extension SceneDelegate: RelayCacheTrackerObserver {
+ func relayCacheTracker(
+ _ tracker: RelayCacheTracker,
didUpdateCachedRelays cachedRelays: CachedRelays
) {
selectLocationViewController?.setCachedRelays(cachedRelays)
diff --git a/ios/PacketTunnel/PacketTunnelProvider.swift b/ios/PacketTunnel/PacketTunnelProvider.swift
index 00b8c47b97..1ec04c0afe 100644
--- a/ios/PacketTunnel/PacketTunnelProvider.swift
+++ b/ios/PacketTunnel/PacketTunnelProvider.swift
@@ -40,6 +40,11 @@ class PacketTunnelProvider: NEPacketTunnelProvider, TunnelMonitorDelegate {
/// Last runtime error.
private var lastError: Error?
+ /// Relay cache.
+ private let relayCache = RelayCache(
+ securityGroupIdentifier: ApplicationConfiguration.securityGroupIdentifier
+ )!
+
/// Current selector result.
private var selectorResult: RelaySelectorResult?
@@ -363,7 +368,7 @@ class PacketTunnelProvider: NEPacketTunnelProvider, TunnelMonitorDelegate {
switch nextRelay {
case .automatic:
- selectorResult = try Self.selectRelayEndpoint(
+ selectorResult = try selectRelayEndpoint(
relayConstraints: tunnelSettings.relayConstraints
)
case let .set(aSelectorResult):
@@ -436,17 +441,10 @@ class PacketTunnelProvider: NEPacketTunnelProvider, TunnelMonitorDelegate {
/// Load relay cache with potential networking to refresh the cache and pick the relay for the
/// given relay constraints.
- private class func selectRelayEndpoint(relayConstraints: RelayConstraints) throws
+ private func selectRelayEndpoint(relayConstraints: RelayConstraints) throws
-> RelaySelectorResult
{
- let cacheFileURL = RelayCache.defaultCacheFileURL(
- forSecurityApplicationGroupIdentifier: ApplicationConfiguration.securityGroupIdentifier
- )!
- let prebundledRelaysURL = RelayCache.preBundledRelaysFileURL!
- let cachedRelayList = try RelayCache.readWithFallback(
- cacheFileURL: cacheFileURL,
- preBundledRelaysFileURL: prebundledRelaysURL
- )
+ let cachedRelayList = try relayCache.read()
return try RelaySelector.evaluate(
relays: cachedRelayList.relays,
diff --git a/ios/RelayCache/RelayCache.swift b/ios/RelayCache/RelayCache.swift
index 64ce748128..0952f05438 100644
--- a/ios/RelayCache/RelayCache.swift
+++ b/ios/RelayCache/RelayCache.swift
@@ -9,80 +9,40 @@
import Foundation
import MullvadREST
-public class RelayCache {
- /// The default cache file location bound by app group container.
- public static func defaultCacheFileURL(
- forSecurityApplicationGroupIdentifier appGroupIdentifier: String
- ) -> URL? {
- let containerURL = FileManager.default.containerURL(
- forSecurityApplicationGroupIdentifier: appGroupIdentifier
- )
+public final class RelayCache {
+ /// Cache file location.
+ let cacheFileURL: URL
- return containerURL?.appendingPathComponent("relays.json")
- }
+ /// Location of pre-bundled relays file.
+ let prebundledRelaysFileURL: URL
- /// The path to pre-bundled `relays.json` file.
- public static var preBundledRelaysFileURL: URL? {
- return Bundle(for: Self.self).url(forResource: "relays", withExtension: "json")
- }
-
- /// Safely read the cache file from disk using file coordinator.
- public static func read(cacheFileURL: URL) throws -> CachedRelays {
- var result: Result<CachedRelays, Error>?
- let fileCoordinator = NSFileCoordinator(filePresenter: nil)
+ /// Initialize cache with default cache file location in app group container.
+ public init?(securityGroupIdentifier: String) {
+ guard let containerURL = FileManager.default.containerURL(
+ forSecurityApplicationGroupIdentifier: securityGroupIdentifier
+ ), let prebundledRelaysFileURL = Bundle(for: Self.self)
+ .url(forResource: "relays", withExtension: "json") else { return nil }
- let accessor = { (fileURLForReading: URL) in
- result = Result {
- let data = try Data(contentsOf: fileURLForReading)
- return try JSONDecoder().decode(CachedRelays.self, from: data)
- }
- }
-
- var error: NSError?
- fileCoordinator.coordinate(
- readingItemAt: cacheFileURL,
- options: [.withoutChanges],
- error: &error,
- byAccessor: accessor
- )
-
- if let error = error {
- result = .failure(error)
- }
-
- return try result!.get()
+ cacheFileURL = containerURL.appendingPathComponent("relays.json", isDirectory: false)
+ self.prebundledRelaysFileURL = prebundledRelaysFileURL
}
/// Safely read the cache file from disk using file coordinator and fallback to prebundled
/// relays in case if the relay cache file is missing.
- public static func readWithFallback(cacheFileURL: URL, preBundledRelaysFileURL: URL)
- throws -> CachedRelays
- {
+ public func read() throws -> CachedRelays {
do {
- return try Self.read(cacheFileURL: cacheFileURL)
+ return try readDiskCache()
} catch {
if error is DecodingError || (error as? CocoaError)?.code == .fileReadNoSuchFile {
- return try Self.readPrebundledRelays(fileURL: preBundledRelaysFileURL)
+ return try readPrebundledRelays()
} else {
throw error
}
}
}
- /// Read pre-bundled relays file from disk.
- public static func readPrebundledRelays(fileURL: URL) throws -> CachedRelays {
- let data = try Data(contentsOf: fileURL)
- let relays = try REST.Coding.makeJSONDecoder()
- .decode(REST.ServerRelaysResponse.self, from: data)
-
- return CachedRelays(
- relays: relays,
- updatedAt: Date(timeIntervalSince1970: 0)
- )
- }
-
/// Safely write the cache file on disk using file coordinator.
- public static func write(cacheFileURL: URL, record: CachedRelays) throws {
+ public func write(record: CachedRelays) throws {
var result: Result<Void, Error>?
let fileCoordinator = NSFileCoordinator(filePresenter: nil)
@@ -107,4 +67,43 @@ public class RelayCache {
try result?.get()
}
+
+ /// Safely read the cache file from disk using file coordinator.
+ private func readDiskCache() throws -> CachedRelays {
+ var result: Result<CachedRelays, Error>?
+ let fileCoordinator = NSFileCoordinator(filePresenter: nil)
+
+ let accessor = { (fileURLForReading: URL) in
+ result = Result {
+ let data = try Data(contentsOf: fileURLForReading)
+ return try JSONDecoder().decode(CachedRelays.self, from: data)
+ }
+ }
+
+ var error: NSError?
+ fileCoordinator.coordinate(
+ readingItemAt: cacheFileURL,
+ options: [.withoutChanges],
+ error: &error,
+ byAccessor: accessor
+ )
+
+ if let error = error {
+ result = .failure(error)
+ }
+
+ return try result!.get()
+ }
+
+ /// Read pre-bundled relays file from disk.
+ private func readPrebundledRelays() throws -> CachedRelays {
+ let data = try Data(contentsOf: prebundledRelaysFileURL)
+ let relays = try REST.Coding.makeJSONDecoder()
+ .decode(REST.ServerRelaysResponse.self, from: data)
+
+ return CachedRelays(
+ relays: relays,
+ updatedAt: Date(timeIntervalSince1970: 0)
+ )
+ }
}