@@ -917,6 +917,8 @@ mod buf_ring {
917917 } ;
918918
919919 use io_uring:: { opcode, squeue:: Flags , types:: Fd } ;
920+ use pin_project_lite:: pin_project;
921+ use socket2:: { SockAddr , SockAddrStorage , socklen_t} ;
920922
921923 use super :: OpCode ;
922924 use crate :: { BorrowedBuffer , BufferPool , OpEntry , TakeBuffer } ;
@@ -1096,6 +1098,83 @@ mod buf_ring {
10961098 res
10971099 }
10981100 }
1101+
1102+ pin_project ! {
1103+ /// Receive data and source address into managed buffer.
1104+ pub struct RecvFromManaged <S > {
1105+ fd: S ,
1106+ buffer_group: u16 ,
1107+ flags: i32 ,
1108+ addr: SockAddrStorage ,
1109+ addr_len: socklen_t,
1110+ iovec: libc:: iovec,
1111+ msg: libc:: msghdr,
1112+ _p: PhantomPinned ,
1113+ }
1114+ }
1115+
1116+ impl < S > RecvFromManaged < S > {
1117+ /// Create [`RecvFromManaged`].
1118+ pub fn new ( fd : S , buffer_pool : & BufferPool , len : usize , flags : i32 ) -> io:: Result < Self > {
1119+ #[ cfg( fusion) ]
1120+ let buffer_pool = buffer_pool. as_io_uring ( ) ;
1121+ let len: u32 = len. try_into ( ) . map_err ( |_| {
1122+ io:: Error :: new ( io:: ErrorKind :: InvalidInput , "required length too long" )
1123+ } ) ?;
1124+ let addr = SockAddrStorage :: zeroed ( ) ;
1125+ Ok ( Self {
1126+ fd,
1127+ buffer_group : buffer_pool. buffer_group ( ) ,
1128+ flags,
1129+ addr_len : addr. size_of ( ) as _ ,
1130+ addr,
1131+ iovec : libc:: iovec {
1132+ iov_base : ptr:: null_mut ( ) ,
1133+ iov_len : len as _ ,
1134+ } ,
1135+ msg : unsafe { std:: mem:: zeroed ( ) } ,
1136+ _p : PhantomPinned ,
1137+ } )
1138+ }
1139+ }
1140+
1141+ unsafe impl < S : AsFd > OpCode for RecvFromManaged < S > {
1142+ fn create_entry ( self : Pin < & mut Self > ) -> OpEntry {
1143+ let this = self . project ( ) ;
1144+ this. msg . msg_name = this. addr as * mut _ as _ ;
1145+ this. msg . msg_namelen = * this. addr_len ;
1146+ this. msg . msg_iov = this. iovec as * const _ as * mut _ ;
1147+ this. msg . msg_iovlen = 1 ;
1148+ opcode:: RecvMsg :: new ( Fd ( this. fd . as_fd ( ) . as_raw_fd ( ) ) , this. msg )
1149+ . flags ( * this. flags as _ )
1150+ . buf_group ( * this. buffer_group )
1151+ . build ( )
1152+ . flags ( Flags :: BUFFER_SELECT )
1153+ . into ( )
1154+ }
1155+ }
1156+
1157+ impl < S > TakeBuffer for RecvFromManaged < S > {
1158+ type Buffer < ' a > = ( BorrowedBuffer < ' a > , SockAddr ) ;
1159+ type BufferPool = BufferPool ;
1160+
1161+ fn take_buffer (
1162+ self ,
1163+ buffer_pool : & Self :: BufferPool ,
1164+ result : io:: Result < usize > ,
1165+ buffer_id : u16 ,
1166+ ) -> io:: Result < Self :: Buffer < ' _ > > {
1167+ #[ cfg( fusion) ]
1168+ let buffer_pool = buffer_pool. as_io_uring ( ) ;
1169+ let result = result. inspect_err ( |_| buffer_pool. reuse_buffer ( buffer_id) ) ?;
1170+ let addr = unsafe { SockAddr :: new ( self . addr , self . addr_len ) } ;
1171+ // SAFETY: result is valid
1172+ let buffer = unsafe { buffer_pool. get_buffer ( buffer_id, result) } ?;
1173+ #[ cfg( fusion) ]
1174+ let buffer = BorrowedBuffer :: new_io_uring ( buffer) ;
1175+ Ok ( ( buffer, addr) )
1176+ }
1177+ }
10991178}
11001179
1101- pub use buf_ring:: { ReadManaged , ReadManagedAt , RecvManaged } ;
1180+ pub use buf_ring:: { ReadManaged , ReadManagedAt , RecvFromManaged , RecvManaged } ;
0 commit comments