1- use std:: os:: windows:: io:: AsRawSocket ;
2-
31use rustix:: net:: RecvFlags ;
42use windows_sys:: Win32 :: {
53 Networking :: WinSock :: {
6- LPFN_ACCEPTEX , LPFN_CONNECTEX , LPFN_GETACCEPTEXSOCKADDRS , LPFN_WSARECVMSG ,
7- SO_UPDATE_ACCEPT_CONTEXT , SO_UPDATE_CONNECT_CONTEXT , SOCKADDR , SOCKADDR_STORAGE ,
8- SOL_SOCKET , WSAID_ACCEPTEX , WSAID_CONNECTEX , WSAID_GETACCEPTEXSOCKADDRS , WSAID_WSARECVMSG ,
9- WSAMSG , WSARecv , WSARecvFrom , WSASend , WSASendMsg , WSASendTo , closesocket , setsockopt ,
10- socklen_t,
4+ LPFN_ACCEPTEX , LPFN_CONNECTEX , LPFN_DISCONNECTEX , LPFN_GETACCEPTEXSOCKADDRS ,
5+ LPFN_WSARECVMSG , SO_UPDATE_ACCEPT_CONTEXT , SO_UPDATE_CONNECT_CONTEXT , SOCKADDR ,
6+ SOCKADDR_STORAGE , SOL_SOCKET , TF_REUSE_SOCKET , WSAID_ACCEPTEX , WSAID_CONNECTEX ,
7+ WSAID_DISCONNECTEX , WSAID_GETACCEPTEXSOCKADDRS , WSAID_WSARECVMSG , WSAMSG , WSARecv ,
8+ WSARecvFrom , WSASend , WSASendMsg , WSASendTo , closesocket , setsockopt , socklen_t,
119 } ,
1210 System :: IO :: OVERLAPPED ,
1311} ;
@@ -35,15 +33,15 @@ unsafe impl OpCode for CloseSocket {
3533}
3634
3735/// Accept a connection.
38- pub struct Accept < S > {
36+ pub struct Accept < S , SA > {
3937 pub ( crate ) fd : S ,
40- pub ( crate ) accept_fd : socket2 :: Socket ,
38+ pub ( crate ) accept_fd : SA ,
4139 pub ( crate ) buffer : [ u8 ; ACCEPT_BUFFER_SIZE ] ,
4240}
4341
44- impl < S > Accept < S > {
42+ impl < S , SA > Accept < S , SA > {
4543 /// Create [`Accept`]. `accept_fd` should not be bound.
46- pub fn new ( fd : S , accept_fd : socket2 :: Socket ) -> Self {
44+ pub fn new ( fd : S , accept_fd : SA ) -> Self {
4745 Self {
4846 fd,
4947 accept_fd,
@@ -52,14 +50,14 @@ impl<S> Accept<S> {
5250 }
5351}
5452
55- impl < S : AsFd > Accept < S > {
53+ impl < S : AsFd , SA : AsFd > Accept < S , SA > {
5654 /// Update accept context.
5755 pub fn update_context ( & self ) -> io:: Result < ( ) > {
5856 let fd = self . fd . as_fd ( ) . as_raw_fd ( ) ;
5957 syscall ! (
6058 SOCKET ,
6159 setsockopt(
62- self . accept_fd. as_raw_socket ( ) as _,
60+ self . accept_fd. as_fd ( ) . as_raw_fd ( ) as _,
6361 SOL_SOCKET ,
6462 SO_UPDATE_ACCEPT_CONTEXT ,
6563 & fd as * const _ as _,
@@ -70,7 +68,7 @@ impl<S: AsFd> Accept<S> {
7068 }
7169
7270 /// Get the remote address from the inner buffer.
73- pub fn into_addr ( self ) -> io:: Result < ( socket2 :: Socket , SockAddr ) > {
71+ pub fn into_addr ( self ) -> io:: Result < ( SA , SockAddr ) > {
7472 let get_addrs_fn = GET_ADDRS
7573 . get_or_try_init ( || {
7674 get_wsa_fn ( self . fd . as_fd ( ) . as_raw_fd ( ) , WSAID_GETACCEPTEXSOCKADDRS )
@@ -109,7 +107,7 @@ impl<S: AsFd> Accept<S> {
109107 }
110108}
111109
112- unsafe impl < S : AsFd > OpCode for Accept < S > {
110+ unsafe impl < S : AsFd , SA : AsFd > OpCode for Accept < S , SA > {
113111 type Control = ( ) ;
114112
115113 unsafe fn operate ( & mut self , _: & mut ( ) , optr : * mut OVERLAPPED ) -> Poll < io:: Result < usize > > {
@@ -122,7 +120,7 @@ unsafe impl<S: AsFd> OpCode for Accept<S> {
122120 let res = unsafe {
123121 accept_fn (
124122 self . fd . as_fd ( ) . as_raw_fd ( ) as _ ,
125- self . accept_fd . as_raw_socket ( ) as _ ,
123+ self . accept_fd . as_fd ( ) . as_raw_fd ( ) as _ ,
126124 self . buffer . sys_slice_mut ( ) . ptr ( ) as _ ,
127125 0 ,
128126 ACCEPT_ADDR_BUFFER_SIZE as _ ,
@@ -187,7 +185,38 @@ unsafe impl<S: AsFd> OpCode for Connect<S> {
187185 }
188186}
189187
190- /// Receive data from remote.
188+ /// Disconnect a connected socket and reuse it for another connection.
189+ pub struct Disconnect < S > {
190+ pub ( crate ) fd : S ,
191+ }
192+
193+ impl < S > Disconnect < S > {
194+ /// Create [`Disconnect`].
195+ pub fn new ( fd : S ) -> Self {
196+ Self { fd }
197+ }
198+ }
199+
200+ static DISCONNECT_EX : OnceLock < LPFN_DISCONNECTEX > = OnceLock :: new ( ) ;
201+
202+ unsafe impl < S : AsFd > OpCode for Disconnect < S > {
203+ type Control = ( ) ;
204+
205+ unsafe fn operate ( & mut self , _: & mut ( ) , optr : * mut OVERLAPPED ) -> Poll < io:: Result < usize > > {
206+ let disconnect_fn = DISCONNECT_EX
207+ . get_or_try_init ( || get_wsa_fn ( self . fd . as_fd ( ) . as_raw_fd ( ) , WSAID_DISCONNECTEX ) ) ?
208+ . ok_or_else ( || {
209+ io:: Error :: new ( io:: ErrorKind :: Unsupported , "cannot retrieve DisconnectEx" )
210+ } ) ?;
211+ let res =
212+ unsafe { disconnect_fn ( self . fd . as_fd ( ) . as_raw_fd ( ) as _ , optr, TF_REUSE_SOCKET , 0 ) } ;
213+ win32_result ( res, 0 )
214+ }
215+
216+ fn cancel ( & mut self , _: & mut ( ) , optr : * mut OVERLAPPED ) -> io:: Result < ( ) > {
217+ cancel ( self . fd . as_fd ( ) . as_raw_fd ( ) , optr)
218+ }
219+ }
191220
192221#[ derive( Default ) ]
193222#[ doc( hidden) ]
0 commit comments