Updated NETunnelProvider save format
Signed-off-by: Eric Kuck <eric@bluelinelabs.com>
This commit is contained in:
committed by
Jason A. Donenfeld
parent
38445114e0
commit
8553723e04
@@ -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
|
||||
]
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user