Skip to content

Commit 76155b6

Browse files
committed
Foundation: port NSHost to Windows
This ports the NSHost functionality to Windows.
1 parent 1375de0 commit 76155b6

File tree

1 file changed

+105
-3
lines changed

1 file changed

+105
-3
lines changed

Foundation/Host.swift

+105-3
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,19 @@ open class Host: NSObject {
3333
}
3434

3535
static internal func currentHostName() -> String {
36+
#if os(Windows)
37+
var dwLength: DWORD = 0
38+
GetComputerNameExA(ComputerNameDnsHostname, nil, &dwLength)
39+
guard dwLength > 0 else { return "localhost" }
40+
41+
let hostname: UnsafeMutablePointer<Int8> =
42+
UnsafeMutableBufferPointer<Int8>.allocate(capacity: Int(dwLength + 1)).baseAddress
43+
defer { hostname.deallocate() }
44+
guard GetComputerNameExA(ComputerNameDnsHostname, hostname, &dwLength) else {
45+
return "localhost"
46+
}
47+
return String(cString: hostname)
48+
#else
3649
let hname = UnsafeMutablePointer<Int8>.allocate(capacity: Int(NI_MAXHOST))
3750
defer {
3851
hname.deallocate()
@@ -42,6 +55,7 @@ open class Host: NSObject {
4255
return "localhost"
4356
}
4457
return String(cString: hname)
58+
#endif
4559
}
4660

4761
open class func current() -> Host {
@@ -63,6 +77,39 @@ open class Host: NSObject {
6377
internal func _resolveCurrent() {
6478
#if os(Android)
6579
return
80+
#elseif os(Windows)
81+
var ulResult: ULONG = 0
82+
83+
var ulSize: ULONG = 0
84+
var arAdapterInfo: UnsafeMutablePointer<IP_ADAPTER_ADDRESSES>?
85+
86+
var buffer: UnsafeMutablePointer<Int8> =
87+
UnsafeMutablePointer<Int8>.allocate(capacity: Int(NI_MAXHOST))
88+
defer { buffer.deallocate() }
89+
90+
ulResult = GetAdapterAddresses(AF_UNSPEC, 0, nil, nil, &ulSize)
91+
arAdapterInfo = UnsafeMutablePointer<IP_ADAPTER_ADDRESSES>
92+
.allocate(capacity: ulSize / MemoryLayout<IP_ADAPTER_ADDRESSES>.size)
93+
defer { arAdapterInfo.deallocate() }
94+
95+
ulResult = GetAdapterAddresses(AF_UNSPEC, 0, nil, &arAdapterInfo, &ulSize)
96+
while arAdapterInfo != nil {
97+
var address = arAdapterInfo.FirstUnicastAddress
98+
while address != nil {
99+
switch address.lpSockaddr.sa_family {
100+
case AF_INET, AF_INET6:
101+
if GetNameInfoW(address.lpSockaddr, address.iSockaddrLength,
102+
buffer, socklen_t(NI_MAXHOST), nil, 0,
103+
NI_NUMERICHOST) == 0 {
104+
_addresses.append(String(cString: buffer))
105+
}
106+
default: break
107+
}
108+
address = address.Next
109+
}
110+
arAdapterInfo = arAdapterInfo.Next
111+
}
112+
_resolved = true
66113
#else
67114
var ifaddr: UnsafeMutablePointer<ifaddrs>? = nil
68115
if getifaddrs(&ifaddr) != 0 {
@@ -91,12 +138,67 @@ open class Host: NSObject {
91138
}
92139

93140
internal func _resolve() {
141+
guard _resolved == false else { return }
94142
#if os(Android)
95143
return
96-
#else
97-
if _resolved {
98-
return
144+
#elseif os(Windows)
145+
if let info = _info {
146+
if _type == .current { return _resolveCurrent() }
147+
148+
var hints: ADDRINFOW = ADDRINFOW()
149+
ZeroMemory(&hints, MemoryLayout<ADDRINFOW>.size)
150+
151+
switch (_type) {
152+
case .name:
153+
hints.ai_flags = AI_PASSIVE | AI_CANONNAME
154+
case .address:
155+
hints.ai_flags = AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST
156+
case .current:
157+
break
158+
}
159+
hints.ai_family = AF_UNSPEC
160+
hints.ai_socktype = SOCK_STREAM
161+
hints.ai_protocol = IPPROTO_TCP
162+
163+
var aiResult: UnsafeMutablePointer<ADDRINFOW>?
164+
if GetAddrInfoW(info, nil, &hints, &aiResult) != 0 { return }
165+
defer { FreeAddrInfoW(aiResult) }
166+
167+
let szHostName =
168+
UnsafeMutablePointer<Int8>.allocate(capacity: Int(NI_MAXHOST))
169+
defer { szHostName.deallocate() }
170+
171+
while aiResult != nil {
172+
let aiInfo: ADDRINFOW = aiResult.pointee
173+
let sa_len: socklen_t = 0
174+
175+
switch aiInfo.ai_family {
176+
case AF_INET:
177+
sa_len = MemoryLayout<sockaddr_in>.size
178+
case AF_INET6:
179+
sa_len = MemoryLayout<sockaddr_in6>.size
180+
default:
181+
result = aiInfo.ai_next
182+
continue
183+
}
184+
185+
let lookup = { (content: inout [String], flags: Int32) in
186+
if GetNameInfoW(aiInfo.ai_addr, sa_len, szHostName,
187+
socklen_t(NI_MAXHOST), nil, 0, flags) == 0 {
188+
content.append(String(cString: szHostName))
189+
}
190+
}
191+
192+
lookup(&_addresses, NI_NUMERICHOST)
193+
lookup(&_names, NI_NAMEREQD)
194+
lookup(&_names, NI_NOFQDN | NI_NAMEREQD)
195+
196+
aiResult = aiInfo.ai_next
197+
}
198+
199+
_resolved = true
99200
}
201+
#else
100202
if let info = _info {
101203
var flags: Int32 = 0
102204
switch (_type) {

0 commit comments

Comments
 (0)