@@ -2009,12 +2009,145 @@ pub fn socketpair<T: Into<Option<SockProtocol>>>(
2009
2009
unsafe { Ok ( ( OwnedFd :: from_raw_fd ( fds[ 0 ] ) , OwnedFd :: from_raw_fd ( fds[ 1 ] ) ) ) }
2010
2010
}
2011
2011
2012
+ #[ derive( Debug , Clone , Copy , PartialEq , Eq ) ]
2013
+ pub struct Backlog ( i32 ) ;
2014
+
2015
+ impl Backlog {
2016
+ /// Sets the listen queue size to system `SOMAXCONN` value
2017
+ pub const MAXCONN : Self = Self ( libc:: SOMAXCONN ) ;
2018
+ /// Sets the listen queue size to -1 for system supporting it
2019
+ #[ cfg( any( target_os = "linux" , target_os = "freebsd" ) ) ]
2020
+ pub const MAXALLOWABLE : Self = Self ( -1 ) ;
2021
+
2022
+ // Create a `Backlog`, an `EINVAL` will be returned if `val` is invalid.
2023
+ pub fn new < I : Into < i32 > + PartialOrd < I > + From < i32 > > ( val : I ) -> Result < Self > {
2024
+ cfg_if ! {
2025
+ if #[ cfg( any( target_os = "linux" , target_os = "freebsd" ) ) ] {
2026
+ const MIN : i32 = -1 ;
2027
+ } else {
2028
+ const MIN : i32 = 0 ;
2029
+ }
2030
+ }
2031
+
2032
+ if val < MIN . into ( ) || val > Self :: MAXCONN . 0 . into ( ) {
2033
+ return Err ( Errno :: EINVAL ) ;
2034
+ }
2035
+
2036
+ Ok ( Self ( val. into ( ) ) )
2037
+ }
2038
+ }
2039
+
2040
+ #[ derive( Debug , Clone , Copy , PartialEq , Eq ) ]
2041
+ pub enum BacklogTryFromError {
2042
+ TooNegative ,
2043
+ TooPositive ,
2044
+ }
2045
+
2046
+ impl std:: fmt:: Display for BacklogTryFromError {
2047
+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
2048
+ match self {
2049
+ #[ cfg( any( target_os = "linux" , target_os = "freebsd" ) ) ]
2050
+ Self :: TooNegative => write ! ( f, "Passed a positive backlog less than -1" ) ,
2051
+ #[ cfg( not( any( target_os = "linux" , target_os = "freebsd" ) ) ) ]
2052
+ Self :: TooNegative => write ! ( f, "Passed a positive backlog less than 0" ) ,
2053
+ Self :: TooPositive => write ! ( f, "Passed a positive backlog greater than `{:?}`" , Backlog :: MAXCONN )
2054
+ }
2055
+ }
2056
+ }
2057
+
2058
+ impl std:: error:: Error for BacklogTryFromError { }
2059
+
2060
+ impl From < u16 > for Backlog {
2061
+ fn from ( backlog : u16 ) -> Self {
2062
+ Self ( i32:: from ( backlog) )
2063
+ }
2064
+ }
2065
+
2066
+ impl From < u8 > for Backlog {
2067
+ fn from ( backlog : u8 ) -> Self {
2068
+ Self ( i32:: from ( backlog) )
2069
+ }
2070
+ }
2071
+
2072
+ impl From < Backlog > for i32 {
2073
+ fn from ( backlog : Backlog ) -> Self {
2074
+ backlog. 0
2075
+ }
2076
+ }
2077
+
2078
+ impl TryFrom < i64 > for Backlog {
2079
+ type Error = BacklogTryFromError ;
2080
+ fn try_from ( backlog : i64 ) -> std:: result:: Result < Self , Self :: Error > {
2081
+ match backlog {
2082
+ #[ cfg( any( target_os = "linux" , target_os = "freebsd" ) ) ]
2083
+ ..=-2 => Err ( BacklogTryFromError :: TooNegative ) ,
2084
+ #[ cfg( not( any( target_os = "linux" , target_os = "freebsd" ) ) ) ]
2085
+ ..=-1 => Err ( BacklogTryFromError :: TooNegative ) ,
2086
+ #[ cfg( any( target_os = "linux" , target_os = "freebsd" ) ) ]
2087
+ val if ( -1 ..=i64:: from ( Backlog :: MAXCONN . 0 ) ) . contains ( & val) => Ok ( Self ( i32:: try_from ( backlog) . map_err ( |_| BacklogTryFromError :: TooPositive ) ?) ) ,
2088
+ #[ cfg( not( any( target_os = "linux" , target_os = "freebsd" ) ) ) ]
2089
+ val if ( 0 ..=i64:: from ( Backlog :: MAXCONN . 0 ) ) . contains ( & val) => Ok ( Self ( i32:: try_from ( backlog) . map_err ( |_| BacklogTryFromError :: TooPositive ) ?) ) ,
2090
+ _ => Err ( BacklogTryFromError :: TooPositive ) ,
2091
+ }
2092
+ }
2093
+ }
2094
+
2095
+ impl TryFrom < i32 > for Backlog {
2096
+ type Error = BacklogTryFromError ;
2097
+ fn try_from ( backlog : i32 ) -> std:: result:: Result < Self , Self :: Error > {
2098
+ match backlog {
2099
+ #[ cfg( any( target_os = "linux" , target_os = "freebsd" ) ) ]
2100
+ ..=-2 => Err ( BacklogTryFromError :: TooNegative ) ,
2101
+ #[ cfg( not( any( target_os = "linux" , target_os = "freebsd" ) ) ) ]
2102
+ ..=-1 => Err ( BacklogTryFromError :: TooNegative ) ,
2103
+ #[ cfg( any( target_os = "linux" , target_os = "freebsd" ) ) ]
2104
+ val if ( -1 ..=Backlog :: MAXCONN . 0 ) . contains ( & val) => Ok ( Self ( backlog) ) ,
2105
+ #[ cfg( not( any( target_os = "linux" , target_os = "freebsd" ) ) ) ]
2106
+ val if ( 0 ..=Backlog :: MAXCONN . 0 ) . contains ( & val) => Ok ( Self ( backlog) ) ,
2107
+ _ => Err ( BacklogTryFromError :: TooPositive ) ,
2108
+ }
2109
+ }
2110
+ }
2111
+
2112
+ impl TryFrom < i16 > for Backlog {
2113
+ type Error = BacklogTryFromError ;
2114
+ fn try_from ( backlog : i16 ) -> std:: result:: Result < Self , Self :: Error > {
2115
+ match backlog {
2116
+ #[ cfg( any( target_os = "linux" , target_os = "freebsd" ) ) ]
2117
+ ..=-2 => Err ( BacklogTryFromError :: TooNegative ) ,
2118
+ #[ cfg( not( any( target_os = "linux" , target_os = "freebsd" ) ) ) ]
2119
+ ..=-1 => Err ( BacklogTryFromError :: TooNegative ) ,
2120
+ #[ cfg( any( target_os = "linux" , target_os = "freebsd" ) ) ]
2121
+ val if ( -1 ..=i16:: try_from ( Backlog :: MAXCONN . 0 ) . unwrap ( ) ) . contains ( & val) => Ok ( Self ( i32:: from ( backlog) ) ) ,
2122
+ #[ cfg( not( any( target_os = "linux" , target_os = "freebsd" ) ) ) ]
2123
+ val if ( 0 ..=i16:: try_from ( Backlog :: MAXCONN . 0 ) . unwrap ( ) ) . contains ( & val) => Ok ( Self ( i32:: from ( backlog) ) ) ,
2124
+ _ => Err ( BacklogTryFromError :: TooPositive ) ,
2125
+ }
2126
+ }
2127
+ }
2128
+
2129
+ impl TryFrom < i8 > for Backlog {
2130
+ type Error = BacklogTryFromError ;
2131
+ fn try_from ( backlog : i8 ) -> std:: result:: Result < Self , Self :: Error > {
2132
+ match backlog {
2133
+ ..=-2 => Err ( BacklogTryFromError :: TooNegative ) ,
2134
+ _ => Err ( BacklogTryFromError :: TooPositive ) ,
2135
+ }
2136
+ }
2137
+ }
2138
+
2139
+ impl < T : Into < Backlog > > From < Option < T > > for Backlog {
2140
+ fn from ( backlog : Option < T > ) -> Self {
2141
+ backlog. map_or ( Self :: MAXCONN , |b| b. into ( ) )
2142
+ }
2143
+ }
2144
+
2012
2145
/// Listen for connections on a socket
2013
2146
///
2014
2147
/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/listen.html)
2015
- pub fn listen < F : AsFd > ( sock : & F , backlog : usize ) -> Result < ( ) > {
2148
+ pub fn listen < F : AsFd , B : Into < Backlog > > ( sock : & F , backlog : B ) -> Result < ( ) > {
2016
2149
let fd = sock. as_fd ( ) . as_raw_fd ( ) ;
2017
- let res = unsafe { libc:: listen ( fd, backlog as c_int ) } ;
2150
+ let res = unsafe { libc:: listen ( fd, i32 :: from ( backlog. into ( ) ) ) } ;
2018
2151
2019
2152
Errno :: result ( res) . map ( drop)
2020
2153
}
0 commit comments