Skip to content

Commit 51377a0

Browse files
committed
Add MsgHdr type
This wraps msghdr on Unix and WSAMSG on Windows to be used in send/recvmsg calls.
1 parent 5ca3960 commit 51377a0

File tree

3 files changed

+149
-0
lines changed

3 files changed

+149
-0
lines changed

src/lib.rs

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,12 @@
5959
#![doc(test(attr(deny(warnings))))]
6060

6161
use std::fmt;
62+
#[cfg(not(target_os = "redox"))]
63+
use std::io::IoSlice;
64+
#[cfg(not(target_os = "redox"))]
65+
use std::marker::PhantomData;
66+
#[cfg(not(target_os = "redox"))]
67+
use std::mem;
6268
use std::mem::MaybeUninit;
6369
use std::net::SocketAddr;
6470
use std::ops::{Deref, DerefMut};
@@ -562,3 +568,97 @@ impl TcpKeepalive {
562568
}
563569
}
564570
}
571+
572+
/// Configuration of a `{send,recv}msg` system call.
573+
///
574+
/// This wraps `msghdr` on Unix and `WSAMSG` on Windows.
575+
#[cfg(not(target_os = "redox"))]
576+
pub struct MsgHdr<'addr, 'bufs, 'control> {
577+
inner: sys::msghdr,
578+
#[allow(clippy::type_complexity)]
579+
_lifetimes: PhantomData<(&'addr SockAddr, &'bufs [&'bufs [u8]], &'control [u8])>,
580+
}
581+
582+
#[cfg(not(target_os = "redox"))]
583+
impl<'addr, 'bufs, 'control> MsgHdr<'addr, 'bufs, 'control> {
584+
/// Create a new `MsgHdr` with all empty/zero fields.
585+
#[allow(clippy::new_without_default)]
586+
pub fn new() -> MsgHdr<'addr, 'bufs, 'control> {
587+
// SAFETY: all zero is valid for `msghdr` and `WSAMSG`.
588+
MsgHdr {
589+
inner: unsafe { mem::zeroed() },
590+
_lifetimes: PhantomData,
591+
}
592+
}
593+
594+
/// Set the address (name) of the message.
595+
///
596+
/// Corresponds to setting `msg_name` and `msg_namelen` on Unix and `name`
597+
/// and `namelen` on Windows.
598+
pub fn with_addr(mut self, addr: &'addr SockAddr) -> Self {
599+
sys::set_msghdr_name(&mut self.inner, addr);
600+
self
601+
}
602+
603+
/// Set the mutable address (name) of the message. Same as [`with_addr`],
604+
/// but with a mutable address.
605+
///
606+
/// [`with_addr`]: MsgHdr::with_addr
607+
pub fn with_addr_mut(mut self, addr: &'addr mut SockAddr) -> Self {
608+
sys::set_msghdr_name(&mut self.inner, addr);
609+
self
610+
}
611+
612+
/// Set the buffer(s) of the message.
613+
///
614+
/// Corresponds to setting `msg_iov` and `msg_iovlen` on Unix and `lpBuffers`
615+
/// and `dwBufferCount` on Windows.
616+
pub fn with_buffers(mut self, bufs: &'bufs [IoSlice<'bufs>]) -> Self {
617+
let ptr = bufs.as_ptr().cast_mut().cast();
618+
sys::set_msghdr_iov(&mut self.inner, ptr, bufs.len());
619+
self
620+
}
621+
622+
/// Set the mutable buffer(s) of the message. Same as [`with_buffers`], but
623+
/// with mutable buffers.
624+
///
625+
/// [`with_buffers`]: MsgHdr::with_buffers
626+
pub fn with_buffers_mut(mut self, bufs: &'bufs mut [MaybeUninitSlice<'bufs>]) -> Self {
627+
sys::set_msghdr_iov(&mut self.inner, bufs.as_mut_ptr().cast(), bufs.len());
628+
self
629+
}
630+
631+
/// Set the control buffer of the message.
632+
///
633+
/// Corresponds to setting `msg_control` and `msg_controllen` on Unix and
634+
/// `Control` on Windows.
635+
pub fn with_control(mut self, buf: &'control [u8]) -> Self {
636+
let ptr = buf.as_ptr().cast_mut().cast();
637+
sys::set_msghdr_control(&mut self.inner, ptr, buf.len());
638+
self
639+
}
640+
641+
/// Set the mutable control buffer of the message. Same as [`with_control`],
642+
/// but with a mutable buffers.
643+
///
644+
/// [`with_control`]: MsgHdr::with_control
645+
pub fn with_control_mut(mut self, buf: &'control mut [u8]) -> Self {
646+
sys::set_msghdr_control(&mut self.inner, buf.as_mut_ptr().cast(), buf.len());
647+
self
648+
}
649+
650+
/// Set the flags of the message.
651+
///
652+
/// Corresponds to setting `msg_flags` on Unix and `dwFlags` on Windows.
653+
pub fn with_flags(mut self, flags: sys::c_int) -> Self {
654+
sys::set_msghdr_flags(&mut self.inner, flags);
655+
self
656+
}
657+
}
658+
659+
#[cfg(not(target_os = "redox"))]
660+
impl<'name, 'bufs, 'control> fmt::Debug for MsgHdr<'name, 'bufs, 'control> {
661+
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
662+
"MsgHdr".fmt(fmt)
663+
}
664+
}

