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
- Upgrade OpenSSL to 1.1.1q.
- Use natively async methods from NetworkExtension. [#284](https://github.com/passepartoutvpn/tunnelkit/pull/284)
### Fixed

View File

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