Skip to content

Commit 101a405

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

File tree

1 file changed

+42
-51
lines changed

1 file changed

+42
-51
lines changed

src/sys/socket/mod.rs

Lines changed: 42 additions & 51 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,46 +846,39 @@ 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

879-
let mut initialized_data = unsafe { mem::transmute::<_, Vec<libc::mmsghdr>>(output) };
880-
881-
let ret = unsafe { libc::sendmmsg(fd, initialized_data.as_mut_ptr(), initialized_data.len() as _, flags.bits() as _) };
875+
let ret = unsafe { libc::sendmmsg(fd, output.as_mut_ptr(), output.len() as _, flags.bits() as _) };
882876

883877
let sent_messages = Errno::result(ret)? as usize;
884878
let mut sent_bytes = Vec::with_capacity(sent_messages);
885-
unsafe { sent_bytes.set_len(sent_messages) };
886879

887-
for i in 0..sent_messages {
888-
sent_bytes[i] = initialized_data[i].msg_len as usize;
880+
for item in &output {
881+
sent_bytes.push(item.msg_len as usize);
889882
}
890883

891884
Ok(sent_bytes)
@@ -941,7 +934,8 @@ pub struct RecvMmsgData<'a, I>
941934
))]
942935
pub fn recvmmsg<'a, I>(
943936
fd: RawFd,
944-
data: impl std::iter::IntoIterator<Item=&'a mut RecvMmsgData<'a, I>>,
937+
data: impl std::iter::IntoIterator<Item=&'a mut RecvMmsgData<'a, I>,
938+
IntoIter=impl ExactSizeIterator + Iterator<Item=&'a mut RecvMmsgData<'a, I>>>,
945939
flags: MsgFlags,
946940
timeout: Option<crate::sys::time::TimeSpec>
947941
) -> Result<Vec<RecvMsg<'a>>>
@@ -950,23 +944,22 @@ pub fn recvmmsg<'a, I>(
950944
{
951945
let iter = data.into_iter();
952946

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

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];
949+
let mut output: Vec<libc::mmsghdr> = Vec::with_capacity(num_messages);
950+
let mut address: Vec<sockaddr_storage> = Vec::with_capacity(num_messages);
958951

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-
}
952+
unsafe {
953+
output.set_len(num_messages);
954+
address.set_len(num_messages);
955+
}
964956

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

967960
let msg_controllen = unsafe {
968-
recv_pack_mhdr(
969-
&mut (*element.as_mut_ptr()).msg_hdr,
961+
pack_mhdr_to_receive(
962+
&mut element.msg_hdr,
970963
d.iov.as_ref(),
971964
&mut d.cmsg_buffer,
972965
&mut address[i]
@@ -976,29 +969,27 @@ pub fn recvmmsg<'a, I>(
976969
(msg_controllen as usize, &mut d.cmsg_buffer)
977970
}).collect();
978971

979-
let mut initialized_data = unsafe { mem::transmute::<_, Vec<libc::mmsghdr>>(output) };
980-
981972
let timeout = if let Some(mut t) = timeout {
982973
t.as_mut() as *mut libc::timespec
983974
} else {
984975
ptr::null_mut()
985976
};
986977

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

989980
let r = Errno::result(ret)?;
990981

991-
Ok(initialized_data
982+
Ok(output
992983
.into_iter()
993984
.zip(address.into_iter())
994985
.zip(results.into_iter())
995-
.map(|((mmsghdr, address), (msg_controllen, cmsg_buffer))| {
986+
.map(|((mmsghdr, mut address), (msg_controllen, cmsg_buffer))| {
996987
unsafe {
997988
read_mhdr(
998989
mmsghdr.msg_hdr,
999990
r as isize,
1000991
msg_controllen,
1001-
address,
992+
&mut address,
1002993
cmsg_buffer
1003994
)
1004995
}
@@ -1010,7 +1001,7 @@ unsafe fn read_mhdr<'a, 'b>(
10101001
mhdr: msghdr,
10111002
r: isize,
10121003
msg_controllen: usize,
1013-
address: MaybeUninit<sockaddr_storage>,
1004+
address: *mut sockaddr_storage,
10141005
cmsg_buffer: &'a mut Option<&'b mut Vec<u8>>
10151006
) -> RecvMsg<'b> {
10161007
let cmsghdr = {
@@ -1029,7 +1020,7 @@ unsafe fn read_mhdr<'a, 'b>(
10291020
};
10301021

10311022
let address = sockaddr_storage_to_addr(
1032-
&address.assume_init(),
1023+
&*address ,
10331024
mhdr.msg_namelen as usize
10341025
).ok();
10351026

@@ -1042,11 +1033,11 @@ unsafe fn read_mhdr<'a, 'b>(
10421033
}
10431034
}
10441035

1045-
unsafe fn recv_pack_mhdr<'a, I>(
1036+
unsafe fn pack_mhdr_to_receive<'a, I>(
10461037
out: *mut msghdr,
10471038
iov: I,
10481039
cmsg_buffer: &mut Option<&mut Vec<u8>>,
1049-
address: &mut mem::MaybeUninit<sockaddr_storage>
1040+
address: *mut sockaddr_storage,
10501041
) -> usize
10511042
where
10521043
I: AsRef<[IoVec<&'a mut [u8]>]> + 'a,
@@ -1055,7 +1046,7 @@ unsafe fn recv_pack_mhdr<'a, I>(
10551046
.map(|v| (v.as_mut_ptr(), v.capacity()))
10561047
.unwrap_or((ptr::null_mut(), 0));
10571048

1058-
(*out).msg_name = address.as_mut_ptr() as *mut c_void;
1049+
(*out).msg_name = address as *mut c_void;
10591050
(*out).msg_namelen = mem::size_of::<sockaddr_storage>() as socklen_t;
10601051
(*out).msg_iov = iov.as_ref().as_ptr() as *mut iovec;
10611052
(*out).msg_iovlen = iov.as_ref().len() as _;
@@ -1067,7 +1058,7 @@ unsafe fn recv_pack_mhdr<'a, I>(
10671058
}
10681059

10691060

1070-
fn pack_mhdr<'a, I, C>(
1061+
fn pack_mhdr_to_send<'a, I, C>(
10711062
out: *mut msghdr,
10721063
cmsg_buffer: &mut [u8],
10731064
iov: I,
@@ -1146,7 +1137,7 @@ pub fn recvmsg<'a>(fd: RawFd, iov: &[IoVec<&mut [u8]>],
11461137
let mut address = mem::MaybeUninit::uninit();
11471138

11481139
let msg_controllen = unsafe {
1149-
recv_pack_mhdr(out.as_mut_ptr(), &iov, &mut cmsg_buffer, &mut address)
1140+
pack_mhdr_to_receive(out.as_mut_ptr(), &iov, &mut cmsg_buffer, address.as_mut_ptr())
11501141
};
11511142

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

11561147
let r = Errno::result(ret)?;
11571148

1158-
Ok(unsafe { read_mhdr(mhdr, r, msg_controllen, address, &mut cmsg_buffer) })
1149+
Ok(unsafe { read_mhdr(mhdr, r, msg_controllen, address.as_mut_ptr(), &mut cmsg_buffer) })
11591150
}
11601151

11611152

0 commit comments

Comments
 (0)