Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Socket::{send,recv}msg and MsgHdr(Mut) #447

Merged
merged 10 commits into from
Jun 8, 2023
Prev Previous commit
Next Next commit
Use MsgHdrMut in recvmsg
  • Loading branch information
Thomasdezeeuw committed Jun 3, 2023
commit 5ed3b0f64d964f531549eae1dabcaff878e47bc5
4 changes: 2 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -605,7 +605,7 @@ impl<'addr, 'bufs, 'control> MsgHdr<'addr, 'bufs, 'control> {
///
/// Corresponds to setting `msg_iov` and `msg_iovlen` on Unix and `lpBuffers`
/// and `dwBufferCount` on Windows.
pub fn with_buffers(mut self, bufs: &'bufs [IoSlice<'bufs>]) -> Self {
pub fn with_buffers(mut self, bufs: &'bufs [IoSlice<'_>]) -> Self {
let ptr = bufs.as_ptr().cast_mut().cast();
sys::set_msghdr_iov(&mut self.inner, ptr, bufs.len());
self
Expand Down Expand Up @@ -677,7 +677,7 @@ impl<'addr, 'bufs, 'control> MsgHdrMut<'addr, 'bufs, 'control> {
///
/// Corresponds to setting `msg_iov` and `msg_iovlen` on Unix and `lpBuffers`
/// and `dwBufferCount` on Windows.
pub fn with_buffers(mut self, bufs: &'bufs mut [MaybeUninitSlice<'bufs>]) -> Self {
pub fn with_buffers(mut self, bufs: &'bufs mut [MaybeUninitSlice<'_>]) -> Self {
sys::set_msghdr_iov(&mut self.inner, bufs.as_mut_ptr().cast(), bufs.len());
self
}
Expand Down
51 changes: 18 additions & 33 deletions src/sys/unix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ use libc::{in6_addr, in_addr};

use crate::{Domain, Protocol, SockAddr, TcpKeepalive, Type};
#[cfg(not(target_os = "redox"))]
use crate::{MsgHdr, RecvFlags};
use crate::{MsgHdr, MsgHdrMut, RecvFlags};

pub(crate) use libc::c_int;

Expand Down Expand Up @@ -982,7 +982,9 @@ pub(crate) fn recv_vectored(
bufs: &mut [crate::MaybeUninitSlice<'_>],
flags: c_int,
) -> io::Result<(usize, RecvFlags)> {
recvmsg(fd, ptr::null_mut(), bufs, flags).map(|(n, _, recv_flags)| (n, recv_flags))
let mut msg = MsgHdrMut::new().with_buffers(bufs);
let n = recvmsg(fd, &mut msg, flags)?;
Ok((n, msg.flags()))
}

#[cfg(not(target_os = "redox"))]
Expand All @@ -991,42 +993,25 @@ pub(crate) fn recv_from_vectored(
bufs: &mut [crate::MaybeUninitSlice<'_>],
flags: c_int,
) -> io::Result<(usize, RecvFlags, SockAddr)> {
// Safety: `recvmsg` initialises the address storage and we set the length
let mut msg = MsgHdrMut::new().with_buffers(bufs);
// SAFETY: `recvmsg` initialises the address storage and we set the length
// manually.
unsafe {
let (n, addr) = unsafe {
SockAddr::try_init(|storage, len| {
recvmsg(fd, storage, bufs, flags).map(|(n, addrlen, recv_flags)| {
// Set the correct address length.
*len = addrlen;
(n, recv_flags)
})
})
}
.map(|((n, recv_flags), addr)| (n, recv_flags, addr))
msg.inner.msg_name = storage.cast();
msg.inner.msg_namelen = *len;
let n = recvmsg(fd, &mut msg, flags)?;
// Set the correct address length.
*len = msg.inner.msg_namelen;
Ok(n)
})?
};
Ok((n, msg.flags(), addr))
}

/// Returns the (bytes received, sending address len, `RecvFlags`).
#[cfg(not(target_os = "redox"))]
#[allow(clippy::unnecessary_cast)] // For `IovLen::MAX as usize` (Already `usize` on Linux).
fn recvmsg(
fd: Socket,
msg_name: *mut sockaddr_storage,
bufs: &mut [crate::MaybeUninitSlice<'_>],
flags: c_int,
) -> io::Result<(usize, libc::socklen_t, RecvFlags)> {
let msg_namelen = if msg_name.is_null() {
0
} else {
size_of::<sockaddr_storage>() as libc::socklen_t
};
// libc::msghdr contains unexported padding fields on Fuchsia.
let mut msg: libc::msghdr = unsafe { mem::zeroed() };
msg.msg_name = msg_name.cast();
msg.msg_namelen = msg_namelen;
msg.msg_iov = bufs.as_mut_ptr().cast();
msg.msg_iovlen = min(bufs.len(), IovLen::MAX as usize) as IovLen;
syscall!(recvmsg(fd, &mut msg, flags))
.map(|n| (n as usize, msg.msg_namelen, RecvFlags(msg.msg_flags)))
fn recvmsg(fd: Socket, msg: &mut MsgHdrMut<'_, '_, '_>, flags: c_int) -> io::Result<usize> {
syscall!(recvmsg(fd, &mut msg.inner, flags)).map(|n| n as usize)
}

pub(crate) fn send(fd: Socket, buf: &[u8], flags: c_int) -> io::Result<usize> {
Expand Down