//! Utilities for dealing with message headers. //! //! These take closures rather than returning a `c::msghdr` directly because //! the message headers may reference stack-local data.
/// Create a message header intended to receive a datagram. /// /// # Safety /// /// If `f` dereferences the pointers in the `msghdr`, it must do so only within /// the bounds indicated by the associated lengths in the `msghdr`. /// /// And, if `f` returns `Ok`, it must have updated the `msg_controllen` field /// of the `msghdr` to indicate how many bytes it initialized. pub(crate) unsafefn with_recv_msghdr<R>(
name: &mut SocketAddrBuf,
iov: &mut [IoSliceMut<'_>],
control: &mut RecvAncillaryBuffer<'_>,
f: impl FnOnce(&mut c::msghdr) -> io::Result<R>,
) -> io::Result<R> {
control.clear();
// Reset the control length. if res.is_ok() { // SAFETY: `f` returned `Ok`, so our safety condition requires `f` to // have initialized `msg_controllen` bytes.
control.set_control_len(msghdr.msg_controllen as usize);
}
name.len = msghdr.msg_namelen;
res
}
/// Create a message header intended to send without an address. /// /// The returned `msghdr` will contain raw pointers to the memory /// referenced by `iov` and `control`. pub(crate) fn noaddr_msghdr(
iov: &[IoSlice<'_>],
control: &mut SendAncillaryBuffer<'_, '_, '_>,
) -> c::msghdr { letmut h = zero_msghdr();
h.msg_iov = iov.as_ptr() as _;
h.msg_iovlen = msg_iov_len(iov.len());
h.msg_control = control.as_control_ptr().cast();
h.msg_controllen = msg_control_len(control.control_len());
h
}
/// Create a message header intended to send with the specified address. /// /// This creates a `c::msghdr` and calls a function `f` on it. The `msghdr`'s /// raw pointers may point to temporaries, so this function should avoid /// storing the pointers anywhere that would outlive the function call. /// /// # Safety /// /// If `f` dereferences the pointers in the `msghdr`, it must do so only within /// the bounds indicated by the associated lengths in the `msghdr`. pub(crate) unsafefn with_msghdr<R>(
addr: &impl SocketAddrArg,
iov: &[IoSlice<'_>],
control: &mut SendAncillaryBuffer<'_, '_, '_>,
f: impl FnOnce(&c::msghdr) -> R,
) -> R {
addr.with_sockaddr(|addr_ptr, addr_len| { letmut h = zero_msghdr();
h.msg_name = addr_ptr as *mut _;
h.msg_namelen = bitcast!(addr_len);
h.msg_iov = iov.as_ptr() as _;
h.msg_iovlen = msg_iov_len(iov.len());
h.msg_control = control.as_control_ptr().cast();
h.msg_controllen = msg_control_len(control.control_len()); // Pass a reference to the `c::msghdr` instead of passing it by value // because it may contain pointers to temporary objects that won't // live beyond the call to `with_sockaddr`.
f(&h)
})
}
/// Create a zero-initialized message header struct value. #[cfg(unix)] pub(crate) fn zero_msghdr() -> c::msghdr { // SAFETY: We can't initialize all the fields by value because on some // platforms the `msghdr` struct in the libc crate contains private padding // fields. But it is still a C type that's meant to be zero-initializable. unsafe { zeroed() }
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.