diff --git a/PassepartoutLibrary/Package.swift b/PassepartoutLibrary/Package.swift
index 7c90df34..e8987693 100644
--- a/PassepartoutLibrary/Package.swift
+++ b/PassepartoutLibrary/Package.swift
@@ -85,7 +85,7 @@ let package = Package(
.target(
name: "PassepartoutCore",
dependencies: [
- .product(name: "GenericJSON", package: "generic-json-swift") // FIXME: arch, drop this
+ .product(name: "GenericJSON", package: "generic-json-swift")
]),
// MARK: App extensions
diff --git a/PassepartoutLibrary/Sources/PassepartoutCore/Utils/Utils+Dates.swift b/PassepartoutLibrary/Sources/PassepartoutCore/Utils/Utils+Dates.swift
index 7ea04d50..514b9ac7 100644
--- a/PassepartoutLibrary/Sources/PassepartoutCore/Utils/Utils+Dates.swift
+++ b/PassepartoutLibrary/Sources/PassepartoutCore/Utils/Utils+Dates.swift
@@ -52,3 +52,9 @@ extension TimeInterval {
return str
}
}
+
+extension TimeInterval {
+ public var dispatchTimeInterval: DispatchTimeInterval {
+ .nanoseconds(Int(self * Double(NSEC_PER_SEC)))
+ }
+}
diff --git a/PassepartoutLibrary/Sources/PassepartoutVPN/Domain/Profile+OpenVPNSettings.swift b/PassepartoutLibrary/Sources/PassepartoutVPN/Domain/Profile+OpenVPNSettings.swift
index a117dfd3..3e8e8b0e 100644
--- a/PassepartoutLibrary/Sources/PassepartoutVPN/Domain/Profile+OpenVPNSettings.swift
+++ b/PassepartoutLibrary/Sources/PassepartoutVPN/Domain/Profile+OpenVPNSettings.swift
@@ -43,4 +43,20 @@ extension Profile {
self.configuration = configuration
}
}
+
+ init(_ id: UUID = UUID(), name: String, configuration: OpenVPN.Configuration) {
+ let header = Header(
+ uuid: id,
+ name: name,
+ providerName: nil
+ )
+ self.init(header, configuration: configuration)
+ }
+
+ public init(_ header: Header, configuration: OpenVPN.Configuration) {
+ self.header = header
+ currentVPNProtocol = .openVPN
+ host = Host()
+ host?.ovpnSettings = OpenVPNSettings(configuration: configuration)
+ }
}
diff --git a/PassepartoutLibrary/Sources/PassepartoutVPN/Domain/Profile+WireGuardSettings.swift b/PassepartoutLibrary/Sources/PassepartoutVPN/Domain/Profile+WireGuardSettings.swift
index ddd8cb90..19cce0fd 100644
--- a/PassepartoutLibrary/Sources/PassepartoutVPN/Domain/Profile+WireGuardSettings.swift
+++ b/PassepartoutLibrary/Sources/PassepartoutVPN/Domain/Profile+WireGuardSettings.swift
@@ -39,4 +39,20 @@ extension Profile {
self.configuration = configuration
}
}
+
+ init(_ id: UUID = UUID(), name: String, configuration: WireGuard.Configuration) {
+ let header = Header(
+ uuid: id,
+ name: name,
+ providerName: nil
+ )
+ self.init(header, configuration: configuration)
+ }
+
+ public init(_ header: Header, configuration: WireGuard.Configuration) {
+ self.header = header
+ currentVPNProtocol = .wireGuard
+ host = Host()
+ host?.wgSettings = WireGuardSettings(configuration: configuration)
+ }
}
diff --git a/PassepartoutLibrary/Sources/PassepartoutVPN/Domain/Profile.swift b/PassepartoutLibrary/Sources/PassepartoutVPN/Domain/Profile.swift
index c32d73a2..f5c21846 100644
--- a/PassepartoutLibrary/Sources/PassepartoutVPN/Domain/Profile.swift
+++ b/PassepartoutLibrary/Sources/PassepartoutVPN/Domain/Profile.swift
@@ -25,8 +25,6 @@
import Foundation
import PassepartoutCore
-import TunnelKitOpenVPN
-import TunnelKitWireGuard
public protocol ProfileSubtype {
var vpnProtocols: [VPNProtocolType] { get }
@@ -59,24 +57,6 @@ public struct Profile: Identifiable, Codable, Equatable {
currentVPNProtocol = .openVPN
}
- init(_ id: UUID = UUID(), name: String, configuration: OpenVPN.Configuration) {
- let header = Header(
- uuid: id,
- name: name,
- providerName: nil
- )
- self.init(header, configuration: configuration)
- }
-
- init(_ id: UUID = UUID(), name: String, configuration: WireGuard.Configuration) {
- let header = Header(
- uuid: id,
- name: name,
- providerName: nil
- )
- self.init(header, configuration: configuration)
- }
-
init(_ id: UUID = UUID(), name: String, provider: Profile.Provider) {
let header = Header(
uuid: id,
@@ -86,20 +66,6 @@ public struct Profile: Identifiable, Codable, Equatable {
self.init(header, provider: provider)
}
- public init(_ header: Header, configuration: OpenVPN.Configuration) {
- self.header = header
- currentVPNProtocol = .openVPN
- host = Host()
- host?.ovpnSettings = OpenVPNSettings(configuration: configuration)
- }
-
- public init(_ header: Header, configuration: WireGuard.Configuration) {
- self.header = header
- currentVPNProtocol = .wireGuard
- host = Host()
- host?.wgSettings = WireGuardSettings(configuration: configuration)
- }
-
public init(_ header: Header, provider: Profile.Provider) {
guard let firstVPNProtocol = provider.vpnSettings.keys.first else {
fatalError("No VPN protocols defined in provider")
diff --git a/PassepartoutLibrary/Sources/PassepartoutVPN/Domain/VPNConfiguration.swift b/PassepartoutLibrary/Sources/PassepartoutVPN/Domain/VPNConfiguration.swift
deleted file mode 100644
index 6f7215bb..00000000
--- a/PassepartoutLibrary/Sources/PassepartoutVPN/Domain/VPNConfiguration.swift
+++ /dev/null
@@ -1,29 +0,0 @@
-//
-// VPNConfiguration.swift
-// Passepartout
-//
-// Created by Davide De Rosa on 6/22/22.
-// Copyright (c) 2023 Davide De Rosa. All rights reserved.
-//
-// https://github.com/passepartoutvpn
-//
-// This file is part of Passepartout.
-//
-// Passepartout is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// Passepartout is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with Passepartout. If not, see .
-//
-
-import Foundation
-import TunnelKitManager
-
-public typealias VPNConfiguration = (neConfiguration: NetworkExtensionConfiguration, neExtra: NetworkExtensionExtra)
diff --git a/PassepartoutLibrary/Sources/PassepartoutVPN/Domain/VPNConfigurationParameters.swift b/PassepartoutLibrary/Sources/PassepartoutVPN/Domain/VPNConfigurationParameters.swift
index d7b94af1..bd39428b 100644
--- a/PassepartoutLibrary/Sources/PassepartoutVPN/Domain/VPNConfigurationParameters.swift
+++ b/PassepartoutLibrary/Sources/PassepartoutVPN/Domain/VPNConfigurationParameters.swift
@@ -25,11 +25,13 @@
import Foundation
import PassepartoutCore
-import TunnelKitManager
+import PassepartoutProviders
public struct VPNConfigurationParameters {
public let profile: Profile
+ public let providerManager: ProviderManager
+
public var title: String {
profile.header.name
}
@@ -52,12 +54,14 @@ public struct VPNConfigurationParameters {
init(
_ profile: Profile,
+ providerManager: ProviderManager,
preferences: VPNPreferences,
passwordReference: Data?,
withNetworkSettings: Bool,
withCustomRules: Bool
) {
self.profile = profile
+ self.providerManager = providerManager
self.preferences = preferences
self.passwordReference = passwordReference
self.withNetworkSettings = withNetworkSettings
diff --git a/PassepartoutLibrary/Sources/PassepartoutVPN/Managers/VPNManager+Extensions.swift b/PassepartoutLibrary/Sources/PassepartoutVPN/Managers/VPNManager+Extensions.swift
index 4d454b1b..87e0573d 100644
--- a/PassepartoutLibrary/Sources/PassepartoutVPN/Managers/VPNManager+Extensions.swift
+++ b/PassepartoutLibrary/Sources/PassepartoutVPN/Managers/VPNManager+Extensions.swift
@@ -65,10 +65,9 @@ extension VPNManager {
if let newPassword {
profile.account.password = newPassword
}
- let cfg = try vpnConfiguration(withProfile: profile)
profileManager.activateProfile(profile)
- await reconnect(cfg)
+ await reconnect(profile)
return profile
}
@@ -99,14 +98,13 @@ extension VPNManager {
pp_log.info("Connecting to: \(profile.logDescription) @ \(newServer.logDescription)")
profile.setProviderServer(newServer)
- let cfg = try vpnConfiguration(withProfile: profile)
profileManager.activateProfile(profile)
guard !profileManager.isCurrentProfile(profileId) else {
pp_log.debug("Active profile is current, will reconnect via observation")
return profile
}
- await reconnect(cfg)
+ await reconnect(profile)
return profile
}
@@ -118,13 +116,12 @@ extension VPNManager {
pp_log.info("Modifying active profile")
block(&profile)
- let cfg = try vpnConfiguration(withProfile: profile)
profileManager.activateProfile(profile)
guard !profileManager.isCurrentProfile(profile.id) else {
pp_log.debug("Active profile is current, will reinstate via observation")
return
}
- await reinstate(cfg)
+ await reinstate(profile)
}
}
diff --git a/PassepartoutLibrary/Sources/PassepartoutVPN/Managers/VPNManager.swift b/PassepartoutLibrary/Sources/PassepartoutVPN/Managers/VPNManager.swift
index 6559e21d..4754c0e8 100644
--- a/PassepartoutLibrary/Sources/PassepartoutVPN/Managers/VPNManager.swift
+++ b/PassepartoutLibrary/Sources/PassepartoutVPN/Managers/VPNManager.swift
@@ -84,16 +84,28 @@ public final class VPNManager: ObservableObject {
currentState = ObservableVPNState()
}
- func reinstate(_ configuration: VPNConfiguration) async {
+ func reinstate(_ profile: Profile) async {
pp_log.info("Reinstating VPN")
clearLastError()
- await strategy.reinstate(configuration: configuration)
+ do {
+ let parameters = try vpnConfigurationParameters(withProfile: profile)
+ await strategy.reinstate(parameters)
+ } catch {
+ pp_log.error("Unable to build configuration: \(error)")
+ configurationError.send((profile, error))
+ }
}
- func reconnect(_ configuration: VPNConfiguration) async {
+ func reconnect(_ profile: Profile) async {
pp_log.info("Reconnecting VPN (with new configuration)")
clearLastError()
- await strategy.connect(configuration: configuration)
+ do {
+ let parameters = try vpnConfigurationParameters(withProfile: profile)
+ await strategy.connect(parameters)
+ } catch {
+ pp_log.error("Unable to build configuration: \(error)")
+ configurationError.send((profile, error))
+ }
}
public func reconnect() async {
@@ -139,7 +151,11 @@ extension VPNManager {
}
private func observeStrategy() {
- strategy.observe(into: MutableObservableVPNState(currentState))
+ strategy.observe(into: MutableObservableVPNState(currentState)) { profile, error in
+
+ // UI is certainly interested in configuration errors
+ self.configurationError.send((profile, error))
+ }
}
private func observeProfileManager() {
@@ -233,72 +249,51 @@ extension VPNManager {
guard isHandled else {
return
}
- guard let cfg = vpnConfigurationWithCurrentProfile() else {
+ guard profileManager.isActiveProfile(newProfile.id) else {
+ pp_log.info("Skipping VPN reaction, current profile is not active")
return
}
if shouldReconnect {
- await reconnect(cfg)
+ await reconnect(newProfile)
} else {
- await reinstate(cfg)
+ await reinstate(newProfile)
}
}
}
// MARK: Configuration
-extension VPNManager {
- func vpnConfigurationWithCurrentProfile() -> VPNConfiguration? {
- do {
- guard profileManager.isCurrentProfileActive() else {
- pp_log.info("Skipping VPN configuration, current profile is not active")
- return nil
+private extension VPNManager {
+ func vpnConfigurationParameters(withProfile profile: Profile) throws -> VPNConfigurationParameters {
+ if profile.requiresCredentials {
+ guard !profile.account.isEmpty else {
+ throw PassepartoutError.missingAccount
}
- return try vpnConfiguration(withProfile: profileManager.currentProfile.value)
- } catch {
- return nil
}
- }
- func vpnConfiguration(withProfile profile: Profile) throws -> VPNConfiguration {
- do {
- if profile.requiresCredentials {
- guard !profile.account.isEmpty else {
- throw PassepartoutError.missingAccount
- }
+ // specific provider customizations
+ var newPassword: String?
+ if let providerName = profile.providerName {
+ switch providerName {
+ case .mullvad:
+ newPassword = "m"
+
+ default:
+ break
}
-
- // specific provider customizations
- var newPassword: String?
- if let providerName = profile.providerName {
- switch providerName {
- case .mullvad:
- newPassword = "m"
-
- default:
- break
- }
- }
-
- // IMPORTANT: must commit password to keychain (tunnel needs a password reference)
- profileManager.savePassword(forProfile: profile, newPassword: newPassword)
-
- let parameters = VPNConfigurationParameters(
- profile,
- preferences: vpnPreferences,
- passwordReference: profileManager.passwordReference(forProfile: profile),
- withNetworkSettings: isNetworkSettingsSupported(),
- withCustomRules: isOnDemandRulesSupported()
- )
-
- return try strategy.vpnConfiguration(parameters, providerManager: providerManager)
- } catch {
- pp_log.error("Unable to build VPNConfiguration: \(error)")
-
- // UI is certainly interested in configuration errors
- configurationError.send((profile, error))
-
- throw error
}
+
+ // IMPORTANT: must commit password to keychain (tunnel needs a password reference)
+ profileManager.savePassword(forProfile: profile, newPassword: newPassword)
+
+ return VPNConfigurationParameters(
+ profile,
+ providerManager: providerManager,
+ preferences: vpnPreferences,
+ passwordReference: profileManager.passwordReference(forProfile: profile),
+ withNetworkSettings: isNetworkSettingsSupported(),
+ withCustomRules: isOnDemandRulesSupported()
+ )
}
}
diff --git a/PassepartoutLibrary/Sources/PassepartoutVPN/Strategies/VPNManagerStrategy.swift b/PassepartoutLibrary/Sources/PassepartoutVPN/Strategies/VPNManagerStrategy.swift
index 150c8898..4a04c1ac 100644
--- a/PassepartoutLibrary/Sources/PassepartoutVPN/Strategies/VPNManagerStrategy.swift
+++ b/PassepartoutLibrary/Sources/PassepartoutVPN/Strategies/VPNManagerStrategy.swift
@@ -29,11 +29,11 @@ import PassepartoutCore
import PassepartoutProviders
public protocol VPNManagerStrategy {
- func observe(into state: MutableObservableVPNState)
+ func observe(into state: MutableObservableVPNState, onConfigurationError: @escaping (Profile, Error) -> Void)
- func reinstate(configuration: VPNConfiguration) async
+ func reinstate(_ parameters: VPNConfigurationParameters) async
- func connect(configuration: VPNConfiguration) async
+ func connect(_ parameters: VPNConfigurationParameters) async
func reconnect() async
@@ -44,9 +44,4 @@ public protocol VPNManagerStrategy {
func serverConfiguration(forProtocol vpnProtocol: VPNProtocolType) -> Any?
func debugLogURL(forProtocol vpnProtocol: VPNProtocolType) -> URL?
-
- func vpnConfiguration(
- _ parameters: VPNConfigurationParameters,
- providerManager: ProviderManager
- ) throws -> VPNConfiguration
}
diff --git a/PassepartoutLibrary/Sources/PassepartoutVPNImpl/Extensions/OpenVPNSettings+TunnelKit.swift b/PassepartoutLibrary/Sources/PassepartoutVPNImpl/Extensions/OpenVPNSettings+TunnelKit.swift
index 59bc4923..8366ce3f 100644
--- a/PassepartoutLibrary/Sources/PassepartoutVPNImpl/Extensions/OpenVPNSettings+TunnelKit.swift
+++ b/PassepartoutLibrary/Sources/PassepartoutVPNImpl/Extensions/OpenVPNSettings+TunnelKit.swift
@@ -30,7 +30,7 @@ import TunnelKitManager
import TunnelKitOpenVPN
extension Profile.OpenVPNSettings: TunnelKitConfigurationProviding {
- func tunnelKitConfiguration(_ appGroup: String, parameters: VPNConfigurationParameters) throws -> VPNConfiguration {
+ func tunnelKitConfiguration(_ appGroup: String, parameters: VPNConfigurationParameters) throws -> TunnelKitVPNConfiguration {
var customBuilder = configuration.builder()
// tolerate widest range of certificates
diff --git a/PassepartoutLibrary/Sources/PassepartoutVPNImpl/Extensions/WireGuardSettings+TunnelKit.swift b/PassepartoutLibrary/Sources/PassepartoutVPNImpl/Extensions/WireGuardSettings+TunnelKit.swift
index 4cfe3115..13914938 100644
--- a/PassepartoutLibrary/Sources/PassepartoutVPNImpl/Extensions/WireGuardSettings+TunnelKit.swift
+++ b/PassepartoutLibrary/Sources/PassepartoutVPNImpl/Extensions/WireGuardSettings+TunnelKit.swift
@@ -30,7 +30,7 @@ import TunnelKitManager
import TunnelKitWireGuard
extension Profile.WireGuardSettings: TunnelKitConfigurationProviding {
- func tunnelKitConfiguration(_ appGroup: String, parameters: VPNConfigurationParameters) throws -> VPNConfiguration {
+ func tunnelKitConfiguration(_ appGroup: String, parameters: VPNConfigurationParameters) throws -> TunnelKitVPNConfiguration {
var customBuilder = configuration.builder()
// network settings
diff --git a/PassepartoutLibrary/Sources/PassepartoutVPNImpl/Strategies/TunnelKitVPNManagerStrategy.swift b/PassepartoutLibrary/Sources/PassepartoutVPNImpl/Strategies/TunnelKitVPNManagerStrategy.swift
index 5d7cd82c..9cc266e4 100644
--- a/PassepartoutLibrary/Sources/PassepartoutVPNImpl/Strategies/TunnelKitVPNManagerStrategy.swift
+++ b/PassepartoutLibrary/Sources/PassepartoutVPNImpl/Strategies/TunnelKitVPNManagerStrategy.swift
@@ -33,8 +33,10 @@ import TunnelKitCore
import TunnelKitManager
import TunnelKitOpenVPNCore
+typealias TunnelKitVPNConfiguration = (neConfiguration: NetworkExtensionConfiguration, neExtra: NetworkExtensionExtra)
+
protocol TunnelKitConfigurationProviding {
- func tunnelKitConfiguration(_ appGroup: String, parameters: VPNConfigurationParameters) throws -> VPNConfiguration
+ func tunnelKitConfiguration(_ appGroup: String, parameters: VPNConfigurationParameters) throws -> TunnelKitVPNConfiguration
}
public final class TunnelKitVPNManagerStrategy: VPNManagerStrategy where VPNType.Configuration == NetworkExtensionConfiguration, VPNType.Extra == NetworkExtensionExtra {
@@ -49,8 +51,6 @@ public final class TunnelKitVPNManagerStrategy: VPNManagerStrategy
}
}
- private let reconnectionSeconds = 2
-
private let appGroup: String
private let tunnelBundleIdentifier: (VPNProtocolType) -> String
@@ -59,12 +59,16 @@ public final class TunnelKitVPNManagerStrategy: VPNManagerStrategy
private let vpn: VPNType
+ private let reconnectionInterval: TimeInterval
+
private let dataCountInterval: TimeInterval
// MARK: State
private var currentState: MutableObservableVPNState?
+ private var onConfigurationError: ((Profile, Error) -> Void)?
+
private let vpnState = CurrentValueSubject(.init())
private var dataCountTimer: AnyCancellable?
@@ -79,6 +83,7 @@ public final class TunnelKitVPNManagerStrategy: VPNManagerStrategy
appGroup: String,
tunnelBundleIdentifier: @escaping (VPNProtocolType) -> String,
vpn: VPNType,
+ reconnectionInterval: TimeInterval = 2.0,
dataCountInterval: TimeInterval = 3.0
) {
self.appGroup = appGroup
@@ -88,6 +93,7 @@ public final class TunnelKitVPNManagerStrategy: VPNManagerStrategy
}
self.defaults = defaults
self.vpn = vpn
+ self.reconnectionInterval = reconnectionInterval
self.dataCountInterval = dataCountInterval
registerNotification(withName: VPNNotification.didReinstall) {
@@ -115,8 +121,9 @@ public final class TunnelKitVPNManagerStrategy: VPNManagerStrategy
// MARK: Actions
extension TunnelKitVPNManagerStrategy {
- public func observe(into state: MutableObservableVPNState) {
+ public func observe(into state: MutableObservableVPNState, onConfigurationError: @escaping (Profile, Error) -> Void) {
currentState = state
+ self.onConfigurationError = onConfigurationError
// use this to drop redundant NE notifications
vpnState
@@ -128,7 +135,10 @@ extension TunnelKitVPNManagerStrategy {
}.store(in: &cancellables)
}
- public func reinstate(configuration: VPNConfiguration) async {
+ public func reinstate(_ parameters: VPNConfigurationParameters) async {
+ guard let configuration = try? vpnConfiguration(withParameters: parameters) else {
+ return
+ }
guard let vpnType = configuration.neConfiguration as? VPNProtocolProviding else {
fatalError("Configuration must implement VPNProtocolProviding")
}
@@ -148,7 +158,10 @@ extension TunnelKitVPNManagerStrategy {
}
}
- public func connect(configuration: VPNConfiguration) async {
+ public func connect(_ parameters: VPNConfigurationParameters) async {
+ guard let configuration = try? vpnConfiguration(withParameters: parameters) else {
+ return
+ }
guard let vpnType = configuration.neConfiguration as? VPNProtocolProviding else {
fatalError("Configuration must implement VPNProtocolProviding")
}
@@ -162,7 +175,7 @@ extension TunnelKitVPNManagerStrategy {
bundleIdentifier,
configuration: configuration.neConfiguration,
extra: configuration.neExtra,
- after: .seconds(reconnectionSeconds)
+ after: reconnectionInterval.dispatchTimeInterval
)
} catch {
pp_log.error("Unable to connect: \(error)")
@@ -171,7 +184,7 @@ extension TunnelKitVPNManagerStrategy {
public func reconnect() async {
try? await vpn.reconnect(
- after: .seconds(reconnectionSeconds)
+ after: reconnectionInterval.dispatchTimeInterval
)
}
@@ -192,8 +205,8 @@ extension TunnelKitVPNManagerStrategy {
// MARK: Notifications
-extension TunnelKitVPNManagerStrategy {
- private func onVPNReinstall(_ notification: Notification) {
+private extension TunnelKitVPNManagerStrategy {
+ func onVPNReinstall(_ notification: Notification) {
guard isRelevantNotification(notification) else {
return
}
@@ -204,7 +217,7 @@ extension TunnelKitVPNManagerStrategy {
))
}
- private func onVPNStatus(_ notification: Notification) {
+ func onVPNStatus(_ notification: Notification) {
// assume first notified identifier to be the relevant one
// in order to restore VPN status on app launch
@@ -239,7 +252,7 @@ extension TunnelKitVPNManagerStrategy {
currentState?.lastError = error
}
- private func onVPNFail(_ notification: Notification) {
+ func onVPNFail(_ notification: Notification) {
vpnState.send(AtomicState(
isEnabled: notification.vpnIsEnabled,
vpnStatus: vpnState.value.vpnStatus
@@ -247,7 +260,7 @@ extension TunnelKitVPNManagerStrategy {
currentState?.lastError = notification.vpnError
}
- private func isRelevantNotification(_ notification: Notification) -> Bool {
+ func isRelevantNotification(_ notification: Notification) -> Bool {
guard let notificationTunnelIdentifier = notification.vpnBundleIdentifier else {
return false
}
@@ -260,7 +273,7 @@ extension TunnelKitVPNManagerStrategy {
// MARK: Data count
- private func onDataCount(_: Date) {
+ func onDataCount(_: Date) {
switch vpnState.value.vpnStatus {
case .connected:
guard let currentDataCount = currentDataCount else {
@@ -273,7 +286,7 @@ extension TunnelKitVPNManagerStrategy {
}
}
- private func startCountingData() {
+ func startCountingData() {
guard dataCountTimer == nil else {
return
}
@@ -284,7 +297,7 @@ extension TunnelKitVPNManagerStrategy {
}
}
- private func stopCountingData() {
+ func stopCountingData() {
dataCountTimer?.cancel()
dataCountTimer = nil
@@ -292,6 +305,45 @@ extension TunnelKitVPNManagerStrategy {
}
}
+// MARK: Configuration
+
+private extension TunnelKitVPNManagerStrategy {
+ func vpnConfiguration(withParameters parameters: VPNConfigurationParameters) throws -> TunnelKitVPNConfiguration {
+ let profile = parameters.profile
+ do {
+ switch profile.currentVPNProtocol {
+ case .openVPN:
+ let settings: Profile.OpenVPNSettings
+ if profile.isProvider {
+ settings = try profile.providerOpenVPNSettings(withManager: parameters.providerManager)
+ } else {
+ guard let hostSettings = profile.hostOpenVPNSettings else {
+ fatalError("Profile currentVPNProtocol is OpenVPN, but host has no OpenVPN settings")
+ }
+ settings = hostSettings
+ }
+ return try settings.tunnelKitConfiguration(appGroup, parameters: parameters)
+
+ case .wireGuard:
+ let settings: Profile.WireGuardSettings
+ if profile.isProvider {
+ settings = try profile.providerWireGuardSettings(withManager: parameters.providerManager)
+ } else {
+ guard let hostSettings = profile.hostWireGuardSettings else {
+ fatalError("Profile currentVPNProtocol is WireGuard, but host has no WireGuard settings")
+ }
+ settings = hostSettings
+ }
+ return try settings.tunnelKitConfiguration(appGroup, parameters: parameters)
+ }
+ } catch {
+ pp_log.error("Unable to build TunnelKitVPNConfiguration: \(error)")
+ onConfigurationError?(profile, error)
+ throw error
+ }
+ }
+}
+
// MARK: Pulled
extension TunnelKitVPNManagerStrategy {
@@ -314,10 +366,12 @@ extension TunnelKitVPNManagerStrategy {
return defaults.wireGuardURLForDebugLog(appGroup: appGroup)
}
}
+}
- // MARK: Callbacks
+// MARK: Callbacks
- private func lastError(withBundleIdentifier bundleIdentifier: String?) -> Error? {
+private extension TunnelKitVPNManagerStrategy {
+ func lastError(withBundleIdentifier bundleIdentifier: String?) -> Error? {
switch bundleIdentifier {
case tunnelBundleIdentifier(.openVPN):
return defaults.openVPNLastError
@@ -330,7 +384,7 @@ extension TunnelKitVPNManagerStrategy {
}
}
- private var currentDataCount: DataCount? {
+ var currentDataCount: DataCount? {
switch currentBundleIdentifier {
case tunnelBundleIdentifier(.openVPN):
return defaults.openVPNDataCount
@@ -340,36 +394,3 @@ extension TunnelKitVPNManagerStrategy {
}
}
}
-
-// MARK: Configuration
-
-extension TunnelKitVPNManagerStrategy {
- public func vpnConfiguration(_ parameters: VPNConfigurationParameters, providerManager: ProviderManager) throws -> VPNConfiguration {
- let profile = parameters.profile
- switch profile.currentVPNProtocol {
- case .openVPN:
- let settings: Profile.OpenVPNSettings
- if profile.isProvider {
- settings = try profile.providerOpenVPNSettings(withManager: providerManager)
- } else {
- guard let hostSettings = profile.hostOpenVPNSettings else {
- fatalError("Profile currentVPNProtocol is OpenVPN, but host has no OpenVPN settings")
- }
- settings = hostSettings
- }
- return try settings.tunnelKitConfiguration(appGroup, parameters: parameters)
-
- case .wireGuard:
- let settings: Profile.WireGuardSettings
- if profile.isProvider {
- settings = try profile.providerWireGuardSettings(withManager: providerManager)
- } else {
- guard let hostSettings = profile.hostWireGuardSettings else {
- fatalError("Profile currentVPNProtocol is WireGuard, but host has no WireGuard settings")
- }
- settings = hostSettings
- }
- return try settings.tunnelKitConfiguration(appGroup, parameters: parameters)
- }
- }
-}
diff --git a/PassepartoutLibrary/Tests/PassepartoutProvidersTests/ProvidersTests.swift b/PassepartoutLibrary/Tests/PassepartoutProvidersTests/ProvidersTests.swift
index 0a1df4d9..b59484e9 100644
--- a/PassepartoutLibrary/Tests/PassepartoutProvidersTests/ProvidersTests.swift
+++ b/PassepartoutLibrary/Tests/PassepartoutProvidersTests/ProvidersTests.swift
@@ -38,7 +38,6 @@ final class ProvidersTests: XCTestCase {
private var cancellables: Set = []
override func setUp() {
- let model = NSManagedObjectModel.mergedModel(from: [.module])!
persistence = ProvidersPersistence(withName: "ProvidersTests", cloudKit: false, author: nil)
let remoteStrategy = APIRemoteProvidersStrategy(