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
+ break
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
@@ -289,97 +370,99 @@ extension NIONetworkDevice: Hashable {
289
370
}
290
371
}
291
372
292
- /// A representation of a single network interface on a system.
293
- @available ( * , deprecated, renamed: " NIONetworkDevice " )
294
- public final class NIONetworkInterface {
295
- // This is a class because in almost all cases this will carry
296
- // four structs that are backed by classes, and so will incur 4
297
- // refcount operations each time it is copied.
373
+ #if !os(Windows)
374
+ /// A representation of a single network interface on a system.
375
+ @available ( * , deprecated, renamed: " NIONetworkDevice " )
376
+ public final class NIONetworkInterface {
377
+ // This is a class because in almost all cases this will carry
378
+ // four structs that are backed by classes, and so will incur 4
379
+ // refcount operations each time it is copied.
298
380
299
- /// The name of the network interface.
300
- public let name : String
381
+ /// The name of the network interface.
382
+ public let name : String
301
383
302
- /// The address associated with the given network interface.
303
- public let address : SocketAddress
384
+ /// The address associated with the given network interface.
385
+ public let address : SocketAddress
304
386
305
- /// The netmask associated with this address, if any.
306
- public let netmask : SocketAddress ?
387
+ /// The netmask associated with this address, if any.
388
+ public let netmask : SocketAddress ?
307
389
308
- /// The broadcast address associated with this socket interface, if it has one. Some
309
- /// interfaces do not, especially those that have a `pointToPointDestinationAddress`.
310
- public let broadcastAddress : SocketAddress ?
390
+ /// The broadcast address associated with this socket interface, if it has one. Some
391
+ /// interfaces do not, especially those that have a `pointToPointDestinationAddress`.
392
+ public let broadcastAddress : SocketAddress ?
311
393
312
- /// The address of the peer on a point-to-point interface, if this is one. Some
313
- /// interfaces do not have such an address: most of those have a `broadcastAddress`
314
- /// instead.
315
- public let pointToPointDestinationAddress : SocketAddress ?
394
+ /// The address of the peer on a point-to-point interface, if this is one. Some
395
+ /// interfaces do not have such an address: most of those have a `broadcastAddress`
396
+ /// instead.
397
+ public let pointToPointDestinationAddress : SocketAddress ?
316
398
317
- /// If the Interface supports Multicast
318
- public let multicastSupported : Bool
399
+ /// If the Interface supports Multicast
400
+ public let multicastSupported : Bool
319
401
320
- /// The index of the interface, as provided by `if_nametoindex`.
321
- public let interfaceIndex : Int
402
+ /// The index of the interface, as provided by `if_nametoindex`.
403
+ public let interfaceIndex : Int
322
404
323
- /// Create a brand new network interface.
324
- ///
325
- /// This constructor will fail if NIO does not understand the format of the underlying
326
- /// socket address family. This is quite common: for example, Linux will return AF_PACKET
327
- /// addressed interfaces on most platforms, which NIO does not currently understand.
328
- internal init ? ( _ caddr: ifaddrs ) {
329
- self . name = String ( cString: caddr. ifa_name)
330
- guard let address = caddr. ifa_addr!. convert ( ) else {
331
- return nil
332
- }
333
- self . address = address
405
+ /// Create a brand new network interface.
406
+ ///
407
+ /// This constructor will fail if NIO does not understand the format of the underlying
408
+ /// socket address family. This is quite common: for example, Linux will return AF_PACKET
409
+ /// addressed interfaces on most platforms, which NIO does not currently understand.
410
+ internal init ? ( _ caddr: ifaddrs ) {
411
+ self . name = String ( cString: caddr. ifa_name)
412
+ guard let address = caddr. ifa_addr!. convert ( ) else {
413
+ return nil
414
+ }
415
+ self . address = address
334
416
335
- if let netmask = caddr. ifa_netmask {
336
- self . netmask = netmask. convert ( )
337
- } else {
338
- self . netmask = nil
339
- }
417
+ if let netmask = caddr. ifa_netmask {
418
+ self . netmask = netmask. convert ( )
419
+ } else {
420
+ self . netmask = nil
421
+ }
340
422
341
- if ( caddr. ifa_flags & UInt32 ( IFF_BROADCAST) ) != 0 , let addr = caddr. broadaddr {
342
- self . broadcastAddress = addr. convert ( )
343
- self . pointToPointDestinationAddress = nil
344
- } else if ( caddr. ifa_flags & UInt32 ( IFF_POINTOPOINT) ) != 0 , let addr = caddr. dstaddr {
345
- self . broadcastAddress = nil
346
- self . pointToPointDestinationAddress = addr. convert ( )
347
- } else {
348
- self . broadcastAddress = nil
349
- self . pointToPointDestinationAddress = nil
350
- }
423
+ if ( caddr. ifa_flags & UInt32 ( IFF_BROADCAST) ) != 0 , let addr = caddr. broadaddr {
424
+ self . broadcastAddress = addr. convert ( )
425
+ self . pointToPointDestinationAddress = nil
426
+ } else if ( caddr. ifa_flags & UInt32 ( IFF_POINTOPOINT) ) != 0 , let addr = caddr. dstaddr {
427
+ self . broadcastAddress = nil
428
+ self . pointToPointDestinationAddress = addr. convert ( )
429
+ } else {
430
+ self . broadcastAddress = nil
431
+ self . pointToPointDestinationAddress = nil
432
+ }
351
433
352
- if ( caddr. ifa_flags & UInt32 ( IFF_MULTICAST) ) != 0 {
353
- self . multicastSupported = true
354
- } else {
355
- self . multicastSupported = false
356
- }
434
+ if ( caddr. ifa_flags & UInt32 ( IFF_MULTICAST) ) != 0 {
435
+ self . multicastSupported = true
436
+ } else {
437
+ self . multicastSupported = false
438
+ }
357
439
358
- do {
359
- self . interfaceIndex = Int ( try Posix . if_nametoindex ( caddr. ifa_name) )
360
- } catch {
361
- return nil
440
+ do {
441
+ self . interfaceIndex = Int ( try Posix . if_nametoindex ( caddr. ifa_name) )
442
+ } catch {
443
+ return nil
444
+ }
362
445
}
363
446
}
364
- }
365
447
366
- @available ( * , deprecated, renamed: " NIONetworkDevice " )
367
- extension NIONetworkInterface : CustomDebugStringConvertible {
368
- public var debugDescription : String {
369
- let baseString = " Interface \( self . name) : address \( self . address) "
370
- let maskString = self . netmask != nil ? " netmask \( self . netmask!) " : " "
371
- return baseString + maskString
448
+ @available ( * , deprecated, renamed: " NIONetworkDevice " )
449
+ extension NIONetworkInterface : CustomDebugStringConvertible {
450
+ public var debugDescription : String {
451
+ let baseString = " Interface \( self . name) : address \( self . address) "
452
+ let maskString = self . netmask != nil ? " netmask \( self . netmask!) " : " "
453
+ return baseString + maskString
454
+ }
372
455
}
373
- }
374
456
375
- @available ( * , deprecated, renamed: " NIONetworkDevice " )
376
- extension NIONetworkInterface : Equatable {
377
- public static func == ( lhs: NIONetworkInterface , rhs: NIONetworkInterface ) -> Bool {
378
- return lhs. name == rhs. name &&
379
- lhs. address == rhs. address &&
380
- lhs. netmask == rhs. netmask &&
381
- lhs. broadcastAddress == rhs. broadcastAddress &&
382
- lhs. pointToPointDestinationAddress == rhs. pointToPointDestinationAddress &&
383
- lhs. interfaceIndex == rhs. interfaceIndex
457
+ @available ( * , deprecated, renamed: " NIONetworkDevice " )
458
+ extension NIONetworkInterface : Equatable {
459
+ public static func == ( lhs: NIONetworkInterface , rhs: NIONetworkInterface ) -> Bool {
460
+ return lhs. name == rhs. name &&
461
+ lhs. address == rhs. address &&
462
+ lhs. netmask == rhs. netmask &&
463
+ lhs. broadcastAddress == rhs. broadcastAddress &&
464
+ lhs. pointToPointDestinationAddress == rhs. pointToPointDestinationAddress &&
465
+ lhs. interfaceIndex == rhs. interfaceIndex
466
+ }
384
467
}
385
- }
468
+ #endif
0 commit comments