@@ -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 , LPFN_ACCEPTEX , LPFN_CONNECTEX , LPFN_GETACCEPTEXSOCKADDRS ,
31
+ LPFN_WSARECVMSG , SD_BOTH , SD_RECEIVE , SD_SEND , SIO_GET_EXTENSION_FUNCTION_POINTER ,
32
+ SOCKADDR , SOCKADDR_STORAGE , SOL_SOCKET , SO_UPDATE_ACCEPT_CONTEXT ,
33
+ SO_UPDATE_CONNECT_CONTEXT , WSABUF , WSAID_ACCEPTEX , WSAID_CONNECTEX ,
34
+ WSAID_GETACCEPTEXSOCKADDRS , WSAID_WSARECVMSG , WSAMSG ,
32
35
} ,
33
36
Storage :: FileSystem :: { FlushFileBuffers , ReadFile , WriteFile } ,
34
37
System :: {
@@ -774,6 +777,261 @@ 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
+ struct RecvMsgHeader < S > {
783
+ fd : SharedFd < S > ,
784
+ addr : SOCKADDR_STORAGE ,
785
+ addr_len : socklen_t ,
786
+ _p : PhantomPinned ,
787
+ }
788
+
789
+ impl < S > RecvMsgHeader < S > {
790
+ fn new ( fd : SharedFd < S > ) -> Self {
791
+ Self {
792
+ fd,
793
+ addr : unsafe { std:: mem:: zeroed ( ) } ,
794
+ addr_len : std:: mem:: size_of :: < SOCKADDR_STORAGE > ( ) as _ ,
795
+ _p : PhantomPinned ,
796
+ }
797
+ }
798
+
799
+ fn into_addr ( self ) -> ( SOCKADDR_STORAGE , socklen_t ) {
800
+ ( self . addr , self . addr_len )
801
+ }
802
+ }
803
+
804
+ impl < S : AsRawFd > RecvMsgHeader < S > {
805
+ unsafe fn operate (
806
+ & mut self ,
807
+ slices : & mut [ IoSliceMut ] ,
808
+ control : IoSliceMut ,
809
+ optr : * mut OVERLAPPED ,
810
+ ) -> Poll < io:: Result < usize > > {
811
+ let recvmsg_fn = WSA_RECVMSG
812
+ . get_or_try_init ( || get_wsa_fn ( self . fd . as_raw_fd ( ) , WSAID_WSARECVMSG ) ) ?
813
+ . ok_or_else ( || {
814
+ io:: Error :: new ( io:: ErrorKind :: Unsupported , "cannot retrieve WSARecvMsg" )
815
+ } ) ?;
816
+
817
+ let mut msg = WSAMSG {
818
+ name : & mut self . addr as * mut _ as _ ,
819
+ namelen : self . addr_len ,
820
+ lpBuffers : slices. as_mut_ptr ( ) as _ ,
821
+ dwBufferCount : slices. len ( ) as _ ,
822
+ Control : std:: mem:: transmute :: < IoSliceMut , WSABUF > ( control) ,
823
+ dwFlags : 0 ,
824
+ } ;
825
+
826
+ let mut received = 0 ;
827
+ let res = recvmsg_fn (
828
+ self . fd . as_raw_fd ( ) as _ ,
829
+ & mut msg,
830
+ & mut received,
831
+ optr,
832
+ None ,
833
+ ) ;
834
+ winsock_result ( res, received)
835
+ }
836
+ }
837
+
838
+ /// Receive data and source address with ancillary data.
839
+ pub struct RecvMsg < T : IoBufMut , C : IoBufMut , S > {
840
+ header : RecvMsgHeader < S > ,
841
+ buffer : MsgBuf < T , C > ,
842
+ }
843
+
844
+ impl < T : IoBufMut , C : IoBufMut , S > RecvMsg < T , C , S > {
845
+ /// Create [`RecvMsg`].
846
+ pub fn new ( fd : SharedFd < S > , buffer : MsgBuf < T , C > ) -> Self {
847
+ Self {
848
+ header : RecvMsgHeader :: new ( fd) ,
849
+ buffer,
850
+ }
851
+ }
852
+ }
853
+
854
+ impl < T : IoBufMut , C : IoBufMut , S > IntoInner for RecvMsg < T , C , S > {
855
+ type Inner = ( MsgBuf < T , C > , SOCKADDR_STORAGE , socklen_t ) ;
856
+
857
+ fn into_inner ( self ) -> Self :: Inner {
858
+ let ( addr, addr_len) = self . header . into_addr ( ) ;
859
+ ( self . buffer , addr, addr_len)
860
+ }
861
+ }
862
+
863
+ impl < T : IoBufMut , C : IoBufMut , S : AsRawFd > OpCode for RecvMsg < T , C , S > {
864
+ unsafe fn operate ( self : Pin < & mut Self > , optr : * mut OVERLAPPED ) -> Poll < io:: Result < usize > > {
865
+ let this = self . get_unchecked_mut ( ) ;
866
+ this. header . operate (
867
+ & mut [ this. buffer . inner . as_io_slice_mut ( ) ] ,
868
+ this. buffer . control . as_io_slice_mut ( ) ,
869
+ optr,
870
+ )
871
+ }
872
+
873
+ unsafe fn cancel ( self : Pin < & mut Self > , optr : * mut OVERLAPPED ) -> io:: Result < ( ) > {
874
+ cancel ( self . header . fd . as_raw_fd ( ) , optr)
875
+ }
876
+ }
877
+
878
+ /// Receive data and source address with ancillary data into vectored buffer.
879
+ pub struct RecvMsgVectored < T : IoVectoredBufMut , C : IoBufMut , S > {
880
+ header : RecvMsgHeader < S > ,
881
+ buffer : MsgBuf < T , C > ,
882
+ }
883
+
884
+ impl < T : IoVectoredBufMut , C : IoBufMut , S > RecvMsgVectored < T , C , S > {
885
+ /// Create [`RecvMsgVectored`].
886
+ pub fn new ( fd : SharedFd < S > , buffer : MsgBuf < T , C > ) -> Self {
887
+ Self {
888
+ header : RecvMsgHeader :: new ( fd) ,
889
+ buffer,
890
+ }
891
+ }
892
+ }
893
+
894
+ impl < T : IoVectoredBufMut , C : IoBufMut , S > IntoInner for RecvMsgVectored < T , C , S > {
895
+ type Inner = ( MsgBuf < T , C > , SOCKADDR_STORAGE , socklen_t ) ;
896
+
897
+ fn into_inner ( self ) -> Self :: Inner {
898
+ let ( addr, addr_len) = self . header . into_addr ( ) ;
899
+ ( self . buffer , addr, addr_len)
900
+ }
901
+ }
902
+
903
+ impl < T : IoVectoredBufMut , C : IoBufMut , S : AsRawFd > OpCode for RecvMsgVectored < T , C , S > {
904
+ unsafe fn operate ( self : Pin < & mut Self > , optr : * mut OVERLAPPED ) -> Poll < io:: Result < usize > > {
905
+ let this = self . get_unchecked_mut ( ) ;
906
+ this. header . operate (
907
+ & mut this. buffer . inner . as_io_slices_mut ( ) ,
908
+ this. buffer . control . as_io_slice_mut ( ) ,
909
+ optr,
910
+ )
911
+ }
912
+
913
+ unsafe fn cancel ( self : Pin < & mut Self > , optr : * mut OVERLAPPED ) -> io:: Result < ( ) > {
914
+ cancel ( self . header . fd . as_raw_fd ( ) , optr)
915
+ }
916
+ }
917
+
918
+ struct SendMsgHeader < S > {
919
+ fd : SharedFd < S > ,
920
+ addr : SockAddr ,
921
+ _p : PhantomPinned ,
922
+ }
923
+
924
+ impl < S > SendMsgHeader < S > {
925
+ pub fn new ( fd : SharedFd < S > , addr : SockAddr ) -> Self {
926
+ Self {
927
+ fd,
928
+ addr,
929
+ _p : PhantomPinned ,
930
+ }
931
+ }
932
+ }
933
+
934
+ impl < S : AsRawFd > SendMsgHeader < S > {
935
+ unsafe fn operate (
936
+ & mut self ,
937
+ slices : & mut [ IoSlice ] ,
938
+ control : IoSlice ,
939
+ optr : * mut OVERLAPPED ,
940
+ ) -> Poll < io:: Result < usize > > {
941
+ let msg = WSAMSG {
942
+ name : self . addr . as_ptr ( ) as _ ,
943
+ namelen : self . addr . len ( ) ,
944
+ lpBuffers : slices. as_ptr ( ) as _ ,
945
+ dwBufferCount : slices. len ( ) as _ ,
946
+ Control : std:: mem:: transmute :: < IoSlice , WSABUF > ( control) ,
947
+ dwFlags : 0 ,
948
+ } ;
949
+
950
+ let mut sent = 0 ;
951
+ let res = WSASendMsg ( self . fd . as_raw_fd ( ) as _ , & msg, 0 , & mut sent, optr, None ) ;
952
+ winsock_result ( res, sent)
953
+ }
954
+ }
955
+
956
+ /// Send data to specified address accompanied by ancillary data.
957
+ pub struct SendMsg < T : IoBuf , C : IoBuf , S > {
958
+ header : SendMsgHeader < S > ,
959
+ buffer : MsgBuf < T , C > ,
960
+ }
961
+
962
+ impl < T : IoBuf , C : IoBuf , S > SendMsg < T , C , S > {
963
+ /// Create [`SendMsg`].
964
+ pub fn new ( fd : SharedFd < S > , buffer : MsgBuf < T , C > , addr : SockAddr ) -> Self {
965
+ Self {
966
+ header : SendMsgHeader :: new ( fd, addr) ,
967
+ buffer,
968
+ }
969
+ }
970
+ }
971
+
972
+ impl < T : IoBuf , C : IoBuf , S > IntoInner for SendMsg < T , C , S > {
973
+ type Inner = MsgBuf < T , C > ;
974
+
975
+ fn into_inner ( self ) -> Self :: Inner {
976
+ self . buffer
977
+ }
978
+ }
979
+
980
+ impl < T : IoBuf , C : IoBuf , S : AsRawFd > OpCode for SendMsg < T , C , S > {
981
+ unsafe fn operate ( self : Pin < & mut Self > , optr : * mut OVERLAPPED ) -> Poll < io:: Result < usize > > {
982
+ let this = self . get_unchecked_mut ( ) ;
983
+ this. header . operate (
984
+ & mut [ this. buffer . inner . as_io_slice ( ) ] ,
985
+ this. buffer . control . as_io_slice ( ) ,
986
+ optr,
987
+ )
988
+ }
989
+
990
+ unsafe fn cancel ( self : Pin < & mut Self > , optr : * mut OVERLAPPED ) -> io:: Result < ( ) > {
991
+ cancel ( self . header . fd . as_raw_fd ( ) , optr)
992
+ }
993
+ }
994
+
995
+ /// Send data to specified address accompanied by ancillary data from vectored
996
+ /// buffer.
997
+ pub struct SendMsgVectored < T : IoVectoredBuf , C : IoBuf , S > {
998
+ header : SendMsgHeader < S > ,
999
+ buffer : MsgBuf < T , C > ,
1000
+ }
1001
+
1002
+ impl < T : IoVectoredBuf , C : IoBuf , S > SendMsgVectored < T , C , S > {
1003
+ /// Create [`SendMsgVectored`].
1004
+ pub fn new ( fd : SharedFd < S > , buffer : MsgBuf < T , C > , addr : SockAddr ) -> Self {
1005
+ Self {
1006
+ header : SendMsgHeader :: new ( fd, addr) ,
1007
+ buffer,
1008
+ }
1009
+ }
1010
+ }
1011
+
1012
+ impl < T : IoVectoredBuf , C : IoBuf , S > IntoInner for SendMsgVectored < T , C , S > {
1013
+ type Inner = MsgBuf < T , C > ;
1014
+
1015
+ fn into_inner ( self ) -> Self :: Inner {
1016
+ self . buffer
1017
+ }
1018
+ }
1019
+
1020
+ impl < T : IoVectoredBuf , C : IoBuf , S : AsRawFd > OpCode for SendMsgVectored < T , C , S > {
1021
+ unsafe fn operate ( self : Pin < & mut Self > , optr : * mut OVERLAPPED ) -> Poll < io:: Result < usize > > {
1022
+ let this = self . get_unchecked_mut ( ) ;
1023
+ this. header . operate (
1024
+ & mut this. buffer . inner . as_io_slices ( ) ,
1025
+ this. buffer . control . as_io_slice ( ) ,
1026
+ optr,
1027
+ )
1028
+ }
1029
+
1030
+ unsafe fn cancel ( self : Pin < & mut Self > , optr : * mut OVERLAPPED ) -> io:: Result < ( ) > {
1031
+ cancel ( self . header . fd . as_raw_fd ( ) , optr)
1032
+ }
1033
+ }
1034
+
777
1035
/// Connect a named pipe server.
778
1036
pub struct ConnectNamedPipe < S > {
779
1037
pub ( crate ) fd : SharedFd < S > ,
0 commit comments