@@ -5,6 +5,14 @@ use sys::time::TimeVal;
5
5
use libc:: { self , c_int, uint8_t, c_void, socklen_t} ;
6
6
use std:: mem;
7
7
use std:: os:: unix:: io:: RawFd ;
8
+ use std:: ffi:: { OsStr , OsString } ;
9
+ #[ cfg( target_family = "unix" ) ]
10
+ use std:: os:: unix:: ffi:: OsStrExt ;
11
+
12
+ // Constants
13
+ // TCP_CA_NAME_MAX isn't defined in user space include files
14
+ #[ cfg( any( target_os = "freebsd" , target_os = "linux" ) ) ]
15
+ const TCP_CA_NAME_MAX : usize = 16 ;
8
16
9
17
/// Helper for implementing `SetSockOpt` for a given socket option. See
10
18
/// [`::sys::socket::SetSockOpt`](sys/socket/trait.SetSockOpt.html).
@@ -152,6 +160,10 @@ macro_rules! sockopt_impl {
152
160
sockopt_impl!( Both , $name, $level, $flag, usize , GetUsize , SetUsize ) ;
153
161
} ;
154
162
163
+ ( Both , $name: ident, $level: path, $flag: path, OsString <$array: ty>) => {
164
+ sockopt_impl!( Both , $name, $level, $flag, OsString , GetOsString <$array>, SetOsString ) ;
165
+ } ;
166
+
155
167
/*
156
168
* Matchers with generic getter types must be placed at the end, so
157
169
* they'll only match _after_ specialized matchers fail
@@ -257,6 +269,8 @@ sockopt_impl!(Both, BindAny, libc::IPPROTO_IP, libc::IP_BINDANY, bool);
257
269
sockopt_impl ! ( Both , Mark , libc:: SOL_SOCKET , libc:: SO_MARK , u32 ) ;
258
270
#[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
259
271
sockopt_impl ! ( Both , PassCred , libc:: SOL_SOCKET , libc:: SO_PASSCRED , bool ) ;
272
+ #[ cfg( any( target_os = "freebsd" , target_os = "linux" ) ) ]
273
+ sockopt_impl ! ( Both , TcpCongestion , libc:: IPPROTO_TCP , libc:: TCP_CONGESTION , OsString <[ u8 ; TCP_CA_NAME_MAX ] >) ;
260
274
261
275
/*
262
276
*
@@ -478,6 +492,53 @@ unsafe impl<'a> Set<'a, usize> for SetUsize {
478
492
}
479
493
}
480
494
495
+ /// Getter for a `OsString` value.
496
+ struct GetOsString < T : AsMut < [ u8 ] > > {
497
+ len : socklen_t ,
498
+ val : T ,
499
+ }
500
+
501
+ unsafe impl < T : AsMut < [ u8 ] > > Get < OsString > for GetOsString < T > {
502
+ unsafe fn blank ( ) -> Self {
503
+ GetOsString {
504
+ len : mem:: size_of :: < T > ( ) as socklen_t ,
505
+ val : mem:: zeroed ( ) ,
506
+ }
507
+ }
508
+
509
+ fn ffi_ptr ( & mut self ) -> * mut c_void {
510
+ & mut self . val as * mut T as * mut c_void
511
+ }
512
+
513
+ fn ffi_len ( & mut self ) -> * mut socklen_t {
514
+ & mut self . len
515
+ }
516
+
517
+ unsafe fn unwrap ( mut self ) -> OsString {
518
+ OsStr :: from_bytes ( self . val . as_mut ( ) ) . to_owned ( )
519
+ }
520
+ }
521
+
522
+ /// Setter for a `OsString` value.
523
+ struct SetOsString < ' a > {
524
+ val : & ' a OsStr ,
525
+ }
526
+
527
+ unsafe impl < ' a > Set < ' a , OsString > for SetOsString < ' a > {
528
+ fn new ( val : & ' a OsString ) -> SetOsString {
529
+ SetOsString { val : val. as_os_str ( ) }
530
+ }
531
+
532
+ fn ffi_ptr ( & self ) -> * const c_void {
533
+ self . val . as_bytes ( ) . as_ptr ( ) as * const c_void
534
+ }
535
+
536
+ fn ffi_len ( & self ) -> socklen_t {
537
+ self . val . len ( ) as socklen_t
538
+ }
539
+ }
540
+
541
+
481
542
#[ cfg( test) ]
482
543
mod test {
483
544
#[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
0 commit comments