VPN: DNSResolver: Resolve multiple endpoints in parallel

This commit is contained in:
Roopesh Chander 2018-10-28 15:34:07 +05:30
parent 2c94dd4694
commit 8df53b7709
1 changed files with 32 additions and 21 deletions

View File

@ -6,40 +6,51 @@ import Foundation
class DNSResolver { class DNSResolver {
let endpoints: [Endpoint?] let endpoints: [Endpoint?]
let dispatchGroup: DispatchGroup
var dispatchWorkItems: [DispatchWorkItem]
init(endpoints: [Endpoint?]) { init(endpoints: [Endpoint?]) {
self.endpoints = endpoints self.endpoints = endpoints
self.dispatchWorkItems = []
self.dispatchGroup = DispatchGroup()
} }
func resolve(completionHandler: @escaping ([Endpoint?]?) -> Void) { func resolve(completionHandler: @escaping ([Endpoint?]?) -> Void) {
let endpoints = self.endpoints let endpoints = self.endpoints
DispatchQueue.global(qos: .userInitiated).async { let dispatchGroup = self.dispatchGroup
var resolvedEndpoints: [Endpoint?] = [] dispatchWorkItems = []
var isError = false var resolvedEndpoints: [Endpoint?] = Array<Endpoint?>(repeating: nil, count: endpoints.count)
for endpoint in endpoints { let numberOfEndpointsToResolve = endpoints.compactMap { $0 }.count
if let endpoint = endpoint { for (i, endpoint) in self.endpoints.enumerated() {
if let resolvedEndpoint = DNSResolver.resolveSync(endpoint: endpoint) { guard let endpoint = endpoint else { return }
resolvedEndpoints.append(resolvedEndpoint) let workItem = DispatchWorkItem {
} else { resolvedEndpoints[i] = DNSResolver.resolveSync(endpoint: endpoint)
isError = true
break
}
} else {
resolvedEndpoints.append(nil)
}
} }
if (isError) { dispatchWorkItems.append(workItem)
DispatchQueue.main.async { DispatchQueue.global(qos: .userInitiated).async(group: dispatchGroup, execute: workItem)
completionHandler(nil) }
} dispatchGroup.notify(queue: .main) {
return let numberOfResolvedEndpoints = resolvedEndpoints.compactMap { $0 }.count
} if (numberOfResolvedEndpoints < numberOfEndpointsToResolve) {
DispatchQueue.main.async { completionHandler(nil)
} else {
completionHandler(resolvedEndpoints) completionHandler(resolvedEndpoints)
} }
} }
} }
func cancel() {
for workItem in dispatchWorkItems {
workItem.cancel()
}
}
deinit {
cancel()
}
}
extension DNSResolver {
// Based on DNS resolution code by Jason Donenfeld <jason@zx2c4.com> // Based on DNS resolution code by Jason Donenfeld <jason@zx2c4.com>
// in parse_endpoint() in src/tools/config.c in the WireGuard codebase // in parse_endpoint() in src/tools/config.c in the WireGuard codebase
private static func resolveSync(endpoint: Endpoint) -> Endpoint? { private static func resolveSync(endpoint: Endpoint) -> Endpoint? {