aboutsummaryrefslogtreecommitdiffstats
path: root/WireGuard/Shared/NETunnelProviderProtocol+Extension.swift
diff options
context:
space:
mode:
Diffstat (limited to 'WireGuard/Shared/NETunnelProviderProtocol+Extension.swift')
-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
+ ]
+ }
+
}