diff --git a/swift/apple/FirezoneKit/Sources/FirezoneKit/Managers/TunnelManager.swift b/swift/apple/FirezoneKit/Sources/FirezoneKit/Managers/TunnelManager.swift index 4419fc1f3..cc39a832f 100644 --- a/swift/apple/FirezoneKit/Sources/FirezoneKit/Managers/TunnelManager.swift +++ b/swift/apple/FirezoneKit/Sources/FirezoneKit/Managers/TunnelManager.swift @@ -82,6 +82,8 @@ public enum TunnelMessage: Codable { } public class TunnelManager { + public static let shared = TunnelManager() + // Expose closures that someone else can use to respond to events // for this manager. var statusChangeHandler: ((NEVPNStatus) async -> Void)? @@ -109,10 +111,6 @@ public class TunnelManager { public static let bundleIdentifier: String = "\(Bundle.main.bundleIdentifier!).network-extension" private let bundleDescription = "Firezone" - init() { - manager = nil - } - // Initialize and save a new VPN profile in system Preferences func create() async throws -> Settings { let protocolConfiguration = NETunnelProviderProtocol() diff --git a/swift/apple/FirezoneKit/Sources/FirezoneKit/Stores/Store.swift b/swift/apple/FirezoneKit/Sources/FirezoneKit/Stores/Store.swift index 99d157b41..6df87bc3e 100644 --- a/swift/apple/FirezoneKit/Sources/FirezoneKit/Stores/Store.swift +++ b/swift/apple/FirezoneKit/Sources/FirezoneKit/Stores/Store.swift @@ -28,7 +28,6 @@ public final class Store: ObservableObject { // we could periodically update it if we need to. @Published private(set) var decision: UNAuthorizationStatus - public let tunnelManager: TunnelManager private var sessionNotification: SessionNotification private var cancellables: Set = [] private var resourcesTimer: Timer? @@ -38,7 +37,6 @@ public final class Store: ObservableObject { self.decision = .authorized self.settings = Settings.defaultValue - self.tunnelManager = TunnelManager() self.sessionNotification = SessionNotification() initNotifications() @@ -46,7 +44,7 @@ public final class Store: ObservableObject { } public func internetResourceEnabled() -> Bool { - tunnelManager.internetResourceEnabled + TunnelManager.shared.internetResourceEnabled } private func initNotifications() { @@ -65,11 +63,11 @@ public final class Store: ObservableObject { } private func initTunnelManager() { - // Subscribe to status updates from the tunnelManager - tunnelManager.statusChangeHandler = handleVPNStatusChange + // Subscribe to status updates from the tunnel manager + TunnelManager.shared.statusChangeHandler = handleVPNStatusChange // Load our existing VPN profile and initialize our state - tunnelManager.load() { loadedStatus, loadedSettings, loadedActorName in + TunnelManager.shared.load() { loadedStatus, loadedSettings, loadedActorName in DispatchQueue.main.async { self.status = loadedStatus @@ -98,7 +96,7 @@ public final class Store: ObservableObject { func createVPNProfile() { DispatchQueue.main.async { Task { - self.settings = try await self.tunnelManager.create() + self.settings = try await TunnelManager.shared.create() } } } @@ -114,25 +112,25 @@ public final class Store: ObservableObject { return } - tunnelManager.start(token: token) + TunnelManager.shared.start(token: token) } func stop(clearToken: Bool = false) { guard [.connected, .connecting, .reasserting].contains(status) else { return } - tunnelManager.stop(clearToken: clearToken) + TunnelManager.shared.stop(clearToken: clearToken) } func signIn(authResponse: AuthResponse) async throws { // Save actorName DispatchQueue.main.async { self.actorName = authResponse.actorName } - try await tunnelManager.saveSettings(settings) - try await tunnelManager.saveActorName(authResponse.actorName) + try await TunnelManager.shared.saveSettings(settings) + try await TunnelManager.shared.saveActorName(authResponse.actorName) // Bring the tunnel up and send it a token to start - tunnelManager.start(token: authResponse.token) + TunnelManager.shared.start(token: authResponse.token) } func signOut() async throws { @@ -145,11 +143,11 @@ public final class Store: ObservableObject { func beginUpdatingResources(callback: @escaping (ResourceList) -> Void) { Log.app.log("\(#function)") - tunnelManager.fetchResources(callback: callback) + TunnelManager.shared.fetchResources(callback: callback) let intervalInSeconds: TimeInterval = 1 let timer = Timer(timeInterval: intervalInSeconds, repeats: true) { [weak self] _ in guard let self = self else { return } - tunnelManager.fetchResources(callback: callback) + TunnelManager.shared.fetchResources(callback: callback) } RunLoop.main.add(timer, forMode: .common) resourcesTimer = timer @@ -163,7 +161,7 @@ public final class Store: ObservableObject { func save(_ newSettings: Settings) async throws { Task { do { - try await tunnelManager.saveSettings(newSettings) + try await TunnelManager.shared.saveSettings(newSettings) DispatchQueue.main.async { self.settings = newSettings } } catch { Log.app.error("\(#function): \(error)") @@ -172,9 +170,9 @@ public final class Store: ObservableObject { } func toggleInternetResource(enabled: Bool) { - tunnelManager.toggleInternetResource(enabled: enabled) + TunnelManager.shared.toggleInternetResource(enabled: enabled) var newSettings = settings - newSettings.internetResourceEnabled = tunnelManager.internetResourceEnabled + newSettings.internetResourceEnabled = TunnelManager.shared.internetResourceEnabled Task { try await save(newSettings) } diff --git a/swift/apple/FirezoneKit/Sources/FirezoneKit/Views/SettingsView.swift b/swift/apple/FirezoneKit/Sources/FirezoneKit/Views/SettingsView.swift index 8ec5db8ee..a39bf1f9a 100644 --- a/swift/apple/FirezoneKit/Sources/FirezoneKit/Views/SettingsView.swift +++ b/swift/apple/FirezoneKit/Sources/FirezoneKit/Views/SettingsView.swift @@ -76,7 +76,7 @@ public final class SettingsViewModel: ObservableObject { do { #if os(macOS) - let providerLogFolderSize = try await store.tunnelManager.getLogFolderSize() + let providerLogFolderSize = try await TunnelManager.shared.getLogFolderSize() let totalSize = logFolderSize + providerLogFolderSize #else let totalSize = logFolderSize @@ -105,7 +105,7 @@ public final class SettingsViewModel: ObservableObject { try Log.clear(in: SharedAccess.logFolderURL) #if os(macOS) - try await store.tunnelManager.clearLogs() + try await TunnelManager.shared.clearLogs() #endif } } diff --git a/swift/apple/FirezoneNetworkExtension/PacketTunnelProvider.swift b/swift/apple/FirezoneNetworkExtension/PacketTunnelProvider.swift index 7b67aa90c..98724cfd0 100644 --- a/swift/apple/FirezoneNetworkExtension/PacketTunnelProvider.swift +++ b/swift/apple/FirezoneNetworkExtension/PacketTunnelProvider.swift @@ -78,7 +78,7 @@ class PacketTunnelProvider: NEPacketTunnelProvider { try await adapter.start() - // Tell the system the tunnel is up, moving the tunnelManager status to + // Tell the system the tunnel is up, moving the tunnel manager status to // `connected`. completionHandler(nil) } catch {