Skip to content

Commit 5dd65ff

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

File tree

1 file changed

+102
-3
lines changed

1 file changed

+102
-3
lines changed

Foundation/Host.swift

Lines changed: 102 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,16 @@ 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+
40+
let hostname: UnsafeMutablePointer<Int8> =
41+
UnsafeMutableBufferPointer<Int8>.allocate(capacity: Int(dwLength + 1)).baseAddress
42+
defer { hostname.deallocate() }
43+
GetComputerNameExA(ComputerNameDnsHostname, hostname, &dwLength)
44+
return String(cString: hostname)
45+
#else
3646
let hname = UnsafeMutablePointer<Int8>.allocate(capacity: Int(NI_MAXHOST))
3747
defer {
3848
hname.deallocate()
@@ -42,6 +52,7 @@ open class Host: NSObject {
4252
return "localhost"
4353
}
4454
return String(cString: hname)
55+
#endif
4556
}
4657

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

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

0 commit comments

Comments
 (0)