Server Locations
Fetching Locations
Fetch the list of available VPN servers after authentication:
import KapeVPN
let locations = KapeLocationService(handle: handle)
try await locations.fetchLocations()
Locations are available as a flat list or grouped by continent:
// All locations
locations.allLocations // [KapeServerLocation]
// Grouped by continent
locations.locationsByContinent // [String: [KapeServerLocation]]
// e.g. ["Europe": [...], "North America": [...]]
Each KapeServerLocation provides:
| Property | Type | Description |
|---|---|---|
id | String | Location ID (pass to connect(to:)) |
name | String | Human-readable name (e.g. "Frankfurt") |
country | String | ISO 3166-1 alpha-2 country code |
continent | String | Continent or region name |
latitude | Double | Latitude coordinate |
longitude | Double | Longitude coordinate |
rating | KapeLocationRating? | Quality rating (smart locations only) |
KapeLocationRating values: excellent, good, ok, degraded, poor, unknown. The enum is Comparable —
higher ratings sort greater.
Smart Locations
Smart locations are the SDK's recommended servers for the current user. The rating combines several signals: ping latency (min, avg, median, p90), short HTTP download and upload measurements, and geographic distance. Results are cached per network — when the user reconnects to a known WiFi network, cached results are returned immediately without re-running the full measurement.
Fetch smart locations after fetchLocations():
try await locations.fetchSmartLocations()
locations.smartLocations // [KapeServerLocation] — sorted by best rating
To disable HTTP tests (recommended on cellular to save data and reduce measurement time):
try await locations.fetchSmartLocations(extendedTest: false)
To receive per-location progress updates while the measurement runs:
try await locations.fetchSmartLocations { progress in
Task { @MainActor in
print("\(progress.locationId): \(progress.pingMs ?? 0) ms")
}
}
Call fetchLocations() before fetchSmartLocations(). Smart locations are resolved by matching against the full
location list.
Network Monitoring
KapeNetworkHelper (part of KapeCore) keeps the SDK aware of the current network and exposes the WiFi identity for
display in your UI. It also enables per-network SmartLocation caching — when the user reconnects to a known network,
cached results are returned immediately.
Setup
Create one instance and call start() once after the SDK handle is ready — typically in your app's root object or
view model:
import KapeCore
let networkHelper = KapeNetworkHelper(handle: handle)
networkHelper.start()
KapeNetworkHelper uses NWPathMonitor to detect network changes. On each change it reads the current SSID and
BSSID, pushes them into the SDK configuration, and calls networkChanged() so the SDK can invalidate or restore
cached SmartLocation results for that network.
Call stop() when the helper is no longer needed:
networkHelper.stop()
Observing network info in SwiftUI
KapeNetworkHelper is an ObservableObject with two published properties:
| Property | Type | Description |
|---|---|---|
ssid | String? | WiFi network name. nil on cellular or when entitlement is missing. |
bssid | String? | WiFi access point MAC address. nil on cellular or when entitlement is missing. |
// In your view model
@Published private(set) var wifiSSID: String?
networkHelper.$ssid.assign(to: &$wifiSSID)
// In your SwiftUI view
Section("Network") {
LabeledContent("SSID") { Text(viewModel.wifiSSID ?? "–") }
}
iOS entitlement
On iOS, reading the SSID and BSSID requires the com.apple.developer.networking.wifi-info entitlement. Add it to
your app target's .entitlements file:
<key>com.apple.developer.networking.wifi-info</key>
<true/>
Without this entitlement, ssid and bssid are always nil. The helper still functions — network-change signals
are sent to the SDK — but per-network caching has no benefit since all networks appear identical.
On macOS, no entitlement is required. WiFi info is read via CoreWLAN.
Do not instantiate KapeNetworkHelper in the PacketTunnel extension. The extension does not need SmartLocation
caching and has a strict memory budget.