11use alloc:: sync:: Arc ;
2- #[ cfg( any( feature = "net" , feature = "virtio-vsock" ) ) ]
32use core:: ffi:: c_int;
43use core:: future;
54use core:: mem:: MaybeUninit ;
65use core:: pin:: pin;
76use core:: task:: Poll :: { Pending , Ready } ;
87use core:: time:: Duration ;
98
10- #[ cfg( any( feature = "net" , feature = "virtio-vsock" ) ) ]
11- use num_enum:: TryFromPrimitive ;
9+ use num_enum:: { IntoPrimitive , TryFromPrimitive } ;
1210#[ cfg( feature = "net" ) ]
1311use smoltcp:: wire:: { IpEndpoint , IpListenEndpoint } ;
1412
@@ -18,6 +16,8 @@ use crate::errno::Errno;
1816use crate :: executor:: block_on;
1917use crate :: fs:: { FileAttr , SeekWhence } ;
2018use crate :: io;
19+ #[ cfg( feature = "net" ) ]
20+ use crate :: syscalls:: socket:: { Ipproto , SOL_SOCKET , socklen_t} ;
2121
2222mod delegate;
2323mod eventfd;
@@ -48,12 +48,100 @@ pub(crate) enum ListenEndpoint {
4848 Vsock ( socket:: vsock:: VsockListenEndpoint ) ,
4949}
5050
51- #[ cfg( any( feature = "net" , feature = "virtio-vsock" ) ) ]
52- #[ derive( TryFromPrimitive , PartialEq , Eq , Clone , Copy , Debug ) ]
53- #[ repr( i32 ) ]
51+ #[ allow( dead_code) ]
52+ #[ derive( Debug , PartialEq , Eq ) ]
5453pub ( crate ) enum SocketOption {
55- TcpNodelay = 1 ,
54+ TcpOption ( SocketOptionTcp ) ,
55+ SocketOption ( SocketOptionSocket ) ,
56+ }
57+
58+ #[ cfg( feature = "net" ) ]
59+ impl SocketOption {
60+ pub fn from_level_optname ( level : i32 , optname : i32 ) -> Option < SocketOption > {
61+ if level == SOL_SOCKET {
62+ SocketOptionSocket :: try_from ( optname)
63+ . ok ( )
64+ . map ( SocketOption :: SocketOption )
65+ } else {
66+ let protocol = u8:: try_from ( level)
67+ . ok ( )
68+ . and_then ( |proto| Ipproto :: try_from ( proto) . ok ( ) ) ?;
69+
70+ match protocol {
71+ Ipproto :: Tcp => SocketOptionTcp :: try_from ( optname)
72+ . ok ( )
73+ . map ( SocketOption :: TcpOption ) ,
74+ _ => None ,
75+ }
76+ }
77+ }
78+ }
79+
80+ #[ cfg( feature = "net" ) ]
81+ pub struct SocketOptionValue {
82+ optval : * const core:: ffi:: c_void ,
83+ optlen : socklen_t ,
84+ }
85+
86+ #[ cfg( not( feature = "net" ) ) ]
87+ pub struct SocketOptionValue ;
88+
89+ unsafe impl Send for SocketOptionValue { }
90+
91+ #[ cfg( feature = "net" ) ]
92+ impl SocketOptionValue {
93+ pub fn new ( optval : * const core:: ffi:: c_void , optlen : socklen_t ) -> Self {
94+ Self { optval, optlen }
95+ }
96+ }
97+
98+ #[ cfg( feature = "net" ) ]
99+ impl TryFrom < & SocketOptionValue > for i32 {
100+ type Error = Errno ;
101+
102+ fn try_from ( value : & SocketOptionValue ) -> Result < Self , Self :: Error > {
103+ if value. optval . is_null ( ) {
104+ return Err ( Errno :: Inval ) ;
105+ }
106+
107+ if value. optlen != size_of :: < i32 > ( ) as u32 {
108+ return Err ( Errno :: Inval ) ;
109+ }
110+
111+ let value = unsafe { * value. optval . cast :: < i32 > ( ) } ;
112+ Ok ( value)
113+ }
114+ }
115+
116+ #[ cfg( feature = "net" ) ]
117+ impl TryFrom < & SocketOptionValue > for bool {
118+ type Error = Errno ;
119+
120+ fn try_from ( value : & SocketOptionValue ) -> Result < Self , Self :: Error > {
121+ let value: i32 = value. try_into ( ) ?;
122+ Ok ( value != 0 )
123+ }
124+ }
125+
126+ #[ derive( TryFromPrimitive , IntoPrimitive , PartialEq , Eq , Clone , Copy , Debug ) ]
127+ #[ repr( i32 ) ]
128+ #[ non_exhaustive]
129+ pub ( crate ) enum SocketOptionTcp {
130+ #[ doc( alias = "TCP_NODELAY" ) ]
131+ TcpNoDelay = 1 ,
132+ }
133+
134+ #[ derive( TryFromPrimitive , IntoPrimitive , PartialEq , Eq , Clone , Copy , Debug ) ]
135+ #[ repr( i32 ) ]
136+ #[ non_exhaustive]
137+ pub ( crate ) enum SocketOptionSocket {
138+ #[ doc( alias = "SO_REUSEADDR" ) ]
139+ ReuseAddr = 1 ,
140+ #[ doc( alias = "SO_KEEPALIVE" ) ]
141+ KeepAlive = 8 ,
142+ #[ doc( alias = "SO_SNDBUF" ) ]
56143 SoSndbuf = 0x1001 ,
144+ #[ doc( alias = "SO_RCVBUF" ) ]
57145 SoRcvbuf = 0x1002 ,
58146}
59147
@@ -265,7 +353,7 @@ pub(crate) trait ObjectInterface: Sync + Send {
265353
266354 /// `setsockopt` sets options on sockets
267355 #[ cfg( any( feature = "net" , feature = "virtio-vsock" ) ) ]
268- async fn setsockopt ( & self , _opt : SocketOption , _optval : bool ) -> io:: Result < ( ) > {
356+ async fn setsockopt ( & self , _opt : SocketOption , _optval : SocketOptionValue ) -> io:: Result < ( ) > {
269357 Err ( Errno :: Notsock )
270358 }
271359
0 commit comments