@@ -80,6 +80,13 @@ use crate::{Domain, Protocol, SockAddr, TcpKeepalive, Type};
8080#[ cfg( not( target_os = "redox" ) ) ]
8181use crate :: { MsgHdr , MsgHdrMut , RecvFlags } ;
8282
83+ define_mmsg_if_supported ! {
84+ use crate :: { MMsgHdr , MMsgHdrMut } ;
85+
86+ // Used in `MMsgHdr`.
87+ pub ( crate ) use libc:: mmsghdr;
88+ }
89+
8390pub ( crate ) use libc:: c_int;
8491
8592// Used in `Domain`.
@@ -1076,6 +1083,35 @@ pub(crate) fn recvmsg(
10761083 syscall ! ( recvmsg( fd, & mut msg. inner, flags) ) . map ( |n| n as usize )
10771084}
10781085
1086+ define_mmsg_if_supported ! {
1087+ pub ( crate ) fn recvmmsg(
1088+ fd: Socket ,
1089+ msgvec: & mut [ MMsgHdrMut <' _, ' _, ' _>] ,
1090+ flags: c_int,
1091+ timeout: Option <Duration >,
1092+ ) -> io:: Result <usize > {
1093+ if cfg!( target_env = "musl" ) {
1094+ debug_assert!( flags >= 0 , "socket flags must be non-negative" ) ;
1095+ }
1096+
1097+ let mut timeout = timeout. map( into_timespec) ;
1098+ let timeout_ptr = timeout
1099+ . as_mut( )
1100+ . map( |t| t as * mut _)
1101+ . unwrap_or( ptr:: null_mut( ) ) ;
1102+
1103+ syscall!( recvmmsg(
1104+ fd,
1105+ // SAFETY: `MMsgHdrMut` is `#[repr(transparent)]` and wraps a `libc::mmsghdr`
1106+ msgvec. as_mut_ptr( ) as * mut mmsghdr,
1107+ msgvec. len( ) as _,
1108+ flags as _,
1109+ timeout_ptr
1110+ ) )
1111+ . map( |n| n as usize )
1112+ }
1113+ }
1114+
10791115pub ( crate ) fn send ( fd : Socket , buf : & [ u8 ] , flags : c_int ) -> io:: Result < usize > {
10801116 syscall ! ( send(
10811117 fd,
@@ -1120,6 +1156,27 @@ pub(crate) fn sendmsg(fd: Socket, msg: &MsgHdr<'_, '_, '_>, flags: c_int) -> io:
11201156 syscall ! ( sendmsg( fd, & msg. inner, flags) ) . map ( |n| n as usize )
11211157}
11221158
1159+ define_mmsg_if_supported ! {
1160+ pub ( crate ) fn sendmmsg(
1161+ fd: Socket ,
1162+ msgvec: & mut [ MMsgHdr <' _, ' _, ' _>] ,
1163+ flags: c_int,
1164+ ) -> io:: Result <usize > {
1165+ if cfg!( target_env = "musl" ) {
1166+ debug_assert!( flags >= 0 , "socket flags must be non-negative" ) ;
1167+ }
1168+
1169+ syscall!( sendmmsg(
1170+ fd,
1171+ // SAFETY: `MMsgHdr` is `#[repr(transparent)]` and wraps a `libc::mmsghdr`
1172+ msgvec. as_mut_ptr( ) as * mut mmsghdr,
1173+ msgvec. len( ) as _,
1174+ flags as _
1175+ ) )
1176+ . map( |n| n as usize )
1177+ }
1178+ }
1179+
11231180/// Wrapper around `getsockopt` to deal with platform specific timeouts.
11241181pub ( crate ) fn timeout_opt ( fd : Socket , opt : c_int , val : c_int ) -> io:: Result < Option < Duration > > {
11251182 unsafe { getsockopt ( fd, opt, val) . map ( from_timeval) }
@@ -1161,6 +1218,27 @@ fn into_timeval(duration: Option<Duration>) -> libc::timeval {
11611218 }
11621219}
11631220
1221+ define_mmsg_if_supported ! {
1222+ fn into_timespec( duration: Duration ) -> libc:: timespec {
1223+ // https://github.com/rust-lang/libc/issues/1848
1224+ #[ cfg_attr( target_env = "musl" , allow( deprecated) ) ]
1225+ libc:: timespec {
1226+ tv_sec: min( duration. as_secs( ) , libc:: time_t:: MAX as u64 ) as libc:: time_t,
1227+ #[ cfg( any(
1228+ all( target_arch = "x86_64" , target_pointer_width = "32" ) ,
1229+ target_pointer_width = "64"
1230+ ) ) ]
1231+ tv_nsec: duration. subsec_nanos( ) as i64 ,
1232+
1233+ #[ cfg( not( any(
1234+ all( target_arch = "x86_64" , target_pointer_width = "32" ) ,
1235+ target_pointer_width = "64"
1236+ ) ) ) ]
1237+ tv_nsec: duration. subsec_nanos( ) . clamp( 0 , i32 :: MAX as u32 ) as i32 ,
1238+ }
1239+ }
1240+ }
1241+
11641242#[ cfg( all(
11651243 feature = "all" ,
11661244 not( any( target_os = "haiku" , target_os = "openbsd" , target_os = "vita" ) )
0 commit comments