summaryrefslogtreecommitdiffhomepage
path: root/ios/MullvadREST
diff options
context:
space:
mode:
authorJon Petersson <jon.petersson@mullvad.net>2025-10-24 08:13:18 +0200
committerJon Petersson <jon.petersson@mullvad.net>2025-10-24 08:13:18 +0200
commit3fd0813021ce79818d39996ff089dfb8a5697ad4 (patch)
tree289ecb097e4eca02b78bbecfb72d93215c173873 /ios/MullvadREST
parent63e9eb92c6e7a1aee6b682ed885d10a6f6fc699c (diff)
parente1f357ea3b261265dca2ce0712b265f632079c37 (diff)
downloadmullvadvpn-3fd0813021ce79818d39996ff089dfb8a5697ad4.tar.xz
mullvadvpn-3fd0813021ce79818d39996ff089dfb8a5697ad4.zip
Merge branch 'fetch-current-location-asynchronously-upon-first-start-of-ios-1328'
Diffstat (limited to 'ios/MullvadREST')
-rw-r--r--ios/MullvadREST/ApiHandlers/DefaultLocationService.swift49
-rw-r--r--ios/MullvadREST/ApiHandlers/RESTDefaults.swift3
-rw-r--r--ios/MullvadREST/Info.plist2
-rw-r--r--ios/MullvadREST/Relay/LocationIdentifier.swift10
-rw-r--r--ios/MullvadREST/Relay/RelaySelector+Wireguard.swift9
-rw-r--r--ios/MullvadREST/Relay/RelaySelector.swift16
6 files changed, 66 insertions, 23 deletions
diff --git a/ios/MullvadREST/ApiHandlers/DefaultLocationService.swift b/ios/MullvadREST/ApiHandlers/DefaultLocationService.swift
new file mode 100644
index 0000000000..00d0d56c05
--- /dev/null
+++ b/ios/MullvadREST/ApiHandlers/DefaultLocationService.swift
@@ -0,0 +1,49 @@
+//
+// DefaultLocationService.swift
+// MullvadVPN
+//
+// Created by Jon Petersson on 2025-10-13.
+// Copyright © 2025 Mullvad VPN AB. All rights reserved.
+//
+
+import CoreLocation
+import MullvadLogging
+import MullvadTypes
+
+public struct DefaultLocationService {
+ private let urlSession: URLSessionProtocol
+ private let relayCache: CachedRelays
+ private let logger = Logger(label: "DefaultLocationService")
+
+ public init(urlSession: URLSessionProtocol, relayCache: CachedRelays) {
+ self.urlSession = urlSession
+ self.relayCache = relayCache
+ }
+
+ public func fetchCurrentLocationIdentifier() async throws -> REST.LocationIdentifier? {
+ // Safe to unwrap since it's a constant.
+ let url = URL(string: REST.amIMullvadHostname).unsafelyUnwrapped
+
+ let serverLocation: REST.ServerLocation
+ do {
+ let data = try await urlSession.data(
+ for: URLRequest(url: url, timeoutInterval: REST.defaultAPINetworkTimeout.timeInterval))
+ serverLocation = try JSONDecoder().decode(REST.ServerLocation.self, from: data.0)
+ } catch {
+ logger.log(level: .error, "Could not fetch server location: \(error.localizedDescription)")
+ return nil
+ }
+
+ let mappedRelays = RelayWithLocation.locateRelays(
+ relays: relayCache.relays.wireguard.relays,
+ locations: relayCache.relays.locations
+ )
+
+ let closestRelay = RelaySelector.WireGuard.closestRelay(
+ to: CLLocationCoordinate2D(latitude: serverLocation.latitude, longitude: serverLocation.longitude),
+ using: mappedRelays
+ )
+
+ return closestRelay?.location
+ }
+}
diff --git a/ios/MullvadREST/ApiHandlers/RESTDefaults.swift b/ios/MullvadREST/ApiHandlers/RESTDefaults.swift
index 775f61ffd1..b500826fdb 100644
--- a/ios/MullvadREST/ApiHandlers/RESTDefaults.swift
+++ b/ios/MullvadREST/ApiHandlers/RESTDefaults.swift
@@ -28,4 +28,7 @@ extension REST {
/// Default network timeout for API requests.
public static let defaultAPINetworkTimeout: Duration = .seconds(10)
+
+ /// am.i.mullvad.net hostname.
+ public static let amIMullvadHostname = infoDictionary["AmIMullvad"] as! String
}
diff --git a/ios/MullvadREST/Info.plist b/ios/MullvadREST/Info.plist
index 644beb120a..ec177522a4 100644
--- a/ios/MullvadREST/Info.plist
+++ b/ios/MullvadREST/Info.plist
@@ -2,6 +2,8 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
+ <key>AmIMullvad</key>
+ <string>$(AM_I_JSON_URL)</string>
<key>ApiHostName</key>
<string>$(API_HOST_NAME)</string>
<key>ApiEndpoint</key>
diff --git a/ios/MullvadREST/Relay/LocationIdentifier.swift b/ios/MullvadREST/Relay/LocationIdentifier.swift
index 53e753277c..cb087c255f 100644
--- a/ios/MullvadREST/Relay/LocationIdentifier.swift
+++ b/ios/MullvadREST/Relay/LocationIdentifier.swift
@@ -9,19 +9,19 @@
extension REST {
// locations are currently always "aa-bbb" for some country code aa and city code bbb. Should this change, this type can be extended.
public struct LocationIdentifier: Sendable {
- public let country: Substring
- public let city: Substring
+ public let country: String
+ public let city: String
- fileprivate static func parse(_ input: String) -> (Substring, Substring)? {
+ fileprivate static func parse(_ input: String) -> (String, String)? {
let components = input.split(separator: "-")
guard components.count == 2 else { return nil }
- return (components[0], components[1])
+ return (String(components[0]), String(components[1]))
}
}
}
extension REST.LocationIdentifier: RawRepresentable {
- public var rawValue: String { country.base }
+ public var rawValue: String { "\(country)-\(city)" }
public init?(rawValue: String) {
guard let parsed = Self.parse(rawValue) else { return nil }
diff --git a/ios/MullvadREST/Relay/RelaySelector+Wireguard.swift b/ios/MullvadREST/Relay/RelaySelector+Wireguard.swift
index dbf3030dab..aab6e73d04 100644
--- a/ios/MullvadREST/Relay/RelaySelector+Wireguard.swift
+++ b/ios/MullvadREST/Relay/RelaySelector+Wireguard.swift
@@ -6,6 +6,7 @@
// Copyright © 2025 Mullvad VPN AB. All rights reserved.
//
+import CoreLocation
import MullvadSettings
import MullvadTypes
@@ -47,7 +48,11 @@ extension RelaySelector {
var relayWithLocation: RelayWithLocation<REST.ServerRelay>?
if let referenceLocation {
- let relay = closestRelay(to: referenceLocation, using: relayWithLocations)
+ let relay = closestRelay(
+ to: CLLocationCoordinate2D(
+ latitude: referenceLocation.latitude, longitude: referenceLocation.longitude),
+ using: relayWithLocations
+ )
relayWithLocation = relayWithLocations.first(where: { $0.relay == relay })
}
@@ -61,7 +66,7 @@ extension RelaySelector {
}
public static func closestRelay(
- to location: Location,
+ to location: CLLocationCoordinate2D,
using relayWithLocations: [RelayWithLocation<REST.ServerRelay>]
) -> REST.ServerRelay? {
let relaysWithDistance = relayWithLocations.map {
diff --git a/ios/MullvadREST/Relay/RelaySelector.swift b/ios/MullvadREST/Relay/RelaySelector.swift
index dc74d28568..3b13121056 100644
--- a/ios/MullvadREST/Relay/RelaySelector.swift
+++ b/ios/MullvadREST/Relay/RelaySelector.swift
@@ -131,22 +131,6 @@ public enum RelaySelector {
return nil
}
- private static func makeRelayWithLocationFrom<T: AnyRelay>(
- _ serverLocation: REST.ServerLocation,
- relay: T
- ) -> RelayWithLocation<T>? {
- let location = Location(
- country: serverLocation.country,
- countryCode: String(relay.location.country),
- city: serverLocation.city,
- cityCode: String(relay.location.city),
- latitude: serverLocation.latitude,
- longitude: serverLocation.longitude
- )
-
- return RelayWithLocation(relay: relay, serverLocation: location)
- }
-
private static func filterByActive<T: AnyRelay>(
relays: [RelayWithLocation<T>]
) throws -> [RelayWithLocation<T>] {