Skip to content

Commit 1cdebf6

Browse files
author
Gleb Pomykalov
committed
Expect ExactSizeIterator on sendmmsg/recvmmsg and simplify unsafe code.
1 parent 77421b1 commit 1cdebf6

File tree

1 file changed

+39
-45
lines changed

1 file changed

+39
-45
lines changed

src/sys/socket/mod.rs

Lines changed: 39 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@ pub use libc::{
5050
// Needed by the cmsg_space macro
5151
#[doc(hidden)]
5252
pub use libc::{c_uint, CMSG_SPACE};
53-
use std::mem::MaybeUninit;
5453

5554
/// These constants are used to specify the communication semantics
5655
/// when creating a socket with [`socket()`](fn.socket.html)
@@ -783,7 +782,7 @@ pub fn sendmsg(fd: RawFd, iov: &[IoVec<&[u8]>], cmsgs: &[ControlMessage],
783782
// because subsequent code will not clear the padding bytes.
784783
let mut cmsg_buffer = vec![0u8; capacity];
785784

786-
pack_mhdr(mhdr.as_mut_ptr(), &mut cmsg_buffer[..], &iov, &cmsgs, addr);
785+
pack_mhdr_to_send(mhdr.as_mut_ptr(), &mut cmsg_buffer[..], &iov, &cmsgs, addr);
787786

788787
let mhdr = unsafe { mhdr.assume_init() };
789788

@@ -837,7 +836,8 @@ pub struct SendMmsgData<'a, I, C>
837836
))]
838837
pub fn sendmmsg<'a, I, C>(
839838
fd: RawFd,
840-
data: impl std::iter::IntoIterator<Item=&'a SendMmsgData<'a, I, C>>,
839+
data: impl std::iter::IntoIterator<Item=&'a SendMmsgData<'a, I, C>,
840+
IntoIter=impl ExactSizeIterator + Iterator<Item=&'a SendMmsgData<'a, I, C>>>,
841841
flags: MsgFlags
842842
) -> Result<Vec<usize>>
843843
where
@@ -846,34 +846,30 @@ pub fn sendmmsg<'a, I, C>(
846846
{
847847
let iter = data.into_iter();
848848

849-
let (min_size, max_size) = iter.size_hint();
850-
let reserve_items = max_size.unwrap_or(min_size);
849+
let num_messages = iter.len();
851850

852-
let mut output: Vec<MaybeUninit<libc::mmsghdr>> = vec![MaybeUninit::zeroed(); reserve_items];
851+
let mut output = Vec::<libc::mmsghdr>::with_capacity(num_messages);
852+
unsafe {
853+
output.set_len(num_messages);
854+
}
853855

854856
let mut cmsgs_buffer = vec![0u8; 0];
855857

856858
iter.enumerate().for_each(|(i, d)| {
857-
if output.len() < i {
858-
output.resize(i, MaybeUninit::zeroed());
859-
}
860-
861859
let element = &mut output[i];
862860

863861
let cmsgs_start = cmsgs_buffer.len();
864862
let cmsgs_required_capacity: usize = d.cmsgs.as_ref().iter().map(|c| c.space()).sum();
865863
let cmsgs_buffer_need_capacity = cmsgs_start + cmsgs_required_capacity;
866864
cmsgs_buffer.resize(cmsgs_buffer_need_capacity, 0);
867865

868-
unsafe {
869-
pack_mhdr(
870-
&mut (*element.as_mut_ptr()).msg_hdr,
871-
&mut cmsgs_buffer[cmsgs_start..],
872-
&d.iov,
873-
&d.cmsgs,
874-
d.addr.as_ref()
875-
)
876-
};
866+
pack_mhdr_to_send(
867+
&mut element.msg_hdr,
868+
&mut cmsgs_buffer[cmsgs_start..],
869+
&d.iov,
870+
&d.cmsgs,
871+
d.addr.as_ref()
872+
);
877873
});
878874

879875
let mut initialized_data = unsafe { mem::transmute::<_, Vec<libc::mmsghdr>>(output) };
@@ -941,7 +937,8 @@ pub struct RecvMmsgData<'a, I>
941937
))]
942938
pub fn recvmmsg<'a, I>(
943939
fd: RawFd,
944-
data: impl std::iter::IntoIterator<Item=&'a mut RecvMmsgData<'a, I>>,
940+
data: impl std::iter::IntoIterator<Item=&'a mut RecvMmsgData<'a, I>,
941+
IntoIter=impl ExactSizeIterator + Iterator<Item=&'a mut RecvMmsgData<'a, I>>>,
945942
flags: MsgFlags,
946943
timeout: Option<crate::sys::time::TimeSpec>
947944
) -> Result<Vec<RecvMsg<'a>>>
@@ -950,23 +947,22 @@ pub fn recvmmsg<'a, I>(
950947
{
951948
let iter = data.into_iter();
952949

953-
let (min_size, max_size) = iter.size_hint();
954-
let reserve_items = max_size.unwrap_or(min_size);
950+
let num_messages = iter.len();
955951

956-
let mut output: Vec<MaybeUninit<libc::mmsghdr>> = vec![MaybeUninit::zeroed(); reserve_items];
957-
let mut address: Vec<MaybeUninit<sockaddr_storage>> = vec![MaybeUninit::uninit(); reserve_items];
952+
let mut output: Vec<libc::mmsghdr> = Vec::with_capacity(num_messages);
953+
let mut address: Vec<sockaddr_storage> = Vec::with_capacity(num_messages);
958954

959-
let results: Vec<_> = iter.enumerate().map(|(i, d)| {
960-
if output.len() < i {
961-
output.resize(i, MaybeUninit::zeroed());
962-
address.resize(i, MaybeUninit::uninit());
963-
}
955+
unsafe {
956+
output.set_len(num_messages);
957+
address.set_len(num_messages);
958+
}
964959

960+
let results: Vec<_> = iter.enumerate().map(|(i, d)| {
965961
let element = &mut output[i];
966962

967963
let msg_controllen = unsafe {
968-
recv_pack_mhdr(
969-
&mut (*element.as_mut_ptr()).msg_hdr,
964+
pack_mhdr_to_receive(
965+
&mut element.msg_hdr,
970966
d.iov.as_ref(),
971967
&mut d.cmsg_buffer,
972968
&mut address[i]
@@ -976,29 +972,27 @@ pub fn recvmmsg<'a, I>(
976972
(msg_controllen as usize, &mut d.cmsg_buffer)
977973
}).collect();
978974

979-
let mut initialized_data = unsafe { mem::transmute::<_, Vec<libc::mmsghdr>>(output) };
980-
981975
let timeout = if let Some(mut t) = timeout {
982976
t.as_mut() as *mut libc::timespec
983977
} else {
984978
ptr::null_mut()
985979
};
986980

987-
let ret = unsafe { libc::recvmmsg(fd, initialized_data.as_mut_ptr(), initialized_data.len() as _, flags.bits() as _, timeout) };
981+
let ret = unsafe { libc::recvmmsg(fd, output.as_mut_ptr(), output.len() as _, flags.bits() as _, timeout) };
988982

989983
let r = Errno::result(ret)?;
990984

991-
Ok(initialized_data
985+
Ok(output
992986
.into_iter()
993987
.zip(address.into_iter())
994988
.zip(results.into_iter())
995-
.map(|((mmsghdr, address), (msg_controllen, cmsg_buffer))| {
989+
.map(|((mmsghdr, mut address), (msg_controllen, cmsg_buffer))| {
996990
unsafe {
997991
read_mhdr(
998992
mmsghdr.msg_hdr,
999993
r as isize,
1000994
msg_controllen,
1001-
address,
995+
&mut address,
1002996
cmsg_buffer
1003997
)
1004998
}
@@ -1010,7 +1004,7 @@ unsafe fn read_mhdr<'a, 'b>(
10101004
mhdr: msghdr,
10111005
r: isize,
10121006
msg_controllen: usize,
1013-
address: MaybeUninit<sockaddr_storage>,
1007+
address: *mut sockaddr_storage,
10141008
cmsg_buffer: &'a mut Option<&'b mut Vec<u8>>
10151009
) -> RecvMsg<'b> {
10161010
let cmsghdr = {
@@ -1029,7 +1023,7 @@ unsafe fn read_mhdr<'a, 'b>(
10291023
};
10301024

10311025
let address = sockaddr_storage_to_addr(
1032-
&address.assume_init(),
1026+
&*address ,
10331027
mhdr.msg_namelen as usize
10341028
).ok();
10351029

@@ -1042,11 +1036,11 @@ unsafe fn read_mhdr<'a, 'b>(
10421036
}
10431037
}
10441038

1045-
unsafe fn recv_pack_mhdr<'a, I>(
1039+
unsafe fn pack_mhdr_to_receive<'a, I>(
10461040
out: *mut msghdr,
10471041
iov: I,
10481042
cmsg_buffer: &mut Option<&mut Vec<u8>>,
1049-
address: &mut mem::MaybeUninit<sockaddr_storage>
1043+
address: *mut sockaddr_storage,
10501044
) -> usize
10511045
where
10521046
I: AsRef<[IoVec<&'a mut [u8]>]> + 'a,
@@ -1055,7 +1049,7 @@ unsafe fn recv_pack_mhdr<'a, I>(
10551049
.map(|v| (v.as_mut_ptr(), v.capacity()))
10561050
.unwrap_or((ptr::null_mut(), 0));
10571051

1058-
(*out).msg_name = address.as_mut_ptr() as *mut c_void;
1052+
(*out).msg_name = address as *mut c_void;
10591053
(*out).msg_namelen = mem::size_of::<sockaddr_storage>() as socklen_t;
10601054
(*out).msg_iov = iov.as_ref().as_ptr() as *mut iovec;
10611055
(*out).msg_iovlen = iov.as_ref().len() as _;
@@ -1067,7 +1061,7 @@ unsafe fn recv_pack_mhdr<'a, I>(
10671061
}
10681062

10691063

1070-
fn pack_mhdr<'a, I, C>(
1064+
fn pack_mhdr_to_send<'a, I, C>(
10711065
out: *mut msghdr,
10721066
cmsg_buffer: &mut [u8],
10731067
iov: I,
@@ -1146,7 +1140,7 @@ pub fn recvmsg<'a>(fd: RawFd, iov: &[IoVec<&mut [u8]>],
11461140
let mut address = mem::MaybeUninit::uninit();
11471141

11481142
let msg_controllen = unsafe {
1149-
recv_pack_mhdr(out.as_mut_ptr(), &iov, &mut cmsg_buffer, &mut address)
1143+
pack_mhdr_to_receive(out.as_mut_ptr(), &iov, &mut cmsg_buffer, address.as_mut_ptr())
11501144
};
11511145

11521146
let mut mhdr = unsafe { out.assume_init() };
@@ -1155,7 +1149,7 @@ pub fn recvmsg<'a>(fd: RawFd, iov: &[IoVec<&mut [u8]>],
11551149

11561150
let r = Errno::result(ret)?;
11571151

1158-
Ok(unsafe { read_mhdr(mhdr, r, msg_controllen, address, &mut cmsg_buffer) })
1152+
Ok(unsafe { read_mhdr(mhdr, r, msg_controllen, address.as_mut_ptr(), &mut cmsg_buffer) })
11591153
}
11601154

11611155

0 commit comments

Comments
 (0)