aboutsummaryrefslogtreecommitdiffstats
path: root/WireGuard/Shared/NETunnelProviderProtocol+Extension.swift
diff options
context:
space:
mode:
authorEric Kuck <eric@bluelinelabs.com>2018-12-20 22:52:45 -0600
committerJason A. Donenfeld <Jason@zx2c4.com>2018-12-21 16:42:16 +0100
commit8553723e04c4d63b99e669df2e43fc4a914b7f9d (patch)
treee3b7b25777e47455a787fa590cf00d1c25cbdc5d /WireGuard/Shared/NETunnelProviderProtocol+Extension.swift
parentNE: simplify logic (diff)
downloadwireguard-apple-8553723e04c4d63b99e669df2e43fc4a914b7f9d.tar.xz
wireguard-apple-8553723e04c4d63b99e669df2e43fc4a914b7f9d.zip
Updated NETunnelProvider save format
Signed-off-by: Eric Kuck <eric@bluelinelabs.com>
Diffstat (limited to '')
-rw-r--r--WireGuard/Shared/NETunnelProviderProtocol+Extension.swift87
1 files changed, 70 insertions, 17 deletions
diff --git a/WireGuard/Shared/NETunnelProviderProtocol+Extension.swift b/WireGuard/Shared/NETunnelProviderProtocol+Extension.swift
index 776e03b..e5cfac8 100644
--- a/WireGuard/Shared/NETunnelProviderProtocol+Extension.swift
+++ b/WireGuard/Shared/NETunnelProviderProtocol+Extension.swift
@@ -3,24 +3,53 @@
import NetworkExtension
+let tunnelConfigurationVersion = 2
+
extension NETunnelProviderProtocol {
+
+ enum Keys: String {
+ case tunnelConfiguration = "TunnelConfiguration"
+ case tunnelConfigurationVersion = "TunnelConfigurationVersion"
+ case isActivateOnDemandEnabled = "IsActivateOnDemandEnabled"
+ }
+
+ var tunnelConfiguration: TunnelConfiguration? {
+ migrateConfigurationIfNeeded()
+
+ let tunnelConfigurationData: Data?
+ if let configurationDictionary = providerConfiguration?[Keys.tunnelConfiguration.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!)
+ }
+
+ var isActivateOnDemandEnabled: Bool {
+ return providerConfiguration?[Keys.isActivateOnDemandEnabled.rawValue] as? Bool ?? false
+ }
+
convenience init?(tunnelConfiguration: TunnelConfiguration, isActivateOnDemandEnabled: Bool) {
assert(!tunnelConfiguration.interface.name.isEmpty)
- guard let serializedTunnelConfiguration = try? JSONEncoder().encode(tunnelConfiguration) else { return nil }
-
+
+ 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 = [
- "tunnelConfiguration": serializedTunnelConfiguration,
- "tunnelConfigurationVersion": 1,
- "isActivateOnDemandEnabled": isActivateOnDemandEnabled
+ Keys.tunnelConfiguration.rawValue: tunnelConfigDictionary,
+ Keys.tunnelConfigurationVersion.rawValue: tunnelConfigurationVersion,
+ Keys.isActivateOnDemandEnabled.rawValue: isActivateOnDemandEnabled
]
- let endpoints = tunnelConfiguration.peers.compactMap {$0.endpoint}
+ let endpoints = tunnelConfiguration.peers.compactMap { $0.endpoint }
if endpoints.count == 1 {
- serverAddress = endpoints.first!.stringRepresentation()
+ serverAddress = endpoints[0].stringRepresentation
} else if endpoints.isEmpty {
serverAddress = "Unspecified"
} else {
@@ -29,18 +58,42 @@ extension NETunnelProviderProtocol {
username = tunnelConfiguration.interface.name
}
- func tunnelConfiguration() -> TunnelConfiguration? {
- guard let serializedTunnelConfiguration = providerConfiguration?["tunnelConfiguration"] as? Data else { return nil }
- return try? JSONDecoder().decode(TunnelConfiguration.self, from: serializedTunnelConfiguration)
- }
-
- var isActivateOnDemandEnabled: Bool {
- return (providerConfiguration?["isActivateOnDemandEnabled"] as? Bool) ?? false
- }
-
func hasTunnelConfiguration(tunnelConfiguration otherTunnelConfiguration: TunnelConfiguration) -> Bool {
- guard let serializedThisTunnelConfiguration = providerConfiguration?["tunnelConfiguration"] as? Data else { return false }
+ 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 providerConfiguration = providerConfiguration else { return false }
+ guard let configurationVersion = providerConfiguration[Keys.tunnelConfigurationVersion.rawValue] as? Int ?? providerConfiguration["tunnelConfigurationVersion"] as? Int else { return false }
+
+ if configurationVersion < tunnelConfigurationVersion {
+ switch configurationVersion {
+ case 1:
+ migrateFromConfigurationV1()
+ default:
+ fatalError("No migration from configuration version \(configurationVersion) exists.")
+ }
+ return true
+ }
+
+ return false
+ }
+
+ 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 isActivateOnDemandEnabled = providerConfiguration?["isActivateOnDemandEnabled"] as? Bool 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.tunnelConfiguration.rawValue: tunnelConfigDictionary,
+ Keys.tunnelConfigurationVersion.rawValue: tunnelConfigurationVersion,
+ Keys.isActivateOnDemandEnabled.rawValue: isActivateOnDemandEnabled
+ ]
+ }
+
}