From 1b0dba6772cf0ac7993f1bb222bfb0abaa0a1635 Mon Sep 17 00:00:00 2001 From: Michael Baikov Date: Sun, 9 Feb 2025 18:20:35 -0500 Subject: [PATCH 1/2] Unrelated change for formatting (CI doesn't check the formatting) --- src/sys/socket/mod.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/sys/socket/mod.rs b/src/sys/socket/mod.rs index e26e327d78..78a759fb90 100644 --- a/src/sys/socket/mod.rs +++ b/src/sys/socket/mod.rs @@ -257,8 +257,11 @@ impl SockProtocol { #[cfg(linux_android)] #[allow(non_upper_case_globals)] #[cfg(target_endian = "little")] - pub const EthIp: SockProtocol = unsafe { std::mem::transmute::((libc::ETH_P_IP as u16).to_be() as i32) }; - + pub const EthIp: SockProtocol = unsafe { + std::mem::transmute::( + (libc::ETH_P_IP as u16).to_be() as i32, + ) + }; } #[cfg(linux_android)] libc_bitflags! { From 52c049fe14ec725ec70761cf640acff6262c56d7 Mon Sep 17 00:00:00 2001 From: Michael Baikov Date: Sun, 9 Feb 2025 18:21:53 -0500 Subject: [PATCH 2/2] For recvmmsg split lifetime 'a into separate lifetimes for 'data, headers ('hdr) and related iterator --- src/sys/socket/mod.rs | 23 +++++++++++++---------- test/sys/test_socket.rs | 40 +++++++++++++++++++++++----------------- 2 files changed, 36 insertions(+), 27 deletions(-) diff --git a/src/sys/socket/mod.rs b/src/sys/socket/mod.rs index 78a759fb90..966840cb51 100644 --- a/src/sys/socket/mod.rs +++ b/src/sys/socket/mod.rs @@ -1765,7 +1765,7 @@ pub fn sendmmsg<'a, XS, AS, C, I, S>( // shared across all the messages cmsgs: C, flags: MsgFlags -) -> crate::Result> +) -> crate::Result> where XS: IntoIterator, AS: AsRef<[Option]>, @@ -1820,6 +1820,7 @@ pub fn sendmmsg<'a, XS, AS, C, I, S>( Ok(MultiResults { rmm: data, current_index: 0, + slices: std::marker::PhantomData, received: sent }) @@ -1908,16 +1909,16 @@ impl MultiHeaders { // always produce the desired results - see https://github.com/nix-rust/nix/pull/1744 for more // details #[cfg(any(linux_android, target_os = "freebsd", target_os = "netbsd"))] -pub fn recvmmsg<'a, XS, S, I>( +pub fn recvmmsg<'hdr, 'iter, 'data, XS, S, I>( fd: RawFd, - data: &'a mut MultiHeaders, + data: &'hdr mut MultiHeaders, slices: XS, flags: MsgFlags, mut timeout: Option, -) -> crate::Result> +) -> crate::Result> where - XS: IntoIterator, - I: AsMut<[IoSliceMut<'a>]> + 'a, + XS: IntoIterator, + I: AsMut<[IoSliceMut<'data>]> + 'iter, { let mut count = 0; for (i, (slice, mmsghdr)) in slices.into_iter().zip(data.items.iter_mut()).enumerate() { @@ -1949,6 +1950,7 @@ where })? as usize; Ok(MultiResults { + slices: std::marker::PhantomData, rmm: data, current_index: 0, received, @@ -1958,19 +1960,20 @@ where /// Iterator over results of [`recvmmsg`]/[`sendmmsg`] #[cfg(any(linux_android, target_os = "freebsd", target_os = "netbsd"))] #[derive(Debug)] -pub struct MultiResults<'a, S> { +pub struct MultiResults<'hdrs, 'data, S> { // preallocated structures - rmm: &'a MultiHeaders, + rmm: &'hdrs MultiHeaders, + slices: std::marker::PhantomData<&'data ()>, current_index: usize, received: usize, } #[cfg(any(linux_android, target_os = "freebsd", target_os = "netbsd"))] -impl<'a, S> Iterator for MultiResults<'a, S> +impl<'hdrs, 'data, S> Iterator for MultiResults<'hdrs, 'data, S> where S: Copy + SockaddrLike, { - type Item = RecvMsg<'a, 'a, S>; + type Item = RecvMsg<'hdrs, 'data, S>; // The cast is not unnecessary on all platforms. #[allow(clippy::unnecessary_cast)] diff --git a/test/sys/test_socket.rs b/test/sys/test_socket.rs index 5a43aab437..1605f81757 100644 --- a/test/sys/test_socket.rs +++ b/test/sys/test_socket.rs @@ -646,8 +646,9 @@ mod recvfrom { ) .expect("send socket failed"); + const LOOPS: usize = 3; let send_thread = thread::spawn(move || { - for _ in 0..NUM_MESSAGES_SENT { + for _ in 0..NUM_MESSAGES_SENT * LOOPS { sendto( ssock.as_raw_fd(), &DATA[..], @@ -671,24 +672,29 @@ mod recvfrom { let mut data = MultiHeaders::::preallocate(msgs.len(), None); - let res: Vec> = recvmmsg( - rsock.as_raw_fd(), - &mut data, - msgs.iter_mut(), - MsgFlags::empty(), - None, - ) - .expect("recvmmsg") - .collect(); - assert_eq!(res.len(), DATA.len()); + for _ in 0..LOOPS { + let res: Vec> = recvmmsg( + rsock.as_raw_fd(), + &mut data, + msgs.iter_mut(), + MsgFlags::empty(), + None, + ) + .expect("recvmmsg") + .collect(); + assert_eq!(res.len(), DATA.len()); - for RecvMsg { address, bytes, .. } in res.into_iter() { - assert_eq!(AddressFamily::Inet, address.unwrap().family().unwrap()); - assert_eq!(DATA.len(), bytes); - } + for RecvMsg { address, bytes, .. } in res.into_iter() { + assert_eq!( + AddressFamily::Inet, + address.unwrap().family().unwrap() + ); + assert_eq!(DATA.len(), bytes); + } - for buf in &receive_buffers { - assert_eq!(&buf[..DATA.len()], DATA); + for buf in msgs.iter().flatten() { + assert_eq!(&buf[..DATA.len()], DATA); + } } send_thread.join().unwrap();