VPN: Perform DNS resolution before starting the tunnel

This commit is contained in:
Roopesh Chander 2018-10-26 19:09:11 +05:30
parent 5cb2558fea
commit 02fb23bb45
1 changed files with 29 additions and 10 deletions

View File

@ -235,6 +235,8 @@ class TunnelContainer: NSObject {
private var onActive: ((Bool) -> Void)? = nil private var onActive: ((Bool) -> Void)? = nil
private var onInactive: ((Bool) -> Void)? = nil private var onInactive: ((Bool) -> Void)? = nil
private var dnsResolver: DNSResolver? = nil
init(tunnel: NETunnelProviderManager, index: Int) { init(tunnel: NETunnelProviderManager, index: Int) {
self.name = tunnel.localizedDescription ?? "Unnamed" self.name = tunnel.localizedDescription ?? "Unnamed"
let status = TunnelStatus(from: tunnel.connection.status) let status = TunnelStatus(from: tunnel.connection.status)
@ -253,16 +255,33 @@ class TunnelContainer: NSObject {
fileprivate func activate(completionHandler: @escaping (Bool) -> Void) { fileprivate func activate(completionHandler: @escaping (Bool) -> Void) {
assert(status == .inactive) assert(status == .inactive)
assert(onActive == nil) guard let tunnelConfiguration = tunnelConfiguration() else { fatalError() }
onActive = completionHandler let endpoints = tunnelConfiguration.peers.compactMap { $0.endpoint }
startObservingTunnelStatus() let dnsResolver = DNSResolver(endpoints: endpoints)
let session = (tunnelProvider.connection as! NETunnelProviderSession) assert(self.dnsResolver == nil)
do { self.dnsResolver = dnsResolver
try session.startTunnel(options: [:]) // TODO: Provide options status = .resolvingEndpointDomains
} catch (let error) { dnsResolver.resolve { [weak self] endpoints in
os_log("Failed to activate tunnel: %{public}@", log: OSLog.default, type: .debug, "\(error)") guard (!endpoints.contains { $0 == nil }) else {
onActive = nil completionHandler(false)
completionHandler(false) return
}
guard let s = self else {
completionHandler(false)
return
}
s.dnsResolver = nil
assert(s.onActive == nil)
s.onActive = completionHandler
s.startObservingTunnelStatus()
let session = (s.tunnelProvider.connection as! NETunnelProviderSession)
do {
try session.startTunnel(options: [:]) // TODO: Provide options
} catch (let error) {
os_log("Failed to activate tunnel: %{public}@", log: OSLog.default, type: .debug, "\(error)")
s.onActive = nil
completionHandler(false)
}
} }
} }