VPN: DNSResolver: Resolve multiple endpoints in parallel
Signed-off-by: Roopesh Chander <roop@roopc.net>
This commit is contained in:
parent
dfbdcf3c28
commit
493166bd70
|
@ -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 {
|
dispatchWorkItems.append(workItem)
|
||||||
resolvedEndpoints.append(nil)
|
DispatchQueue.global(qos: .userInitiated).async(group: dispatchGroup, execute: workItem)
|
||||||
}
|
}
|
||||||
}
|
dispatchGroup.notify(queue: .main) {
|
||||||
if (isError) {
|
let numberOfResolvedEndpoints = resolvedEndpoints.compactMap { $0 }.count
|
||||||
DispatchQueue.main.async {
|
if (numberOfResolvedEndpoints < numberOfEndpointsToResolve) {
|
||||||
completionHandler(nil)
|
completionHandler(nil)
|
||||||
}
|
} else {
|
||||||
return
|
|
||||||
}
|
|
||||||
DispatchQueue.main.async {
|
|
||||||
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? {
|
||||||
|
|
Loading…
Reference in New Issue