NIO: implement address resolution on Windows (#1684)

Windows has a slightly different API for address resolution.  Implement
the Windows path for addrinfo resolution.
This commit is contained in:
Saleem Abdulrasool 2020-11-02 09:02:35 -08:00 committed by GitHub
parent 245ce96490
commit 255f29d3f3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 51 additions and 5 deletions

View File

@ -23,6 +23,21 @@
/// This resolver is a single-use object: it can only be used to perform a single host resolution.
import CNIOLinux
#if os(Windows)
import let WinSDK.AF_INET
import let WinSDK.AF_INET6
import func WinSDK.FreeAddrInfoW
import func WinSDK.GetAddrInfoW
import func WinSDK.gai_strerrorA
import struct WinSDK.ADDRESS_FAMILY
import struct WinSDK.ADDRINFOW
import struct WinSDK.SOCKADDR_IN
import struct WinSDK.SOCKADDR_IN6
#endif
internal class GetaddrinfoResolver: Resolver {
private let v4Future: EventLoopPromise<[SocketAddress]>
private let v6Future: EventLoopPromise<[SocketAddress]>
@ -85,6 +100,30 @@ internal class GetaddrinfoResolver: Resolver {
/// - host: The hostname to do the DNS queries on.
/// - port: The port we'll be connecting to.
private func resolve(host: String, port: Int) {
#if os(Windows)
host.withCString(encodedAs: UTF16.self) { wszHost in
String(port).withCString(encodedAs: UTF16.self) { wszPort in
var pResult: UnsafeMutablePointer<ADDRINFOW>?
var aiHints: ADDRINFOW = ADDRINFOW()
aiHints.ai_socktype = self.aiSocktype.rawValue
aiHints.ai_protocol = self.aiProtocol
let iResult = GetAddrInfoW(wszHost, wszPort, &aiHints, &pResult)
guard iResult == 0 else {
self.fail(SocketAddressError.unknown(host: host, port: port))
return
}
if let pResult = pResult {
parseResults(pResult, host: host)
FreeAddrInfoW(pResult)
} else {
self.fail(SocketAddressError.unsupported)
}
}
}
#else
var info: UnsafeMutablePointer<addrinfo>?
var hint = addrinfo()
@ -102,6 +141,7 @@ internal class GetaddrinfoResolver: Resolver {
/* this is odd, getaddrinfo returned NULL */
self.fail(SocketAddressError.unsupported)
}
#endif
}
/// Parses the DNS results from the `addrinfo` linked list.
@ -109,11 +149,17 @@ internal class GetaddrinfoResolver: Resolver {
/// - parameters:
/// - info: The pointer to the first of the `addrinfo` structures in the list.
/// - host: The hostname we resolved.
private func parseResults(_ info: UnsafeMutablePointer<addrinfo>, host: String) {
var info = info
var v4Results = [SocketAddress]()
var v6Results = [SocketAddress]()
#if os(Windows)
internal typealias CAddrInfo = ADDRINFOW
#else
internal typealias CAddrInfo = addrinfo
#endif
private func parseResults(_ info: UnsafeMutablePointer<CAddrInfo>, host: String) {
var v4Results: [SocketAddress] = []
var v6Results: [SocketAddress] = []
var info: UnsafeMutablePointer<CAddrInfo> = info
while true {
switch NIOBSDSocket.AddressFamily(rawValue: info.pointee.ai_family) {
case .inet:

View File

@ -339,7 +339,7 @@ public enum SocketAddress: CustomStringConvertible {
return try String(port).withCString(encodedAs: UTF16.self) { wszPort in
var pResult: UnsafeMutablePointer<ADDRINFOW>?
guard GetAddrInfoW(wsHost, wszPort, nil, &pResult) == 0 else {
guard GetAddrInfoW(wszHost, wszPort, nil, &pResult) == 0 else {
throw SocketAddressError.unknown(host: host, port: port)
}