TunnelsManager: restore sanity

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
This commit is contained in:
Jason A. Donenfeld 2018-11-03 17:23:03 +01:00
parent c80901fbed
commit 1568ae57e3
1 changed files with 20 additions and 45 deletions

View File

@ -48,11 +48,9 @@ class TunnelsManager {
os_log("Failed to load tunnel provider managers: %{public}@", log: OSLog.default, type: .debug, "\(error)") os_log("Failed to load tunnel provider managers: %{public}@", log: OSLog.default, type: .debug, "\(error)")
return return
} }
DispatchQueue.main.async {
completionHandler(TunnelsManager(tunnelProviders: managers ?? [])) completionHandler(TunnelsManager(tunnelProviders: managers ?? []))
} }
} }
}
func add(tunnelConfiguration: TunnelConfiguration, completionHandler: @escaping (TunnelContainer?, TunnelManagementError?) -> Void) { func add(tunnelConfiguration: TunnelConfiguration, completionHandler: @escaping (TunnelContainer?, TunnelManagementError?) -> Void) {
let tunnelName = tunnelConfiguration.interface.name let tunnelName = tunnelConfiguration.interface.name
@ -76,13 +74,10 @@ class TunnelsManager {
defer { self?.isAddingTunnel = false } defer { self?.isAddingTunnel = false }
guard (error == nil) else { guard (error == nil) else {
os_log("Add: Saving configuration failed: %{public}@", log: OSLog.default, type: .error, "\(error!)") os_log("Add: Saving configuration failed: %{public}@", log: OSLog.default, type: .error, "\(error!)")
DispatchQueue.main.async {
completionHandler(nil, TunnelManagementError.vpnSystemErrorOnAddTunnel) completionHandler(nil, TunnelManagementError.vpnSystemErrorOnAddTunnel)
}
return return
} }
DispatchQueue.main.async { [weak self] in if let s = self {
guard let s = self else { return }
let tunnel = TunnelContainer(tunnel: tunnelProviderManager) let tunnel = TunnelContainer(tunnel: tunnelProviderManager)
s.tunnels.append(tunnel) s.tunnels.append(tunnel)
s.tunnels.sort { $0.name < $1.name } s.tunnels.sort { $0.name < $1.name }
@ -137,13 +132,10 @@ class TunnelsManager {
defer { self?.isModifyingTunnel = false } defer { self?.isModifyingTunnel = false }
guard (error == nil) else { guard (error == nil) else {
os_log("Modify: Saving configuration failed: %{public}@", log: OSLog.default, type: .error, "\(error!)") os_log("Modify: Saving configuration failed: %{public}@", log: OSLog.default, type: .error, "\(error!)")
DispatchQueue.main.async {
completionHandler(TunnelManagementError.vpnSystemErrorOnModifyTunnel) completionHandler(TunnelManagementError.vpnSystemErrorOnModifyTunnel)
}
return return
} }
DispatchQueue.main.async { [weak self] in if let s = self {
guard let s = self else { return }
if (isNameChanged) { if (isNameChanged) {
let oldIndex = s.tunnels.firstIndex(of: tunnel)! let oldIndex = s.tunnels.firstIndex(of: tunnel)!
s.tunnels.sort { $0.name < $1.name } s.tunnels.sort { $0.name < $1.name }
@ -174,13 +166,12 @@ class TunnelsManager {
completionHandler(TunnelManagementError.vpnSystemErrorOnRemoveTunnel) completionHandler(TunnelManagementError.vpnSystemErrorOnRemoveTunnel)
return return
} }
DispatchQueue.main.async { [weak self] in if let s = self {
guard let s = self else { return }
let index = s.tunnels.firstIndex(of: tunnel)! let index = s.tunnels.firstIndex(of: tunnel)!
s.tunnels.remove(at: index) s.tunnels.remove(at: index)
s.delegate?.tunnelRemoved(at: index) s.delegate?.tunnelRemoved(at: index)
completionHandler(nil)
} }
completionHandler(nil)
} }
} }
@ -245,7 +236,7 @@ class TunnelContainer: NSObject {
@objc dynamic var status: TunnelStatus @objc dynamic var status: TunnelStatus
fileprivate let tunnelProvider: NETunnelProviderManager fileprivate let tunnelProvider: NETunnelProviderManager
fileprivate var statusObservationToken: AnyObject? private var statusObservationToken: AnyObject?
private var dnsResolver: DNSResolver? = nil private var dnsResolver: DNSResolver? = nil
@ -339,21 +330,18 @@ class TunnelContainer: NSObject {
tunnelProvider.saveToPreferences { [weak self] (error) in tunnelProvider.saveToPreferences { [weak self] (error) in
if (error != nil) { if (error != nil) {
os_log("Error saving tunnel after re-enabling: %{public}@", log: OSLog.default, type: .error, "\(error!)") os_log("Error saving tunnel after re-enabling: %{public}@", log: OSLog.default, type: .error, "\(error!)")
DispatchQueue.main.async {
completionHandler(error) completionHandler(error)
}
return return
} }
os_log("startActivation: Tunnel saved after re-enabling", log: OSLog.default, type: .info) os_log("startActivation: Tunnel saved after re-enabling", log: OSLog.default, type: .info)
os_log("startActivation: Invoking startActivation", log: OSLog.default, type: .debug) os_log("startActivation: Invoking startActivation", log: OSLog.default, type: .debug)
DispatchQueue.main.async { [weak self] in
self?.startActivation(recursionCount: recursionCount + 1, lastError: NEVPNError(NEVPNError.configurationUnknown), tunnelConfiguration: tunnelConfiguration, resolvedEndpoints: resolvedEndpoints, completionHandler: completionHandler) self?.startActivation(recursionCount: recursionCount + 1, lastError: NEVPNError(NEVPNError.configurationUnknown), tunnelConfiguration: tunnelConfiguration, resolvedEndpoints: resolvedEndpoints, completionHandler: completionHandler)
} }
}
return return
} }
// Start the tunnel // Start the tunnel
startObservingTunnelStatus()
let session = (tunnelProvider.connection as! NETunnelProviderSession) let session = (tunnelProvider.connection as! NETunnelProviderSession)
do { do {
os_log("startActivation: Generating options", log: OSLog.default, type: .debug) os_log("startActivation: Generating options", log: OSLog.default, type: .debug)
@ -362,22 +350,19 @@ class TunnelContainer: NSObject {
os_log("startActivation: Starting tunnel", log: OSLog.default, type: .debug) os_log("startActivation: Starting tunnel", log: OSLog.default, type: .debug)
try session.startTunnel(options: tunnelOptions) try session.startTunnel(options: tunnelOptions)
os_log("startActivation: Success", log: OSLog.default, type: .debug) os_log("startActivation: Success", log: OSLog.default, type: .debug)
startObservingTunnelStatus()
completionHandler(nil) completionHandler(nil)
} catch (let error) { } catch (let error) {
os_log("startActivation: Error starting tunnel. Examining error", log: OSLog.default, type: .debug) os_log("startActivation: Error starting tunnel. Examining error", log: OSLog.default, type: .debug)
guard let vpnError = error as? NEVPNError else { guard let vpnError = error as? NEVPNError else {
os_log("Failed to activate tunnel: %{public}@", log: OSLog.default, type: .debug, "\(error)") os_log("Failed to activate tunnel: %{public}@", log: OSLog.default, type: .debug, "\(error)")
DispatchQueue.main.async { status = .inactive
completionHandler(error) completionHandler(error)
}
return return
} }
guard (vpnError.code == NEVPNError.configurationInvalid || vpnError.code == NEVPNError.configurationStale) else { guard (vpnError.code == NEVPNError.configurationInvalid || vpnError.code == NEVPNError.configurationStale) else {
os_log("Failed to activate tunnel: %{public}@", log: OSLog.default, type: .debug, "\(error)") os_log("Failed to activate tunnel: %{public}@", log: OSLog.default, type: .debug, "\(error)")
DispatchQueue.main.async { status = .inactive
completionHandler(error) completionHandler(error)
}
return return
} }
assert(vpnError.code == NEVPNError.configurationInvalid || vpnError.code == NEVPNError.configurationStale) assert(vpnError.code == NEVPNError.configurationInvalid || vpnError.code == NEVPNError.configurationStale)
@ -387,19 +372,16 @@ class TunnelContainer: NSObject {
tunnelProvider.loadFromPreferences { [weak self] (error) in tunnelProvider.loadFromPreferences { [weak self] (error) in
if (error != nil) { if (error != nil) {
os_log("Failed to activate tunnel: %{public}@", log: OSLog.default, type: .debug, "\(error!)") os_log("Failed to activate tunnel: %{public}@", log: OSLog.default, type: .debug, "\(error!)")
DispatchQueue.main.async { self?.status = .inactive
completionHandler(error) completionHandler(error)
}
return return
} }
os_log("startActivation: Tunnel reloaded", log: OSLog.default, type: .info) os_log("startActivation: Tunnel reloaded", log: OSLog.default, type: .info)
os_log("startActivation: Invoking startActivation", log: OSLog.default, type: .debug) os_log("startActivation: Invoking startActivation", log: OSLog.default, type: .debug)
DispatchQueue.main.async { [weak self] in
self?.startActivation(recursionCount: recursionCount + 1, lastError: vpnError, tunnelConfiguration: tunnelConfiguration, resolvedEndpoints: resolvedEndpoints, completionHandler: completionHandler) self?.startActivation(recursionCount: recursionCount + 1, lastError: vpnError, tunnelConfiguration: tunnelConfiguration, resolvedEndpoints: resolvedEndpoints, completionHandler: completionHandler)
} }
} }
} }
}
fileprivate func startDeactivation() { fileprivate func startDeactivation() {
assert(status == .active) assert(status == .active)
@ -433,21 +415,14 @@ class TunnelContainer: NSObject {
} }
if (s.status == .resolvingEndpointDomains && connection.status == .disconnected) { if (s.status == .resolvingEndpointDomains && connection.status == .disconnected) {
// Don't change to .inactive if we're still resolving endpoints // Don't change to .inactive if we're still resolving endpoints
assert(false)
return return
} }
s.status = TunnelStatus(from: connection.status) s.status = TunnelStatus(from: connection.status)
if (s.status == .inactive) { if (s.status == .inactive) {
s.stopObservingTunnelStatus() s.statusObservationToken = nil
} }
} }
} }
private func stopObservingTunnelStatus() {
DispatchQueue.main.async { [weak self] in
self?.statusObservationToken = nil
}
}
} }
@objc enum TunnelStatus: Int { @objc enum TunnelStatus: Int {