8
8
*/
9
9
10
10
extension SocketDescriptor {
11
- @frozen
11
+ @frozen
12
12
public struct Option : RawRepresentable , Hashable {
13
13
@_alwaysEmitIntoClient
14
14
public var rawValue : CInt
@@ -317,129 +317,129 @@ extension SocketDescriptor {
317
317
/// A value of -1 resets to the default value.
318
318
///
319
319
/// The corresponding C constant is `IPV6_UNICAST_HOPS`.
320
- @_alwaysEmitIntoClient
321
- public static var ipv6UnicastHops : Option { Option ( _IPV6_UNICAST_HOPS) }
322
-
323
- /// The interface from which multicast packets will be sent.
324
- ///
325
- /// A value of 0 specifies the default interface.
326
- ///
327
- /// The corresponding C constant is `IPV6_MULTICAST_IF`.
328
- @_alwaysEmitIntoClient
329
- public static var ipv6MulticastInterface : Option { Option ( _IPV6_MULTICAST_IF) }
330
-
331
- /// The default hop limit header field for outgoing multicast datagrams.
332
- ///
333
- /// The corresponding C constant is `IPV6_MULTICAST_HOPS`.
334
- @_alwaysEmitIntoClient
335
- public static var ipv6MulticastHops : Option { Option ( _IPV6_MULTICAST_HOPS) }
336
-
337
- /// Whether multicast datagrams will be looped back.
338
- ///
339
- /// The corresponding C constant is `IPV6_MULTICAST_LOOP`.
340
- @_alwaysEmitIntoClient
341
- public static var ipv6MulticastLoop : Option { Option ( _IPV6_MULTICAST_LOOP) }
342
-
343
- /// Join a multicast group.
344
- ///
345
- /// The corresponding C constant is `IPV6_JOIN_GROUP`.
346
- @_alwaysEmitIntoClient
347
- public static var ipv6JoinGroup : Option { Option ( _IPV6_JOIN_GROUP) }
348
-
349
- /// Leave a multicast group.
350
- ///
351
- /// The corresponding C constant is `IPV6_LEAVE_GROUP`.
352
- @_alwaysEmitIntoClient
353
- public static var ipv6LeaveGroup : Option { Option ( _IPV6_LEAVE_GROUP) }
354
-
355
- /// Allocation policy of ephemeral ports for when the kernel automatically
356
- /// binds a local address to this socket.
357
- ///
358
- /// TODO: portrange struct somewhere, with _DEFAULT, _HIGH, _LOW
359
- ///
360
- /// The corresponding C constant is `IPV6_PORTRANGE`.
361
- @_alwaysEmitIntoClient
362
- public static var ipv6PortRange : Option { Option ( _IPV6_PORTRANGE) }
363
-
364
- // /// Whether additional information about subsequent packets will be
365
- // /// provided in `recvmsg` calls.
366
- // ///
367
- // /// The corresponding C constant is `IPV6_PKTINFO`.
368
- // @_alwaysEmitIntoClient
369
- // public static var ipv6ReceivePacketInfo: Option { Option(_IPV6_PKTINFO) }
320
+ @_alwaysEmitIntoClient
321
+ public static var ipv6UnicastHops : Option { Option ( _IPV6_UNICAST_HOPS) }
322
+
323
+ /// The interface from which multicast packets will be sent.
324
+ ///
325
+ /// A value of 0 specifies the default interface.
326
+ ///
327
+ /// The corresponding C constant is `IPV6_MULTICAST_IF`.
328
+ @_alwaysEmitIntoClient
329
+ public static var ipv6MulticastInterface : Option { Option ( _IPV6_MULTICAST_IF) }
330
+
331
+ /// The default hop limit header field for outgoing multicast datagrams.
332
+ ///
333
+ /// The corresponding C constant is `IPV6_MULTICAST_HOPS`.
334
+ @_alwaysEmitIntoClient
335
+ public static var ipv6MulticastHops : Option { Option ( _IPV6_MULTICAST_HOPS) }
336
+
337
+ /// Whether multicast datagrams will be looped back.
338
+ ///
339
+ /// The corresponding C constant is `IPV6_MULTICAST_LOOP`.
340
+ @_alwaysEmitIntoClient
341
+ public static var ipv6MulticastLoop : Option { Option ( _IPV6_MULTICAST_LOOP) }
342
+
343
+ /// Join a multicast group.
344
+ ///
345
+ /// The corresponding C constant is `IPV6_JOIN_GROUP`.
346
+ @_alwaysEmitIntoClient
347
+ public static var ipv6JoinGroup : Option { Option ( _IPV6_JOIN_GROUP) }
348
+
349
+ /// Leave a multicast group.
350
+ ///
351
+ /// The corresponding C constant is `IPV6_LEAVE_GROUP`.
352
+ @_alwaysEmitIntoClient
353
+ public static var ipv6LeaveGroup : Option { Option ( _IPV6_LEAVE_GROUP) }
354
+
355
+ /// Allocation policy of ephemeral ports for when the kernel automatically
356
+ /// binds a local address to this socket.
357
+ ///
358
+ /// TODO: portrange struct somewhere, with _DEFAULT, _HIGH, _LOW
359
+ ///
360
+ /// The corresponding C constant is `IPV6_PORTRANGE`.
361
+ @_alwaysEmitIntoClient
362
+ public static var ipv6PortRange : Option { Option ( _IPV6_PORTRANGE) }
363
+
364
+ // /// Whether additional information about subsequent packets will be
365
+ // /// provided in `recvmsg` calls.
366
+ // ///
367
+ // /// The corresponding C constant is `IPV6_PKTINFO`.
368
+ // @_alwaysEmitIntoClient
369
+ // public static var ipv6ReceivePacketInfo: Option { Option(_IPV6_PKTINFO) }
370
370
//
371
- // /// Whether the hop limit header field from subsequent packets will
372
- // /// be provided in `recvmsg` calls.
373
- // ///
374
- // /// The corresponding C constant is `IPV6_HOPLIMIT`.
375
- // @_alwaysEmitIntoClient
376
- // public static var ipv6ReceiveHopLimit: Option { Option(_IPV6_HOPLIMIT) }
371
+ // /// Whether the hop limit header field from subsequent packets will
372
+ // /// be provided in `recvmsg` calls.
373
+ // ///
374
+ // /// The corresponding C constant is `IPV6_HOPLIMIT`.
375
+ // @_alwaysEmitIntoClient
376
+ // public static var ipv6ReceiveHopLimit: Option { Option(_IPV6_HOPLIMIT) }
377
377
//
378
- // /// Whether hop-by-hop options from subsequent packets will
379
- // /// be provided in `recvmsg` calls.
380
- // ///
381
- // /// The corresponding C constant is `IPV6_HOPOPTS`.
382
- // @_alwaysEmitIntoClient
383
- // public static var ipv6ReceiveHopOptions: Option { Option(_IPV6_HOPOPTS) }
378
+ // /// Whether hop-by-hop options from subsequent packets will
379
+ // /// be provided in `recvmsg` calls.
380
+ // ///
381
+ // /// The corresponding C constant is `IPV6_HOPOPTS`.
382
+ // @_alwaysEmitIntoClient
383
+ // public static var ipv6ReceiveHopOptions: Option { Option(_IPV6_HOPOPTS) }
384
384
//
385
- // /// Whether destination options from subsequent packets will
386
- // /// be provided in `recvmsg` calls.
387
- // ///
388
- // /// The corresponding C constant is `IPV6_DSTOPTS`.
389
- // @_alwaysEmitIntoClient
390
- // public static var ipv6ReceiveDestinationOptions: Option { Option(_IPV6_DSTOPTS) }
391
-
392
- /// The value of the traffic class field for outgoing datagrams.
393
- ///
394
- /// The corresponding C constant is `IPV6_TCLASS`.
395
- @_alwaysEmitIntoClient
396
- public static var ipv6TrafficClass : Option { Option ( _IPV6_TCLASS) }
397
-
398
- /// Whether traffic class header field from subsequent packets will
399
- /// be provided in `recvmsg` calls.
400
- ///
401
- /// The corresponding C constant is `IPV6_RECVTCLASS`.
402
- @_alwaysEmitIntoClient
403
- public static var ipv6ReceiveTrafficClass : Option { Option ( _IPV6_RECVTCLASS) }
404
-
405
- // /// Whether the routing header from subsequent packets will
406
- // /// be provided in `recvmsg` calls.
407
- // ///
408
- // /// The corresponding C constant is `IPV6_RTHDR`.
409
- // @_alwaysEmitIntoClient
410
- // public static var ipv6ReceiveRoutingHeader: Option { Option(_IPV6_RTHDR) }
385
+ // /// Whether destination options from subsequent packets will
386
+ // /// be provided in `recvmsg` calls.
387
+ // ///
388
+ // /// The corresponding C constant is `IPV6_DSTOPTS`.
389
+ // @_alwaysEmitIntoClient
390
+ // public static var ipv6ReceiveDestinationOptions: Option { Option(_IPV6_DSTOPTS) }
391
+
392
+ /// The value of the traffic class field for outgoing datagrams.
393
+ ///
394
+ /// The corresponding C constant is `IPV6_TCLASS`.
395
+ @_alwaysEmitIntoClient
396
+ public static var ipv6TrafficClass : Option { Option ( _IPV6_TCLASS) }
397
+
398
+ /// Whether traffic class header field from subsequent packets will
399
+ /// be provided in `recvmsg` calls.
400
+ ///
401
+ /// The corresponding C constant is `IPV6_RECVTCLASS`.
402
+ @_alwaysEmitIntoClient
403
+ public static var ipv6ReceiveTrafficClass : Option { Option ( _IPV6_RECVTCLASS) }
404
+
405
+ // /// Whether the routing header from subsequent packets will
406
+ // /// be provided in `recvmsg` calls.
407
+ // ///
408
+ // /// The corresponding C constant is `IPV6_RTHDR`.
409
+ // @_alwaysEmitIntoClient
410
+ // public static var ipv6ReceiveRoutingHeader: Option { Option(_IPV6_RTHDR) }
411
411
//
412
- // /// Get or set all header options and extension headers at one time
413
- // /// on the last packet sent or received.
414
- // ///
415
- // /// The corresponding C constant is `IPV6_PKTOPTIONS`.
416
- // @_alwaysEmitIntoClient
417
- // public static var ipv6PacketOptions: Option { Option(_IPV6_PKTOPTIONS) }
418
-
419
- /// The byte offset into a packet where 16-bit checksum is located.
420
- ///
421
- /// The corresponding C constant is `IPV6_CHECKSUM`.
422
- @_alwaysEmitIntoClient
423
- public static var ipv6Checksum : Option { Option ( _IPV6_CHECKSUM) }
424
-
425
- /// Whether only IPv6 connections can be made to this socket.
426
- ///
427
- /// The corresponding C constant is `IPV6_V6ONLY`.
428
- @_alwaysEmitIntoClient
429
- public static var ipv6Only : Option { Option ( _IPV6_V6ONLY) }
430
-
431
- // /// Whether the minimal IPv6 maximum transmission unit (MTU) size
432
- // /// will be used to avoid fragmentation for subsequenet outgoing
433
- // /// datagrams.
434
- // ///
435
- // /// The corresponding C constant is `IPV6_USE_MIN_MTU`.
436
- // @_alwaysEmitIntoClient
437
- // public static var ipv6UseMinimalMTU: Option { Option(_IPV6_USE_MIN_MTU) }
412
+ // /// Get or set all header options and extension headers at one time
413
+ // /// on the last packet sent or received.
414
+ // ///
415
+ // /// The corresponding C constant is `IPV6_PKTOPTIONS`.
416
+ // @_alwaysEmitIntoClient
417
+ // public static var ipv6PacketOptions: Option { Option(_IPV6_PKTOPTIONS) }
418
+
419
+ /// The byte offset into a packet where 16-bit checksum is located.
420
+ ///
421
+ /// The corresponding C constant is `IPV6_CHECKSUM`.
422
+ @_alwaysEmitIntoClient
423
+ public static var ipv6Checksum : Option { Option ( _IPV6_CHECKSUM) }
424
+
425
+ /// Whether only IPv6 connections can be made to this socket.
426
+ ///
427
+ /// The corresponding C constant is `IPV6_V6ONLY`.
428
+ @_alwaysEmitIntoClient
429
+ public static var ipv6Only : Option { Option ( _IPV6_V6ONLY) }
430
+
431
+ // /// Whether the minimal IPv6 maximum transmission unit (MTU) size
432
+ // /// will be used to avoid fragmentation for subsequenet outgoing
433
+ // /// datagrams.
434
+ // ///
435
+ // /// The corresponding C constant is `IPV6_USE_MIN_MTU`.
436
+ // @_alwaysEmitIntoClient
437
+ // public static var ipv6UseMinimalMTU: Option { Option(_IPV6_USE_MIN_MTU) }
438
438
}
439
439
}
440
440
441
441
extension SocketDescriptor . Option {
442
- /// The level at which a socket option resides
442
+ /// The level at which a socket option resides
443
443
@frozen
444
444
public struct Level : RawRepresentable , Hashable {
445
445
@_alwaysEmitIntoClient
@@ -453,27 +453,87 @@ extension SocketDescriptor.Option {
453
453
454
454
/// Socket options that only apply to IP sockets.
455
455
///
456
- /// The corresponding C constant is `IPPROTO_IP`.
456
+ /// The corresponding C constant is `IPPROTO_IP`.
457
457
@_alwaysEmitIntoClient
458
458
public static var ip : Level { Level ( _IPPROTO_IP) }
459
459
460
460
/// Socket options that only apply to IPv6 sockets
461
461
///
462
- /// The corresponding C constant is `IPPROTO_IPV6`.
462
+ /// The corresponding C constant is `IPPROTO_IPV6`.
463
463
@_alwaysEmitIntoClient
464
464
public static var ipv6 : Level { Level ( _IPPROTO_IPV6) }
465
465
466
466
/// Socket options that only apply to TCP sockets
467
467
///
468
- /// The corresponding C constant is `IPPROTO_TCP`.
468
+ /// The corresponding C constant is `IPPROTO_TCP`.
469
469
@_alwaysEmitIntoClient
470
470
public static var tcp : Level { Level ( _IPPROTO_TCP) }
471
471
472
472
/// Socket options that apply to all sockets.
473
473
///
474
- /// The corresponding C constant is `SOL_SOCKET`.
474
+ /// The corresponding C constant is `SOL_SOCKET`.
475
475
@_alwaysEmitIntoClient
476
476
public static var socket : Level { Level ( _SOL_SOCKET) }
477
477
}
478
478
}
479
479
480
+ extension SocketDescriptor {
481
+ // TODO: Convenience/performance overloads for `Bool` and other concrete types
482
+
483
+ @_alwaysEmitIntoClient
484
+ public func getOption< T> (
485
+ _ level: Option . Level , _ option: Option
486
+ ) throws -> T {
487
+ try _getOption ( level, option) . get ( )
488
+ }
489
+
490
+ @usableFromInline
491
+ internal func _getOption< T> (
492
+ _ level: Option . Level , _ option: Option
493
+ ) -> Result < T , Errno > {
494
+ // We can't zero-initialize `T` directly, nor can we pass an uninitialized `T`
495
+ // to `withUnsafeMutableBytes(of:)`. Instead, we will allocate :-(
496
+ let rawBuf = UnsafeMutableRawBufferPointer . allocate (
497
+ byteCount: MemoryLayout< T> . stride,
498
+ alignment: MemoryLayout< T> . alignment)
499
+ rawBuf. initializeMemory ( as: UInt8 . self, repeating: 0 )
500
+ let resultPtr = rawBuf. baseAddress!. bindMemory ( to: T . self, capacity: 1 )
501
+ defer {
502
+ resultPtr. deinitialize ( count: 1 )
503
+ rawBuf. deallocate ( )
504
+ }
505
+
506
+ var length : _CSockLenT = 0
507
+
508
+ let success = system_getsockopt (
509
+ self . rawValue,
510
+ level. rawValue,
511
+ option. rawValue,
512
+ resultPtr, & length)
513
+
514
+ return nothingOrErrno ( success) . map { resultPtr. pointee }
515
+ }
516
+
517
+ @_alwaysEmitIntoClient
518
+ public func setOption< T> (
519
+ _ level: Option . Level , _ option: Option , to value: T
520
+ ) throws {
521
+ try _setOption ( level, option, to: value) . get ( )
522
+ }
523
+
524
+ @usableFromInline
525
+ internal func _setOption< T> (
526
+ _ level: Option . Level , _ option: Option , to value: T
527
+ ) -> Result < ( ) , Errno > {
528
+ let len = _CSockLenT ( MemoryLayout< T> . stride)
529
+ let success = withUnsafeBytes ( of: value) {
530
+ return system_setsockopt (
531
+ self . rawValue,
532
+ level. rawValue,
533
+ option. rawValue,
534
+ $0. baseAddress,
535
+ len)
536
+ }
537
+ return nothingOrErrno ( success)
538
+ }
539
+ }
0 commit comments