20
20
21
21
import CNIOLinux
22
22
23
+ #if os(Windows)
24
+ import let WinSDK. AF_INET
25
+ import let WinSDK. AF_INET6
26
+
27
+ import let WinSDK. INET_ADDRSTRLEN
28
+ import let WinSDK. INET6_ADDRSTRLEN
29
+
30
+ import struct WinSDK. ADDRESS_FAMILY
31
+ import struct WinSDK. IP_ADAPTER_ADDRESSES
32
+ import struct WinSDK. IP_ADAPTER_UNICAST_ADDRESS
33
+
34
+ import typealias WinSDK. UINT8
35
+ #endif
36
+
37
+ #if !os(Windows)
23
38
private extension ifaddrs {
24
39
var dstaddr : UnsafeMutablePointer < sockaddr > ? {
25
40
#if os(Linux)
@@ -37,6 +52,7 @@ private extension ifaddrs {
37
52
#endif
38
53
}
39
54
}
55
+ #endif
40
56
41
57
/// A representation of a single network device on a system.
42
58
public struct NIONetworkDevice {
@@ -127,14 +143,25 @@ public struct NIONetworkDevice {
127
143
/// This constructor will fail if NIO does not understand the format of the underlying
128
144
/// socket address family. This is quite common: for example, Linux will return AF_PACKET
129
145
/// addressed interfaces on most platforms, which NIO does not currently understand.
146
+ #if os(Windows)
147
+ internal init ? ( _ pAdapter: UnsafeMutablePointer < IP_ADAPTER_ADDRESSES > ,
148
+ _ pAddress: UnsafeMutablePointer < IP_ADAPTER_UNICAST_ADDRESS > ) {
149
+ guard let backing = Backing ( pAdapter, pAddress) else {
150
+ return nil
151
+ }
152
+ self . backing = backing
153
+ }
154
+ #else
130
155
internal init ? ( _ caddr: ifaddrs ) {
131
156
guard let backing = Backing ( caddr) else {
132
157
return nil
133
158
}
134
159
135
160
self . backing = backing
136
161
}
162
+ #endif
137
163
164
+ #if !os(Windows)
138
165
/// Convert a `NIONetworkInterface` to a `NIONetworkDevice`. As `NIONetworkDevice`s are a superset of `NIONetworkInterface`s,
139
166
/// it is always possible to perform this conversion.
140
167
@available ( * , deprecated, message: " This is a compatibility helper, and will be removed in a future release " )
@@ -149,6 +176,7 @@ public struct NIONetworkDevice {
149
176
interfaceIndex: interface. interfaceIndex
150
177
)
151
178
}
179
+ #endif
152
180
153
181
public init ( name: String ,
154
182
address: SocketAddress ? ,
@@ -206,6 +234,58 @@ extension NIONetworkDevice {
206
234
/// This constructor will fail if NIO does not understand the format of the underlying
207
235
/// socket address family. This is quite common: for example, Linux will return AF_PACKET
208
236
/// addressed interfaces on most platforms, which NIO does not currently understand.
237
+ #if os(Windows)
238
+ internal init ? ( _ pAdapter: UnsafeMutablePointer < IP_ADAPTER_ADDRESSES > ,
239
+ _ pAddress: UnsafeMutablePointer < IP_ADAPTER_UNICAST_ADDRESS > ) {
240
+ self . name = String ( decodingCString: pAdapter. pointee. FriendlyName,
241
+ as: UTF16 . self)
242
+ self . address = pAddress. pointee. Address. lpSockaddr. convert ( )
243
+
244
+ // TODO: convert the prefix length to the mask itself
245
+ let v4mask : ( UINT8 ) -> SocketAddress ? = { _ in
246
+ var buffer : [ CChar ] =
247
+ Array < CChar > ( repeating: 0 , count: Int ( INET_ADDRSTRLEN) )
248
+ var mask : sockaddr_in = sockaddr_in ( )
249
+ mask. sin_family = ADDRESS_FAMILY ( AF_INET)
250
+ _ = buffer. withUnsafeMutableBufferPointer {
251
+ try ! NIOBSDSocket . inet_ntop ( af: . inet, src: & mask,
252
+ dst: $0. baseAddress!,
253
+ size: INET_ADDRSTRLEN)
254
+ }
255
+ return SocketAddress ( mask, host: mask. addressDescription ( ) )
256
+ }
257
+ let v6mask : ( UINT8 ) -> SocketAddress ? = { _ in
258
+ var buffer : [ CChar ] =
259
+ Array < CChar > ( repeating: 0 , count: Int ( INET6_ADDRSTRLEN) )
260
+ var mask : sockaddr_in6 = sockaddr_in6 ( )
261
+ mask. sin6_family = ADDRESS_FAMILY ( AF_INET6)
262
+ _ = buffer. withUnsafeMutableBufferPointer {
263
+ try ! NIOBSDSocket . inet_ntop ( af: . inet6, src: & mask,
264
+ dst: $0. baseAddress!,
265
+ size: INET6_ADDRSTRLEN)
266
+ }
267
+ return SocketAddress ( mask, host: mask. addressDescription ( ) )
268
+ }
269
+
270
+ switch pAddress. pointee. Address. lpSockaddr. pointee. sa_family {
271
+ case ADDRESS_FAMILY ( AF_INET) :
272
+ self . netmask = v4mask ( pAddress. pointee. OnLinkPrefixLength)
273
+ self . interfaceIndex = Int ( pAdapter. pointee. IfIndex)
274
+ break
275
+ case ADDRESS_FAMILY ( AF_INET6) :
276
+ self . netmask = v6mask ( pAddress. pointee. OnLinkPrefixLength)
277
+ self . interfaceIndex = Int ( pAdapter. pointee. Ipv6IfIndex)
278
+ break
279
+ default :
280
+ return nil
281
+ }
282
+
283
+ // TODO(compnerd) handle broadcast/ppp/multicast information
284
+ self . broadcastAddress = nil
285
+ self . pointToPointDestinationAddress = nil
286
+ self . multicastSupported = false
287
+ }
288
+ #else
209
289
internal init ? ( _ caddr: ifaddrs ) {
210
290
self . name = String ( cString: caddr. ifa_name)
211
291
self . address = caddr. ifa_addr. flatMap { $0. convert ( ) }
@@ -229,6 +309,7 @@ extension NIONetworkDevice {
229
309
return nil
230
310
}
231
311
}
312
+ #endif
232
313
233
314
init ( copying original: Backing ) {
234
315
self . name = original. name
@@ -325,6 +406,60 @@ public final class NIONetworkInterface {
325
406
/// This constructor will fail if NIO does not understand the format of the underlying
326
407
/// socket address family. This is quite common: for example, Linux will return AF_PACKET
327
408
/// addressed interfaces on most platforms, which NIO does not currently understand.
409
+ #if os(Windows)
410
+ internal init ? ( _ pAdapter: UnsafeMutablePointer < IP_ADAPTER_ADDRESSES > ,
411
+ _ pAddress: UnsafeMutablePointer < IP_ADAPTER_UNICAST_ADDRESS > ) {
412
+ self . name = String ( decodingCString: pAdapter. pointee. FriendlyName,
413
+ as: UTF16 . self)
414
+
415
+ guard let address = pAddress. pointee. Address. lpSockaddr. convert ( ) else {
416
+ return nil
417
+ }
418
+ self . address = address
419
+
420
+ // TODO: convert the prefix length to the mask itself
421
+ let v4mask : ( UINT8 ) -> SocketAddress ? = { _ in
422
+ var buffer : [ CChar ] =
423
+ Array < CChar > ( repeating: 0 , count: Int ( INET_ADDRSTRLEN) )
424
+ var mask : sockaddr_in = sockaddr_in ( )
425
+ mask. sin_family = ADDRESS_FAMILY ( AF_INET)
426
+ _ = buffer. withUnsafeMutableBufferPointer {
427
+ try ! NIOBSDSocket . inet_ntop ( af: . inet, src: & mask,
428
+ dst: $0. baseAddress!,
429
+ size: INET_ADDRSTRLEN)
430
+ }
431
+ return SocketAddress ( mask, host: mask. addressDescription ( ) )
432
+ }
433
+ let v6mask : ( UINT8 ) -> SocketAddress ? = { _ in
434
+ var buffer : [ CChar ] =
435
+ Array < CChar > ( repeating: 0 , count: Int ( INET6_ADDRSTRLEN) )
436
+ var mask : sockaddr_in6 = sockaddr_in6 ( )
437
+ mask. sin6_family = ADDRESS_FAMILY ( AF_INET6)
438
+ _ = buffer. withUnsafeMutableBufferPointer {
439
+ try ! NIOBSDSocket . inet_ntop ( af: . inet6, src: & mask,
440
+ dst: $0. baseAddress!,
441
+ size: INET6_ADDRSTRLEN)
442
+ }
443
+ return SocketAddress ( mask, host: mask. addressDescription ( ) )
444
+ }
445
+
446
+ switch pAddress. pointee. Address. lpSockaddr. pointee. sa_family {
447
+ case ADDRESS_FAMILY ( AF_INET) :
448
+ self . netmask = v4mask ( pAddress. pointee. OnLinkPrefixLength)
449
+ self . interfaceIndex = Int ( pAdapter. pointee. IfIndex)
450
+ case ADDRESS_FAMILY ( AF_INET6) :
451
+ self . netmask = v6mask ( pAddress. pointee. OnLinkPrefixLength)
452
+ self . interfaceIndex = Int ( pAdapter. pointee. Ipv6IfIndex)
453
+ default :
454
+ return nil
455
+ }
456
+
457
+ // TODO(compnerd) handle broadcast/ppp/multicast information
458
+ self . broadcastAddress = nil
459
+ self . pointToPointDestinationAddress = nil
460
+ self . multicastSupported = false
461
+ }
462
+ #else
328
463
internal init ? ( _ caddr: ifaddrs ) {
329
464
self . name = String ( cString: caddr. ifa_name)
330
465
guard let address = caddr. ifa_addr!. convert ( ) else {
@@ -361,6 +496,7 @@ public final class NIONetworkInterface {
361
496
return nil
362
497
}
363
498
}
499
+ #endif
364
500
}
365
501
366
502
@available ( * , deprecated, renamed: " NIONetworkDevice " )
0 commit comments