Files
wireguard-apple/WireGuard/Shared/NETunnelProviderProtocol+Extension.swift
T
Jason A. Donenfeld 78b38a4eba Simplify versioning of stored data
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2018-12-21 18:58:06 +01:00

76 lines
3.3 KiB
Swift

// SPDX-License-Identifier: MIT
// Copyright © 2018 WireGuard LLC. All Rights Reserved.
import NetworkExtension
extension NETunnelProviderProtocol {
enum Keys: String {
case wgQuickConfig = "WgQuickConfigV1"
}
var tunnelConfiguration: TunnelConfiguration? {
migrateConfigurationIfNeeded()
let tunnelConfigurationData: Data?
if let configurationDictionary = providerConfiguration?[Keys.wgQuickConfig.rawValue] {
tunnelConfigurationData = try? JSONSerialization.data(withJSONObject: configurationDictionary, options: [])
} else {
tunnelConfigurationData = nil
}
guard tunnelConfigurationData != nil else { return nil }
return try? JSONDecoder().decode(TunnelConfiguration.self, from: tunnelConfigurationData!)
}
convenience init?(tunnelConfiguration: TunnelConfiguration) {
assert(!tunnelConfiguration.interface.name.isEmpty)
guard let tunnelConfigData = try? JSONEncoder().encode(tunnelConfiguration) else { return nil }
guard let tunnelConfigDictionary = try? JSONSerialization.jsonObject(with: tunnelConfigData, options: .allowFragments) else { return nil }
self.init()
let appId = Bundle.main.bundleIdentifier!
providerBundleIdentifier = "\(appId).network-extension"
providerConfiguration = [ Keys.wgQuickConfig.rawValue: tunnelConfigDictionary ]
let endpoints = tunnelConfiguration.peers.compactMap { $0.endpoint }
if endpoints.count == 1 {
serverAddress = endpoints[0].stringRepresentation
} else if endpoints.isEmpty {
serverAddress = "Unspecified"
} else {
serverAddress = "Multiple endpoints"
}
username = tunnelConfiguration.interface.name
}
func hasTunnelConfiguration(tunnelConfiguration otherTunnelConfiguration: TunnelConfiguration) -> Bool {
guard let serializedThisTunnelConfiguration = try? JSONEncoder().encode(tunnelConfiguration) else { return false }
guard let serializedOtherTunnelConfiguration = try? JSONEncoder().encode(otherTunnelConfiguration) else { return false }
return serializedThisTunnelConfiguration == serializedOtherTunnelConfiguration
}
@discardableResult
func migrateConfigurationIfNeeded() -> Bool {
guard let configurationVersion = providerConfiguration?["tunnelConfigurationVersion"] as? Int else { return false }
if configurationVersion == 1 {
migrateFromConfigurationV1()
} else {
fatalError("No migration from configuration version \(configurationVersion) exists.")
}
return true
}
private func migrateFromConfigurationV1() {
guard let serializedTunnelConfiguration = providerConfiguration?["tunnelConfiguration"] as? Data else { return }
guard let configuration = try? JSONDecoder().decode(LegacyTunnelConfiguration.self, from: serializedTunnelConfiguration) else { return }
guard let tunnelConfigData = try? JSONEncoder().encode(configuration.migrated) else { return }
guard let tunnelConfigDictionary = try? JSONSerialization.jsonObject(with: tunnelConfigData, options: .allowFragments) else { return }
providerConfiguration = [ Keys.wgQuickConfig.rawValue: tunnelConfigDictionary ]
}
}