@@ -11,7 +11,9 @@ use std::{
11
11
} ;
12
12
13
13
use aligned_array:: { Aligned , A8 } ;
14
- use compio_buf:: { BufResult , IntoInner , IoBuf , IoBufMut , IoVectoredBuf , IoVectoredBufMut } ;
14
+ use compio_buf:: {
15
+ BufResult , IntoInner , IoBuf , IoBufMut , IoSlice , IoSliceMut , IoVectoredBuf , IoVectoredBufMut ,
16
+ } ;
15
17
#[ cfg( not( feature = "once_cell_try" ) ) ]
16
18
use once_cell:: sync:: OnceCell as OnceLock ;
17
19
use socket2:: SockAddr ;
@@ -25,10 +27,11 @@ use windows_sys::{
25
27
} ,
26
28
Networking :: WinSock :: {
27
29
closesocket, setsockopt, shutdown, socklen_t, WSAIoctl , WSARecv , WSARecvFrom , WSASend ,
28
- WSASendTo , LPFN_ACCEPTEX , LPFN_CONNECTEX , LPFN_GETACCEPTEXSOCKADDRS , SD_BOTH ,
29
- SD_RECEIVE , SD_SEND , SIO_GET_EXTENSION_FUNCTION_POINTER , SOCKADDR , SOCKADDR_STORAGE ,
30
- SOL_SOCKET , SO_UPDATE_ACCEPT_CONTEXT , SO_UPDATE_CONNECT_CONTEXT , WSAID_ACCEPTEX ,
31
- WSAID_CONNECTEX , WSAID_GETACCEPTEXSOCKADDRS ,
30
+ WSASendMsg , WSASendTo , CMSGHDR , LPFN_ACCEPTEX , LPFN_CONNECTEX ,
31
+ LPFN_GETACCEPTEXSOCKADDRS , LPFN_WSARECVMSG , SD_BOTH , SD_RECEIVE , SD_SEND ,
32
+ SIO_GET_EXTENSION_FUNCTION_POINTER , SOCKADDR , SOCKADDR_STORAGE , SOL_SOCKET ,
33
+ SO_UPDATE_ACCEPT_CONTEXT , SO_UPDATE_CONNECT_CONTEXT , WSABUF , WSAID_ACCEPTEX ,
34
+ WSAID_CONNECTEX , WSAID_GETACCEPTEXSOCKADDRS , WSAID_WSARECVMSG , WSAMSG ,
32
35
} ,
33
36
Storage :: FileSystem :: { FlushFileBuffers , ReadFile , WriteFile } ,
34
37
System :: {
@@ -774,6 +777,146 @@ impl<T: IoVectoredBuf, S: AsRawFd> OpCode for SendToVectored<T, S> {
774
777
}
775
778
}
776
779
780
+ static WSA_RECVMSG : OnceLock < LPFN_WSARECVMSG > = OnceLock :: new ( ) ;
781
+
782
+ /// Receive data and source address with ancillary data into vectored buffer.
783
+ pub struct RecvMsg < T : IoVectoredBufMut , C : IoBufMut , S > {
784
+ addr : SOCKADDR_STORAGE ,
785
+ addr_len : socklen_t ,
786
+ fd : SharedFd < S > ,
787
+ buffer : T ,
788
+ control : C ,
789
+ _p : PhantomPinned ,
790
+ }
791
+
792
+ impl < T : IoVectoredBufMut , C : IoBufMut , S > RecvMsg < T , C , S > {
793
+ /// Create [`RecvMsg`].
794
+ ///
795
+ /// # Panics
796
+ ///
797
+ /// This function will panic if the control message buffer is misaligned.
798
+ pub fn new ( fd : SharedFd < S > , buffer : T , control : C ) -> Self {
799
+ assert ! (
800
+ control. as_buf_ptr( ) . cast:: <CMSGHDR >( ) . is_aligned( ) ,
801
+ "misaligned control message buffer"
802
+ ) ;
803
+ Self {
804
+ addr : unsafe { std:: mem:: zeroed ( ) } ,
805
+ addr_len : std:: mem:: size_of :: < SOCKADDR_STORAGE > ( ) as _ ,
806
+ fd,
807
+ buffer,
808
+ control,
809
+ _p : PhantomPinned ,
810
+ }
811
+ }
812
+ }
813
+
814
+ impl < T : IoVectoredBufMut , C : IoBufMut , S > IntoInner for RecvMsg < T , C , S > {
815
+ type Inner = ( ( T , C ) , SOCKADDR_STORAGE , socklen_t ) ;
816
+
817
+ fn into_inner ( self ) -> Self :: Inner {
818
+ ( ( self . buffer , self . control ) , self . addr , self . addr_len )
819
+ }
820
+ }
821
+
822
+ impl < T : IoVectoredBufMut , C : IoBufMut , S : AsRawFd > OpCode for RecvMsg < T , C , S > {
823
+ unsafe fn operate ( self : Pin < & mut Self > , optr : * mut OVERLAPPED ) -> Poll < io:: Result < usize > > {
824
+ let recvmsg_fn = WSA_RECVMSG
825
+ . get_or_try_init ( || get_wsa_fn ( self . fd . as_raw_fd ( ) , WSAID_WSARECVMSG ) ) ?
826
+ . ok_or_else ( || {
827
+ io:: Error :: new ( io:: ErrorKind :: Unsupported , "cannot retrieve WSARecvMsg" )
828
+ } ) ?;
829
+
830
+ let this = self . get_unchecked_mut ( ) ;
831
+ let mut slices = this. buffer . as_io_slices_mut ( ) ;
832
+ let mut msg = WSAMSG {
833
+ name : & mut this. addr as * mut _ as _ ,
834
+ namelen : this. addr_len ,
835
+ lpBuffers : slices. as_mut_ptr ( ) as _ ,
836
+ dwBufferCount : slices. len ( ) as _ ,
837
+ Control : std:: mem:: transmute :: < IoSliceMut , WSABUF > ( this. control . as_io_slice_mut ( ) ) ,
838
+ dwFlags : 0 ,
839
+ } ;
840
+
841
+ let mut received = 0 ;
842
+ let res = recvmsg_fn (
843
+ this. fd . as_raw_fd ( ) as _ ,
844
+ & mut msg,
845
+ & mut received,
846
+ optr,
847
+ None ,
848
+ ) ;
849
+ winsock_result ( res, received)
850
+ }
851
+
852
+ unsafe fn cancel ( self : Pin < & mut Self > , optr : * mut OVERLAPPED ) -> io:: Result < ( ) > {
853
+ cancel ( self . fd . as_raw_fd ( ) , optr)
854
+ }
855
+ }
856
+
857
+ /// Send data to specified address accompanied by ancillary data from vectored
858
+ /// buffer.
859
+ pub struct SendMsg < T : IoVectoredBuf , C : IoBuf , S > {
860
+ fd : SharedFd < S > ,
861
+ buffer : T ,
862
+ control : C ,
863
+ addr : SockAddr ,
864
+ _p : PhantomPinned ,
865
+ }
866
+
867
+ impl < T : IoVectoredBuf , C : IoBuf , S > SendMsg < T , C , S > {
868
+ /// Create [`SendMsg`].
869
+ ///
870
+ /// # Panics
871
+ ///
872
+ /// This function will panic if the control message buffer is misaligned.
873
+ pub fn new ( fd : SharedFd < S > , buffer : T , control : C , addr : SockAddr ) -> Self {
874
+ assert ! (
875
+ control. as_buf_ptr( ) . cast:: <CMSGHDR >( ) . is_aligned( ) ,
876
+ "misaligned control message buffer"
877
+ ) ;
878
+ Self {
879
+ fd,
880
+ buffer,
881
+ control,
882
+ addr,
883
+ _p : PhantomPinned ,
884
+ }
885
+ }
886
+ }
887
+
888
+ impl < T : IoVectoredBuf , C : IoBuf , S > IntoInner for SendMsg < T , C , S > {
889
+ type Inner = ( T , C ) ;
890
+
891
+ fn into_inner ( self ) -> Self :: Inner {
892
+ ( self . buffer , self . control )
893
+ }
894
+ }
895
+
896
+ impl < T : IoVectoredBuf , C : IoBuf , S : AsRawFd > OpCode for SendMsg < T , C , S > {
897
+ unsafe fn operate ( self : Pin < & mut Self > , optr : * mut OVERLAPPED ) -> Poll < io:: Result < usize > > {
898
+ let this = self . get_unchecked_mut ( ) ;
899
+
900
+ let slices = this. buffer . as_io_slices ( ) ;
901
+ let msg = WSAMSG {
902
+ name : this. addr . as_ptr ( ) as _ ,
903
+ namelen : this. addr . len ( ) ,
904
+ lpBuffers : slices. as_ptr ( ) as _ ,
905
+ dwBufferCount : slices. len ( ) as _ ,
906
+ Control : std:: mem:: transmute :: < IoSlice , WSABUF > ( this. control . as_io_slice ( ) ) ,
907
+ dwFlags : 0 ,
908
+ } ;
909
+
910
+ let mut sent = 0 ;
911
+ let res = WSASendMsg ( this. fd . as_raw_fd ( ) as _ , & msg, 0 , & mut sent, optr, None ) ;
912
+ winsock_result ( res, sent)
913
+ }
914
+
915
+ unsafe fn cancel ( self : Pin < & mut Self > , optr : * mut OVERLAPPED ) -> io:: Result < ( ) > {
916
+ cancel ( self . fd . as_raw_fd ( ) , optr)
917
+ }
918
+ }
919
+
777
920
/// Connect a named pipe server.
778
921
pub struct ConnectNamedPipe < S > {
779
922
pub ( crate ) fd : SharedFd < S > ,
0 commit comments