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:
parent
245ce96490
commit
255f29d3f3
|
@ -23,6 +23,21 @@
|
||||||
/// This resolver is a single-use object: it can only be used to perform a single host resolution.
|
/// This resolver is a single-use object: it can only be used to perform a single host resolution.
|
||||||
import CNIOLinux
|
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 {
|
internal class GetaddrinfoResolver: Resolver {
|
||||||
private let v4Future: EventLoopPromise<[SocketAddress]>
|
private let v4Future: EventLoopPromise<[SocketAddress]>
|
||||||
private let v6Future: EventLoopPromise<[SocketAddress]>
|
private let v6Future: EventLoopPromise<[SocketAddress]>
|
||||||
|
@ -85,6 +100,30 @@ internal class GetaddrinfoResolver: Resolver {
|
||||||
/// - host: The hostname to do the DNS queries on.
|
/// - host: The hostname to do the DNS queries on.
|
||||||
/// - port: The port we'll be connecting to.
|
/// - port: The port we'll be connecting to.
|
||||||
private func resolve(host: String, port: Int) {
|
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 info: UnsafeMutablePointer<addrinfo>?
|
||||||
|
|
||||||
var hint = addrinfo()
|
var hint = addrinfo()
|
||||||
|
@ -102,6 +141,7 @@ internal class GetaddrinfoResolver: Resolver {
|
||||||
/* this is odd, getaddrinfo returned NULL */
|
/* this is odd, getaddrinfo returned NULL */
|
||||||
self.fail(SocketAddressError.unsupported)
|
self.fail(SocketAddressError.unsupported)
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses the DNS results from the `addrinfo` linked list.
|
/// Parses the DNS results from the `addrinfo` linked list.
|
||||||
|
@ -109,11 +149,17 @@ internal class GetaddrinfoResolver: Resolver {
|
||||||
/// - parameters:
|
/// - parameters:
|
||||||
/// - info: The pointer to the first of the `addrinfo` structures in the list.
|
/// - info: The pointer to the first of the `addrinfo` structures in the list.
|
||||||
/// - host: The hostname we resolved.
|
/// - host: The hostname we resolved.
|
||||||
private func parseResults(_ info: UnsafeMutablePointer<addrinfo>, host: String) {
|
#if os(Windows)
|
||||||
var info = info
|
internal typealias CAddrInfo = ADDRINFOW
|
||||||
var v4Results = [SocketAddress]()
|
#else
|
||||||
var v6Results = [SocketAddress]()
|
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 {
|
while true {
|
||||||
switch NIOBSDSocket.AddressFamily(rawValue: info.pointee.ai_family) {
|
switch NIOBSDSocket.AddressFamily(rawValue: info.pointee.ai_family) {
|
||||||
case .inet:
|
case .inet:
|
||||||
|
|
|
@ -339,7 +339,7 @@ public enum SocketAddress: CustomStringConvertible {
|
||||||
return try String(port).withCString(encodedAs: UTF16.self) { wszPort in
|
return try String(port).withCString(encodedAs: UTF16.self) { wszPort in
|
||||||
var pResult: UnsafeMutablePointer<ADDRINFOW>?
|
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)
|
throw SocketAddressError.unknown(host: host, port: port)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue