summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorBug Magnet <marco.nikic@mullvad.net>2024-09-05 13:57:21 +0200
committerBug Magnet <marco.nikic@mullvad.net>2024-09-05 13:57:21 +0200
commit49bf276c49767dbb45c551d51dc25a94aa179f6b (patch)
tree22aef09e17e76b5370ff5a5b97a9383636882926
parent1c5fb0aefddee4996b0e860c4dccbbf6a5995851 (diff)
parent1afb6ad5291864add3c5b4707e1db882a335516e (diff)
downloadmullvadvpn-49bf276c49767dbb45c551d51dc25a94aa179f6b.tar.xz
mullvadvpn-49bf276c49767dbb45c551d51dc25a94aa179f6b.zip
Merge branch 'infer-whether-the-cached-relays-file-has-daita-enabled-and-ios-811'
-rw-r--r--ios/MullvadREST/ApiHandlers/ServerRelaysResponse.swift29
-rw-r--r--ios/MullvadREST/Relay/IPOverrideWrapper.swift7
-rw-r--r--ios/MullvadREST/Relay/RelayCache.swift9
-rw-r--r--ios/MullvadVPN/RelayCacheTracker/RelayCacheTracker.swift72
4 files changed, 105 insertions, 12 deletions
diff --git a/ios/MullvadREST/ApiHandlers/ServerRelaysResponse.swift b/ios/MullvadREST/ApiHandlers/ServerRelaysResponse.swift
index e38ae3e23e..256a101857 100644
--- a/ios/MullvadREST/ApiHandlers/ServerRelaysResponse.swift
+++ b/ios/MullvadREST/ApiHandlers/ServerRelaysResponse.swift
@@ -78,6 +78,22 @@ extension REST {
daita: daita
)
}
+
+ public func override(daita: Bool) -> Self {
+ return ServerRelay(
+ hostname: hostname,
+ active: active,
+ owned: owned,
+ location: location,
+ provider: provider,
+ weight: weight,
+ ipv4AddrIn: ipv4AddrIn,
+ ipv6AddrIn: ipv6AddrIn,
+ publicKey: publicKey,
+ includeInCountry: includeInCountry,
+ daita: daita
+ )
+ }
}
public struct ServerWireguardTunnels: Codable, Equatable {
@@ -85,6 +101,13 @@ extension REST {
public let ipv6Gateway: IPv6Address
public let portRanges: [[UInt16]]
public let relays: [ServerRelay]
+
+ public init(ipv4Gateway: IPv4Address, ipv6Gateway: IPv6Address, portRanges: [[UInt16]], relays: [ServerRelay]) {
+ self.ipv4Gateway = ipv4Gateway
+ self.ipv6Gateway = ipv6Gateway
+ self.portRanges = portRanges
+ self.relays = relays
+ }
}
public struct ServerShadowsocks: Codable, Equatable {
@@ -103,5 +126,11 @@ extension REST {
public let locations: [String: ServerLocation]
public let wireguard: ServerWireguardTunnels
public let bridge: ServerBridges
+
+ public init(locations: [String: ServerLocation], wireguard: ServerWireguardTunnels, bridge: ServerBridges) {
+ self.locations = locations
+ self.wireguard = wireguard
+ self.bridge = bridge
+ }
}
}
diff --git a/ios/MullvadREST/Relay/IPOverrideWrapper.swift b/ios/MullvadREST/Relay/IPOverrideWrapper.swift
index 531112cf54..84516130d1 100644
--- a/ios/MullvadREST/Relay/IPOverrideWrapper.swift
+++ b/ios/MullvadREST/Relay/IPOverrideWrapper.swift
@@ -25,6 +25,13 @@ public class IPOverrideWrapper: RelayCacheProtocol {
return CachedRelays(relays: relayResponse, updatedAt: cache.updatedAt)
}
+ public func readPrebundledRelays() throws -> CachedRelays {
+ let prebundledRelays = try relayCache.readPrebundledRelays()
+ let relayResponse = apply(overrides: ipOverrideRepository.fetchAll(), to: prebundledRelays.relays)
+
+ return CachedRelays(relays: relayResponse, updatedAt: prebundledRelays.updatedAt)
+ }
+
public func write(record: CachedRelays) throws {
try relayCache.write(record: record)
}
diff --git a/ios/MullvadREST/Relay/RelayCache.swift b/ios/MullvadREST/Relay/RelayCache.swift
index 47ea44c6f5..eedf3b997a 100644
--- a/ios/MullvadREST/Relay/RelayCache.swift
+++ b/ios/MullvadREST/Relay/RelayCache.swift
@@ -10,7 +10,14 @@ import Foundation
import MullvadTypes
public protocol RelayCacheProtocol {
+ /// Reads from a cached list,
+ /// which falls back to reading from prebundled relays if there was no cache hit
func read() throws -> CachedRelays
+ /// Reads the relays file that were prebundled with the app installation.
+ ///
+ /// > Warning: Prefer `read()` over this unless there is an explicit need to read
+ /// relays from the bundle, because those might contain stale data.
+ func readPrebundledRelays() throws -> CachedRelays
func write(record: CachedRelays) throws
}
@@ -49,7 +56,7 @@ public final class RelayCache: RelayCacheProtocol {
}
/// Read pre-bundled relays file from disk.
- private func readPrebundledRelays() throws -> CachedRelays {
+ public func readPrebundledRelays() throws -> CachedRelays {
guard let prebundledRelaysFileURL = Bundle(for: Self.self).url(forResource: "relays", withExtension: "json")
else { throw CocoaError(.fileNoSuchFile) }
diff --git a/ios/MullvadVPN/RelayCacheTracker/RelayCacheTracker.swift b/ios/MullvadVPN/RelayCacheTracker/RelayCacheTracker.swift
index 8893436cb6..2d2d0d384e 100644
--- a/ios/MullvadVPN/RelayCacheTracker/RelayCacheTracker.swift
+++ b/ios/MullvadVPN/RelayCacheTracker/RelayCacheTracker.swift
@@ -37,7 +37,7 @@ final class RelayCacheTracker: RelayCacheTrackerProtocol {
private let application: UIApplication
/// Lock used for synchronization.
- private let nslock = NSLock()
+ private let relayCacheLock = NSLock()
/// Internal operation queue.
private let operationQueue = AsyncOperationQueue.makeSerial()
@@ -64,6 +64,7 @@ final class RelayCacheTracker: RelayCacheTrackerProtocol {
do {
cachedRelays = try cache.read()
+ try hotfixRelaysThatDoNotHaveDaita()
} catch {
logger.error(
error: error,
@@ -74,9 +75,58 @@ final class RelayCacheTracker: RelayCacheTrackerProtocol {
}
}
+ /// This method updates the cached relay to include daita information
+ ///
+ /// This is a hotfix meant to upgrade clients shipped with 2024.5 or before that did not have
+ /// daita information in their representation of `ServerRelay`.
+ /// If a version <= 2024.5 is installed less than an hour before a new upgrade,
+ /// no servers will be shown in locations when filtering for daita relays.
+ ///
+ /// > Info: `relayCacheLock` does not need to be accessed here, this method should be ran from `init` only.
+ private func hotfixRelaysThatDoNotHaveDaita() throws {
+ guard let cachedRelays else { return }
+ let daitaPropertyMissing = cachedRelays.relays.wireguard.relays.first { $0.daita ?? false } == nil
+ // If the cached relays already have daita information, this fix is not necessary
+ guard daitaPropertyMissing else { return }
+
+ let preBundledRelays = try cache.readPrebundledRelays()
+ let preBundledDaitaRelays = preBundledRelays.relays.wireguard.relays.filter { $0.daita == true }
+ var cachedRelaysWithFixedDaita = cachedRelays.relays.wireguard.relays
+
+ // For each daita enabled relay in the prebundled relays
+ // Find the corresponding relay in the cache by matching relay hostnames
+ // Then update it to toggle daita
+ for index in 0 ..< cachedRelaysWithFixedDaita.endIndex {
+ let relay = cachedRelaysWithFixedDaita[index]
+ preBundledDaitaRelays.forEach {
+ if $0.hostname == relay.hostname {
+ cachedRelaysWithFixedDaita[index] = relay.override(daita: true)
+ }
+ }
+ }
+
+ let wireguard = REST.ServerWireguardTunnels(
+ ipv4Gateway:
+ cachedRelays.relays.wireguard.ipv4Gateway,
+ ipv6Gateway: cachedRelays.relays.wireguard.ipv6Gateway,
+ portRanges: cachedRelays.relays.wireguard.portRanges,
+ relays: cachedRelaysWithFixedDaita
+ )
+
+ let updatedRelays = REST.ServerRelaysResponse(
+ locations: cachedRelays.relays.locations,
+ wireguard: wireguard,
+ bridge: cachedRelays.relays.bridge
+ )
+
+ let updatedCachedRelays = CachedRelays(relays: updatedRelays, updatedAt: Date())
+ try cache.write(record: updatedCachedRelays)
+ self.cachedRelays = updatedCachedRelays
+ }
+
func startPeriodicUpdates() {
- nslock.lock()
- defer { nslock.unlock() }
+ relayCacheLock.lock()
+ defer { relayCacheLock.unlock() }
guard !isPeriodicUpdatesEnabled else { return }
@@ -90,8 +140,8 @@ final class RelayCacheTracker: RelayCacheTrackerProtocol {
}
func stopPeriodicUpdates() {
- nslock.lock()
- defer { nslock.unlock() }
+ relayCacheLock.lock()
+ defer { relayCacheLock.unlock() }
guard isPeriodicUpdatesEnabled else { return }
@@ -135,8 +185,8 @@ final class RelayCacheTracker: RelayCacheTrackerProtocol {
}
func getCachedRelays() throws -> CachedRelays {
- nslock.lock()
- defer { nslock.unlock() }
+ relayCacheLock.lock()
+ defer { relayCacheLock.unlock() }
if let cachedRelays {
return cachedRelays
@@ -148,9 +198,9 @@ final class RelayCacheTracker: RelayCacheTrackerProtocol {
func refreshCachedRelays() throws {
let newCachedRelays = try cache.read()
- nslock.lock()
+ relayCacheLock.lock()
cachedRelays = newCachedRelays
- nslock.unlock()
+ relayCacheLock.unlock()
DispatchQueue.main.async {
self.observerList.notify { observer in
@@ -160,8 +210,8 @@ final class RelayCacheTracker: RelayCacheTrackerProtocol {
}
func getNextUpdateDate() -> Date {
- nslock.lock()
- defer { nslock.unlock() }
+ relayCacheLock.lock()
+ defer { relayCacheLock.unlock() }
return _getNextUpdateDate()
}