Skip to content

Commit e8901d2

Browse files
committed
Foundation: port NSHost to Windows
This ports the NSHost functionality to Windows.
1 parent 3fcfcd6 commit e8901d2

File tree

1 file changed

+104
-3
lines changed

1 file changed

+104
-3
lines changed

Foundation/Host.swift

Lines changed: 104 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,18 @@ 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>
42+
.allocate(capacity: Int(dwLength + 1))
43+
.baseAddress
44+
defer { hostname?.deallocate() }
45+
GetComputerNameExA(ComputerNameDnsHostname, hostname, &dwLength)
46+
return String(cString: hostname!)
47+
#else
3648
let hname = UnsafeMutablePointer<Int8>.allocate(capacity: Int(NI_MAXHOST))
3749
defer {
3850
hname.deallocate()
@@ -42,6 +54,7 @@ open class Host: NSObject {
4254
return "localhost"
4355
}
4456
return String(cString: hname)
57+
#endif
4558
}
4659

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

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

0 commit comments

Comments
 (0)