diff options
| author | Andrej Mihajlov <and@mullvad.net> | 2022-10-25 08:51:29 +0200 |
|---|---|---|
| committer | Andrej Mihajlov <and@mullvad.net> | 2022-10-25 08:51:29 +0200 |
| commit | 7ab6519535c90087e4edc2aa70a15a133c0cb1f2 (patch) | |
| tree | 55667723ac6792210f5360c56363ee895c1fc5aa | |
| parent | f9553b7a2695f0e2c5794e13ac021f518d947e63 (diff) | |
| parent | 220749af09f1943eb5b73e395361c801a4d00d1d (diff) | |
| download | mullvadvpn-7ab6519535c90087e4edc2aa70a15a133c0cb1f2.tar.xz mullvadvpn-7ab6519535c90087e4edc2aa70a15a133c0cb1f2.zip | |
Merge branch 'relay-cache-instance'
| -rw-r--r-- | ios/MullvadVPN.xcodeproj/project.pbxproj | 8 | ||||
| -rw-r--r-- | ios/MullvadVPN/RelayCache/RelayCacheTracker.swift | 48 | ||||
| -rw-r--r-- | ios/MullvadVPN/RelayCache/RelayCacheTrackerObserver.swift (renamed from ios/MullvadVPN/RelayCache/RelayCacheObserver.swift) | 10 | ||||
| -rw-r--r-- | ios/MullvadVPN/SceneDelegate.swift | 8 | ||||
| -rw-r--r-- | ios/PacketTunnel/PacketTunnelProvider.swift | 18 | ||||
| -rw-r--r-- | ios/RelayCache/RelayCache.swift | 113 |
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) + ) + } } |
