Skip to content

Foundation: port NSHost to Windows #1860

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 29, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 105 additions & 3 deletions Foundation/Host.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,19 @@ open class Host: NSObject {
}

static internal func currentHostName() -> String {
#if os(Windows)
var dwLength: DWORD = 0
GetComputerNameExA(ComputerNameDnsHostname, nil, &dwLength)
guard dwLength > 0 else { return "localhost" }

let hostname: UnsafeMutablePointer<Int8> =
UnsafeMutableBufferPointer<Int8>.allocate(capacity: Int(dwLength + 1)).baseAddress
defer { hostname.deallocate() }
guard GetComputerNameExA(ComputerNameDnsHostname, hostname, &dwLength) else {
return "localhost"
}
return String(cString: hostname)
#else
let hname = UnsafeMutablePointer<Int8>.allocate(capacity: Int(NI_MAXHOST))
defer {
hname.deallocate()
Expand All @@ -42,6 +55,7 @@ open class Host: NSObject {
return "localhost"
}
return String(cString: hname)
#endif
}

open class func current() -> Host {
Expand All @@ -63,6 +77,39 @@ open class Host: NSObject {
internal func _resolveCurrent() {
#if os(Android)
return
#elseif os(Windows)
var ulResult: ULONG = 0

var ulSize: ULONG = 0
var arAdapterInfo: UnsafeMutablePointer<IP_ADAPTER_ADDRESSES>?

var buffer: UnsafeMutablePointer<Int8> =
UnsafeMutablePointer<Int8>.allocate(capacity: Int(NI_MAXHOST))
defer { buffer.deallocate() }

ulResult = GetAdapterAddresses(AF_UNSPEC, 0, nil, nil, &ulSize)
arAdapterInfo = UnsafeMutablePointer<IP_ADAPTER_ADDRESSES>
.allocate(capacity: ulSize / MemoryLayout<IP_ADAPTER_ADDRESSES>.size)
defer { arAdapterInfo.deallocate() }

ulResult = GetAdapterAddresses(AF_UNSPEC, 0, nil, &arAdapterInfo, &ulSize)
while arAdapterInfo != nil {
var address = arAdapterInfo.FirstUnicastAddress
while address != nil {
switch address.lpSockaddr.sa_family {
case AF_INET, AF_INET6:
if GetNameInfoW(address.lpSockaddr, address.iSockaddrLength,
buffer, socklen_t(NI_MAXHOST), nil, 0,
NI_NUMERICHOST) == 0 {
_addresses.append(String(cString: buffer))
}
default: break
}
address = address.Next
}
arAdapterInfo = arAdapterInfo.Next
}
_resolved = true
#else
var ifaddr: UnsafeMutablePointer<ifaddrs>? = nil
if getifaddrs(&ifaddr) != 0 {
Expand Down Expand Up @@ -91,12 +138,67 @@ open class Host: NSObject {
}

internal func _resolve() {
guard _resolved == false else { return }
#if os(Android)
return
#else
if _resolved {
return
#elseif os(Windows)
if let info = _info {
if _type == .current { return _resolveCurrent() }

var hints: ADDRINFOW = ADDRINFOW()
ZeroMemory(&hints, MemoryLayout<ADDRINFOW>.size)

switch (_type) {
case .name:
hints.ai_flags = AI_PASSIVE | AI_CANONNAME
case .address:
hints.ai_flags = AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST
case .current:
break
}
hints.ai_family = AF_UNSPEC
hints.ai_socktype = SOCK_STREAM
hints.ai_protocol = IPPROTO_TCP

var aiResult: UnsafeMutablePointer<ADDRINFOW>?
if GetAddrInfoW(info, nil, &hints, &aiResult) != 0 { return }
defer { FreeAddrInfoW(aiResult) }

let szHostName =
UnsafeMutablePointer<Int8>.allocate(capacity: Int(NI_MAXHOST))
defer { szHostName.deallocate() }

while aiResult != nil {
let aiInfo: ADDRINFOW = aiResult.pointee
let sa_len: socklen_t = 0

switch aiInfo.ai_family {
case AF_INET:
sa_len = MemoryLayout<sockaddr_in>.size
case AF_INET6:
sa_len = MemoryLayout<sockaddr_in6>.size
default:
result = aiInfo.ai_next
continue
}

let lookup = { (content: inout [String], flags: Int32) in
if GetNameInfoW(aiInfo.ai_addr, sa_len, szHostName,
socklen_t(NI_MAXHOST), nil, 0, flags) == 0 {
content.append(String(cString: szHostName))
}
}

lookup(&_addresses, NI_NUMERICHOST)
lookup(&_names, NI_NAMEREQD)
lookup(&_names, NI_NOFQDN | NI_NAMEREQD)

aiResult = aiInfo.ai_next
}

_resolved = true
}
#else
if let info = _info {
var flags: Int32 = 0
switch (_type) {
Expand Down