@@ -536,6 +536,10 @@ pub(crate) mod sockopt {
536536 use crate :: net:: AddressFamily ;
537537 use crate :: net:: { Ipv4Addr , Ipv6Addr , SocketType } ;
538538 use crate :: utils:: as_mut_ptr;
539+ #[ cfg( apple) ]
540+ use c:: TCP_KEEPALIVE as TCP_KEEPIDLE ;
541+ #[ cfg( not( any( apple, target_os = "openbsd" , target_os = "haiku" , target_os = "nto" ) ) ) ]
542+ use c:: TCP_KEEPIDLE ;
539543 use core:: time:: Duration ;
540544 #[ cfg( windows) ]
541545 use windows_sys:: Win32 :: Foundation :: BOOL ;
@@ -613,6 +617,11 @@ pub(crate) mod sockopt {
613617 )
614618 }
615619
620+ #[ inline]
621+ pub ( crate ) fn get_socket_reuseaddr ( fd : BorrowedFd < ' _ > ) -> io:: Result < bool > {
622+ getsockopt ( fd, c:: SOL_SOCKET as _ , c:: SO_REUSEADDR ) . map ( to_bool)
623+ }
624+
616625 #[ inline]
617626 pub ( crate ) fn set_socket_broadcast ( fd : BorrowedFd < ' _ > , broadcast : bool ) -> io:: Result < ( ) > {
618627 setsockopt (
@@ -635,11 +644,7 @@ pub(crate) mod sockopt {
635644 ) -> io:: Result < ( ) > {
636645 // Convert `linger` to seconds, rounding up.
637646 let l_linger = if let Some ( linger) = linger {
638- let mut l_linger = linger. as_secs ( ) ;
639- if linger. subsec_nanos ( ) != 0 {
640- l_linger = l_linger. checked_add ( 1 ) . ok_or ( io:: Errno :: INVAL ) ?;
641- }
642- l_linger. try_into ( ) . map_err ( |_e| io:: Errno :: INVAL ) ?
647+ duration_to_secs ( linger) ?
643648 } else {
644649 0
645650 } ;
@@ -847,6 +852,12 @@ pub(crate) mod sockopt {
847852 ) )
848853 }
849854
855+ #[ inline]
856+ #[ cfg( not( apple) ) ] // Apple platforms declare the constant, but do not actually implement it.
857+ pub ( crate ) fn get_socket_acceptconn ( fd : BorrowedFd < ' _ > ) -> io:: Result < bool > {
858+ getsockopt ( fd, c:: SOL_SOCKET as _ , c:: SO_ACCEPTCONN ) . map ( to_bool)
859+ }
860+
850861 #[ inline]
851862 pub ( crate ) fn set_ip_ttl ( fd : BorrowedFd < ' _ > , ttl : u32 ) -> io:: Result < ( ) > {
852863 setsockopt ( fd, c:: IPPROTO_IP as _ , c:: IP_TTL , ttl)
@@ -1029,6 +1040,46 @@ pub(crate) mod sockopt {
10291040 getsockopt ( fd, c:: IPPROTO_TCP as _ , c:: TCP_NODELAY ) . map ( to_bool)
10301041 }
10311042
1043+ #[ inline]
1044+ #[ cfg( not( any( target_os = "openbsd" , target_os = "haiku" , target_os = "nto" ) ) ) ]
1045+ pub ( crate ) fn set_tcp_keepcnt ( fd : BorrowedFd < ' _ > , count : u32 ) -> io:: Result < ( ) > {
1046+ setsockopt ( fd, c:: IPPROTO_TCP as _ , c:: TCP_KEEPCNT , count)
1047+ }
1048+
1049+ #[ inline]
1050+ #[ cfg( not( any( target_os = "openbsd" , target_os = "haiku" , target_os = "nto" ) ) ) ]
1051+ pub ( crate ) fn get_tcp_keepcnt ( fd : BorrowedFd < ' _ > ) -> io:: Result < u32 > {
1052+ getsockopt ( fd, c:: IPPROTO_TCP as _ , c:: TCP_KEEPCNT )
1053+ }
1054+
1055+ #[ inline]
1056+ #[ cfg( not( any( target_os = "openbsd" , target_os = "haiku" , target_os = "nto" ) ) ) ]
1057+ pub ( crate ) fn set_tcp_keepidle ( fd : BorrowedFd < ' _ > , duration : Duration ) -> io:: Result < ( ) > {
1058+ let secs: c:: c_uint = duration_to_secs ( duration) ?;
1059+ setsockopt ( fd, c:: IPPROTO_TCP as _ , TCP_KEEPIDLE , secs)
1060+ }
1061+
1062+ #[ inline]
1063+ #[ cfg( not( any( target_os = "openbsd" , target_os = "haiku" , target_os = "nto" ) ) ) ]
1064+ pub ( crate ) fn get_tcp_keepidle ( fd : BorrowedFd < ' _ > ) -> io:: Result < Duration > {
1065+ let secs: c:: c_uint = getsockopt ( fd, c:: IPPROTO_TCP as _ , TCP_KEEPIDLE ) ?;
1066+ Ok ( Duration :: from_secs ( secs as u64 ) )
1067+ }
1068+
1069+ #[ inline]
1070+ #[ cfg( not( any( target_os = "openbsd" , target_os = "haiku" , target_os = "nto" ) ) ) ]
1071+ pub ( crate ) fn set_tcp_keepintvl ( fd : BorrowedFd < ' _ > , duration : Duration ) -> io:: Result < ( ) > {
1072+ let secs: c:: c_uint = duration_to_secs ( duration) ?;
1073+ setsockopt ( fd, c:: IPPROTO_TCP as _ , c:: TCP_KEEPINTVL , secs)
1074+ }
1075+
1076+ #[ inline]
1077+ #[ cfg( not( any( target_os = "openbsd" , target_os = "haiku" , target_os = "nto" ) ) ) ]
1078+ pub ( crate ) fn get_tcp_keepintvl ( fd : BorrowedFd < ' _ > ) -> io:: Result < Duration > {
1079+ let secs: c:: c_uint = getsockopt ( fd, c:: IPPROTO_TCP as _ , c:: TCP_KEEPINTVL ) ?;
1080+ Ok ( Duration :: from_secs ( secs as u64 ) )
1081+ }
1082+
10321083 #[ inline]
10331084 fn to_imr ( multiaddr : & Ipv4Addr , interface : & Ipv4Addr ) -> c:: ip_mreq {
10341085 c:: ip_mreq {
@@ -1089,4 +1140,14 @@ pub(crate) mod sockopt {
10891140 fn to_bool ( value : SocketBool ) -> bool {
10901141 value. 0 != 0
10911142 }
1143+
1144+ /// Convert to seconds, rounding up if necessary.
1145+ #[ inline]
1146+ fn duration_to_secs < T : TryFrom < u64 > > ( duration : Duration ) -> io:: Result < T > {
1147+ let mut secs = duration. as_secs ( ) ;
1148+ if duration. subsec_nanos ( ) != 0 {
1149+ secs = secs. checked_add ( 1 ) . ok_or ( io:: Errno :: INVAL ) ?;
1150+ }
1151+ T :: try_from ( secs) . map_err ( |_e| io:: Errno :: INVAL )
1152+ }
10921153}
0 commit comments