diff --git a/Passepartout.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Passepartout.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index fd51ab5f..e9f76def 100644 --- a/Passepartout.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Passepartout.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -51,8 +51,8 @@ "repositoryURL": "https://github.com/passepartoutvpn/tunnelkit", "state": { "branch": null, - "revision": "ca378c4999f2040565b9ec944746b684ab19c347", - "version": "5.0.0" + "revision": "3a54295ed9d2b71057fdeef752144beea66e31f2", + "version": null } }, { diff --git a/Passepartout/AppShared/Context/CoreContext.swift b/Passepartout/AppShared/Context/CoreContext.swift index d821fde7..684374a4 100644 --- a/Passepartout/AppShared/Context/CoreContext.swift +++ b/Passepartout/AppShared/Context/CoreContext.swift @@ -90,13 +90,15 @@ class CoreContext { ) #if targetEnvironment(simulator) - let strategy = MockVPNManagerStrategy() + let vpn = MockVPN() #else + let vpn = NetworkExtensionVPN() + #endif let strategy = TunnelKitVPNManagerStrategy( appGroup: Constants.App.appGroupId, - tunnelBundleIdentifier: Constants.App.tunnelBundleId + tunnelBundleIdentifier: Constants.App.tunnelBundleId, + vpn: vpn ) - #endif vpnManager = VPNManager( appGroup: Constants.App.appGroupId, store: store, diff --git a/PassepartoutLibrary/Package.swift b/PassepartoutLibrary/Package.swift index 135bf1e3..7aea8bab 100644 --- a/PassepartoutLibrary/Package.swift +++ b/PassepartoutLibrary/Package.swift @@ -23,8 +23,8 @@ let package = Package( dependencies: [ // Dependencies declare other packages that this package depends on. // .package(url: /* package url */, from: "1.0.0"), - .package(name: "TunnelKit", url: "https://github.com/passepartoutvpn/tunnelkit", from: "5.0.0"), -// .package(name: "TunnelKit", url: "https://github.com/passepartoutvpn/tunnelkit", .revision("000fde0aa2f028575e811a984ef1972cb9afeb36")), +// .package(name: "TunnelKit", url: "https://github.com/passepartoutvpn/tunnelkit", from: "5.0.0"), + .package(name: "TunnelKit", url: "https://github.com/passepartoutvpn/tunnelkit", .revision("3a54295ed9d2b71057fdeef752144beea66e31f2")), // .package(name: "TunnelKit", path: "../../tunnelkit"), .package(url: "https://github.com/zoul/generic-json-swift", from: "2.0.0"), .package(url: "https://github.com/SwiftyBeaver/SwiftyBeaver", from: "1.9.0") diff --git a/PassepartoutLibrary/Sources/PassepartoutVPN/Managers/MockVPNManagerStrategy.swift b/PassepartoutLibrary/Sources/PassepartoutVPN/Managers/MockVPNManagerStrategy.swift deleted file mode 100644 index 0b13c7d3..00000000 --- a/PassepartoutLibrary/Sources/PassepartoutVPN/Managers/MockVPNManagerStrategy.swift +++ /dev/null @@ -1,126 +0,0 @@ -// -// MockVPNManagerStrategy.swift -// Passepartout -// -// Created by Davide De Rosa on 2/9/22. -// Copyright (c) 2022 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 Combine -import TunnelKitCore -import PassepartoutCore - -// XXX: mock connect/disconnect tasks overlap, should cancel other pending task - -public class MockVPNManagerStrategy: VPNManagerStrategy { - private var currentState: ObservableVPNState? - - private var dataCountTimer: AnyCancellable? - - public init() { - } - - public func observe(into state: ObservableVPNState) { - currentState = state - } - - public func reinstate(configuration: VPNConfiguration) { - } - - @MainActor - public func connect(configuration: VPNConfiguration) { - guard currentState?.vpnStatus != .connected else { - return - } - Task { - currentState?.isEnabled = true - currentState?.vpnStatus = .connecting - await Task.maybeWait(forMilliseconds: 1000) - currentState?.vpnStatus = .connected - startCountingData() - } - } - - @MainActor - public func reconnect() async { - guard currentState?.vpnStatus == .connected else { - return - } - Task { - currentState?.vpnStatus = .disconnecting - await Task.maybeWait(forMilliseconds: 1000) - currentState?.vpnStatus = .disconnected - await Task.maybeWait(forMilliseconds: 1000) - currentState?.vpnStatus = .connecting - await Task.maybeWait(forMilliseconds: 1000) - currentState?.vpnStatus = .connected - currentState?.dataCount = nil - } - } - - @MainActor - public func disconnect() { - stopCountingData() - guard currentState?.vpnStatus != .disconnected else { - return - } - Task { - currentState?.isEnabled = false - currentState?.vpnStatus = .disconnecting - await Task.maybeWait(forMilliseconds: 1000) - currentState?.vpnStatus = .disconnected - currentState?.dataCount = nil - } - } - - private func startCountingData() { - guard currentState?.vpnStatus == .connected else { - return - } - guard dataCountTimer == nil else { - return - } - dataCountTimer = Timer.TimerPublisher(interval: 2.0, runLoop: .main, mode: .common) - .autoconnect() - .sink(receiveValue: { _ in - let previous = self.currentState?.dataCount ?? DataCount(0, 0) - self.currentState?.dataCount = DataCount(previous.received + 4000, previous.sent + 2000) - }) - } - - private func stopCountingData() { - dataCountTimer?.cancel() - dataCountTimer = nil - } - - @MainActor - public func removeConfigurations() { - disconnect() - } - - public func serverConfiguration(forProtocol vpnProtocol: VPNProtocolType) -> Any? { - nil - } - - public func debugLogURL(forProtocol vpnProtocol: VPNProtocolType) -> URL? { - nil - } -} diff --git a/PassepartoutLibrary/Sources/PassepartoutVPN/Managers/TunnelKitVPNManagerStrategy.swift b/PassepartoutLibrary/Sources/PassepartoutVPN/Managers/TunnelKitVPNManagerStrategy.swift index 45f16175..dc4152d9 100644 --- a/PassepartoutLibrary/Sources/PassepartoutVPN/Managers/TunnelKitVPNManagerStrategy.swift +++ b/PassepartoutLibrary/Sources/PassepartoutVPN/Managers/TunnelKitVPNManagerStrategy.swift @@ -32,7 +32,7 @@ import TunnelKitOpenVPNCore import PassepartoutCore import PassepartoutUtils -public class TunnelKitVPNManagerStrategy: VPNManagerStrategy { +public class TunnelKitVPNManagerStrategy: VPNManagerStrategy where VPNType.Configuration == NetworkExtensionConfiguration, VPNType.Extra == NetworkExtensionExtra { private struct AtomicState: Equatable { let isEnabled: Bool @@ -44,7 +44,7 @@ public class TunnelKitVPNManagerStrategy: VPNManagerStrategy { } } - private static let reconnectionSeconds = 2 + private let reconnectionSeconds = 2 private let appGroup: String @@ -52,7 +52,7 @@ public class TunnelKitVPNManagerStrategy: VPNManagerStrategy { private let defaults: UserDefaults - private let vpn: NetworkExtensionVPN + private let vpn: VPNType private let dataCountInterval: TimeInterval @@ -71,14 +71,19 @@ public class TunnelKitVPNManagerStrategy: VPNManagerStrategy { private var currentBundleIdentifier: String? @MainActor - public init(appGroup: String, tunnelBundleIdentifier: @escaping (VPNProtocolType) -> String, dataCountInterval: TimeInterval = 3.0) { + public init( + appGroup: String, + tunnelBundleIdentifier: @escaping (VPNProtocolType) -> String, + vpn: VPNType, + dataCountInterval: TimeInterval = 3.0 + ) { self.appGroup = appGroup self.tunnelBundleIdentifier = tunnelBundleIdentifier guard let defaults = UserDefaults(suiteName: appGroup) else { fatalError("No entitlements for group '\(appGroup)'") } self.defaults = defaults - vpn = NetworkExtensionVPN() + self.vpn = vpn self.dataCountInterval = dataCountInterval registerNotification(withName: VPNNotification.didReinstall) { @@ -151,7 +156,7 @@ public class TunnelKitVPNManagerStrategy: VPNManagerStrategy { bundleIdentifier, configuration: configuration.neConfiguration, extra: configuration.neExtra, - after: .seconds(Self.reconnectionSeconds) + after: .seconds(reconnectionSeconds) ) } catch { pp_log.error("Unable to connect: \(error)") @@ -160,7 +165,7 @@ public class TunnelKitVPNManagerStrategy: VPNManagerStrategy { public func reconnect() async { try? await vpn.reconnect( - after: .seconds(Self.reconnectionSeconds) + after: .seconds(reconnectionSeconds) ) }