src/sys/unix.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -642,6 +642,33 @@ pub(crate) fn unix_sockaddr(path: &Path) -> io::Result<SockAddr> {
642642
Ok(unsafe { SockAddr::new(storage, len as socklen_t) })
643643
}
644644

645+
// Used in `MsgHdr`.
646+
#[cfg(not(target_os = "redox"))]
647+
pub(crate) use libc::msghdr;
648+
649+
#[cfg(not(target_os = "redox"))]
650+
pub(crate) fn set_msghdr_name(msg: &mut msghdr, name: &SockAddr) {
651+
msg.msg_name = name.as_ptr().cast_mut().cast();
652+
msg.msg_namelen = name.len();
653+
}
654+
655+
#[cfg(not(target_os = "redox"))]
656+
pub(crate) fn set_msghdr_iov(msg: &mut msghdr, ptr: *mut libc::iovec, len: usize) {
657+
msg.msg_iov = ptr;
658+
msg.msg_iovlen = len as _;
659+
}
660+
661+
#[cfg(not(target_os = "redox"))]
662+
pub(crate) fn set_msghdr_control(msg: &mut msghdr, ptr: *mut libc::c_void, len: usize) {
663+
msg.msg_control = ptr;
664+
msg.msg_controllen = len as _;
665+
}
666+
667+
#[cfg(not(target_os = "redox"))]
668+
pub(crate) fn set_msghdr_flags(msg: &mut msghdr, flags: libc::c_int) {
669+
msg.msg_flags = flags;
670+
}
671+
645672
/// Unix only API.
646673
impl SockAddr {
647674
/// Constructs a `SockAddr` with the family `AF_VSOCK` and the provided CID/port.

src/sys/windows.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,28 @@ impl<'a> MaybeUninitSlice<'a> {
187187
}
188188
}
189189

190+
// Used in `MsgHdr`.
191+
pub(crate) use windows_sys::Win32::Networking::WinSock::WSAMSG as msghdr;
192+
193+
pub(crate) fn set_msghdr_name(msg: &mut msghdr, name: &SockAddr) {
194+
msg.name = name.as_ptr().cast_mut().cast();
195+
msg.namelen = name.len();
196+
}
197+
198+
pub(crate) fn set_msghdr_iov(msg: &mut msghdr, ptr: *mut WSABUF, len: usize) {
199+
msg.lpBuffers = ptr;
200+
msg.dwBufferCount = len as _;
201+
}
202+
203+
pub(crate) fn set_msghdr_control(msg: &mut msghdr, ptr: *mut u8, len: usize) {
204+
msg.Control.buf = ptr;
205+
msg.Control.len = len as u32;
206+
}
207+
208+
pub(crate) fn set_msghdr_flags(msg: &mut msghdr, flags: c_int) {
209+
msg.dwFlags = flags as u32;
210+
}
211+
190212
fn init() {
191213
static INIT: Once = Once::new();
192214

0 commit comments

Comments
 (0)