Replace continuations with natively async methods (#284)

This commit is contained in:
Davide De Rosa 2022-10-12 22:28:33 +02:00 committed by GitHub
parent a3822678cf
commit 080ee35e61
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 51 additions and 98 deletions

View File

@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed ### Changed
- Upgrade OpenSSL to 1.1.1q. - Upgrade OpenSSL to 1.1.1q.
- Use natively async methods from NetworkExtension. [#284](https://github.com/passepartoutvpn/tunnelkit/pull/284)
### Fixed ### Fixed

View File

@ -31,7 +31,6 @@ private let log = SwiftyBeaver.self
/// `VPN` based on the NetworkExtension framework. /// `VPN` based on the NetworkExtension framework.
public class NetworkExtensionVPN: VPN { public class NetworkExtensionVPN: VPN {
private let semaphore = DispatchSemaphore(value: 1)
/** /**
Initializes a provider. Initializes a provider.
@ -49,13 +48,9 @@ public class NetworkExtensionVPN: VPN {
// MARK: Public // MARK: Public
public func prepare() async { public func prepare() async {
await withCheckedContinuation { (continuation: CheckedContinuation<Void, Never>) in _ = try? await NETunnelProviderManager.loadAllFromPreferences()
NETunnelProviderManager.loadAllFromPreferences { managers, error in
continuation.resume()
}
}
} }
public func install( public func install(
_ tunnelBundleIdentifier: String, _ tunnelBundleIdentifier: String,
configuration: NetworkExtensionConfiguration, configuration: NetworkExtensionConfiguration,
@ -104,48 +99,30 @@ public class NetworkExtensionVPN: VPN {
} }
public func disconnect() async { public func disconnect() async {
do { guard let managers = try? await lookupAll() else {
let managers = try await lookupAll() return
await withCheckedContinuation { (continuation: CheckedContinuation<Void, Never>) in }
guard !managers.isEmpty else { guard !managers.isEmpty else {
continuation.resume() return
return }
} for m in managers {
managers.forEach { m.connection.stopVPNTunnel()
let isLast = ($0 == managers.last) m.isOnDemandEnabled = false
$0.connection.stopVPNTunnel() m.isEnabled = false
$0.isOnDemandEnabled = false try? await m.saveToPreferences()
$0.isEnabled = false
$0.saveToPreferences { _ in
if isLast {
continuation.resume()
}
}
}
}
} catch {
} }
} }
public func uninstall() async { public func uninstall() async {
do { guard let managers = try? await lookupAll() else {
let managers = try await lookupAll() return
await withCheckedContinuation { (continuation: CheckedContinuation<Void, Never>) in }
guard !managers.isEmpty else { guard !managers.isEmpty else {
continuation.resume() return
return }
} for m in managers {
managers.forEach { m.connection.stopVPNTunnel()
let isLast = ($0 == managers.last) try? await m.removeFromPreferences()
$0.connection.stopVPNTunnel()
$0.removeFromPreferences { _ in
if isLast {
continuation.resume()
}
}
}
}
} catch {
} }
} }
@ -190,69 +167,44 @@ public class NetworkExtensionVPN: VPN {
protocolConfiguration: NETunnelProviderProtocol, protocolConfiguration: NETunnelProviderProtocol,
onDemandRules: [NEOnDemandRule] onDemandRules: [NEOnDemandRule]
) async throws -> NETunnelProviderManager { ) async throws -> NETunnelProviderManager {
try await withCheckedThrowingContinuation { continuation in manager.localizedDescription = title
manager.localizedDescription = title manager.protocolConfiguration = protocolConfiguration
manager.protocolConfiguration = protocolConfiguration
if !onDemandRules.isEmpty { if !onDemandRules.isEmpty {
manager.onDemandRules = onDemandRules manager.onDemandRules = onDemandRules
manager.isOnDemandEnabled = true manager.isOnDemandEnabled = true
} else { } else {
manager.isOnDemandEnabled = false manager.isOnDemandEnabled = false
} }
manager.isEnabled = true manager.isEnabled = true
manager.saveToPreferences { error in do {
if let error = error { try await manager.saveToPreferences()
manager.isOnDemandEnabled = false try await manager.loadFromPreferences()
manager.isEnabled = false notifyReinstall(manager)
continuation.resume(throwing: error) return manager
self.notifyInstallError(error) } catch {
} else { manager.isOnDemandEnabled = false
manager.loadFromPreferences { error in manager.isEnabled = false
if let error = error { notifyInstallError(error)
continuation.resume(throwing: error) throw error
self.notifyInstallError(error)
} else {
continuation.resume(returning: manager)
self.notifyReinstall(manager)
}
}
}
}
} }
} }
private func retainManagers(_ managers: [NETunnelProviderManager], isIncluded: (NETunnelProviderManager) -> Bool) async { private func retainManagers(_ managers: [NETunnelProviderManager], isIncluded: (NETunnelProviderManager) -> Bool) async {
await withCheckedContinuation { (continuation: CheckedContinuation<Void, Never>) in let others = managers.filter {
let others = managers.filter { !isIncluded($0)
!isIncluded($0) }
} guard !others.isEmpty else {
guard !others.isEmpty else { return
continuation.resume() }
return for o in others {
} try? await o.removeFromPreferences()
others.forEach {
let isLast = ($0 == others.last)
$0.removeFromPreferences { _ in
if isLast {
continuation.resume()
}
}
}
} }
} }
private func lookupAll() async throws -> [NETunnelProviderManager] { private func lookupAll() async throws -> [NETunnelProviderManager] {
try await withCheckedThrowingContinuation { continuation in try await NETunnelProviderManager.loadAllFromPreferences()
NETunnelProviderManager.loadAllFromPreferences { managers, error in
if let error = error {
continuation.resume(throwing: error)
} else {
continuation.resume(returning: managers ?? [])
}
}
}
} }
// MARK: Notifications // MARK: Notifications