1 //! [`recvmsg`], [`sendmsg`], and related functions.
5 use crate::backend
::{self, c}
;
6 use crate::fd
::{AsFd, BorrowedFd, OwnedFd}
;
7 use crate::io
::{self, IoSlice, IoSliceMut}
;
11 use core
::iter
::FusedIterator
;
12 use core
::marker
::PhantomData
;
13 use core
::mem
::{align_of, size_of, size_of_val, take}
;
15 use core
::ptr
::addr_of
;
16 use core
::{ptr, slice}
;
18 use super::{RecvFlags, SendFlags, SocketAddrAny, SocketAddrV4, SocketAddrV6}
;
20 /// Macro for defining the amount of space to allocate in a buffer for use with
21 /// [`RecvAncillaryBuffer::new`] and [`SendAncillaryBuffer::new`].
25 /// Allocate a buffer for a single file descriptor:
27 /// # use rustix::cmsg_space;
28 /// let mut space = [0; rustix::cmsg_space!(ScmRights(1))];
31 /// Allocate a buffer for credentials:
33 /// # #[cfg(linux_kernel)]
35 /// # use rustix::cmsg_space;
36 /// let mut space = [0; rustix::cmsg_space!(ScmCredentials(1))];
40 /// Allocate a buffer for two file descriptors and credentials:
42 /// # #[cfg(linux_kernel)]
44 /// # use rustix::cmsg_space;
45 /// let mut space = [0; rustix::cmsg_space!(ScmRights(2), ScmCredentials(1))];
49 macro_rules
! cmsg_space
{
51 (ScmRights($len
:expr
)) => {
52 $
crate::net
::__cmsg_space(
53 $len
* ::core
::mem
::size_of
::<$
crate::fd
::BorrowedFd
<'
static>>(),
56 (ScmCredentials($len
:expr
)) => {
57 $
crate::net
::__cmsg_space(
58 $len
* ::core
::mem
::size_of
::<$
crate::net
::UCred
>(),
63 ($firstid
:ident($firstex
:expr
), $
($restid
:ident($restex
:expr
)),*) => {{
64 // We only have to add `cmsghdr` alignment once; all other times we can
65 // use `cmsg_aligned_space`.
66 let sum
= $
crate::cmsg_space
!($
firstid($firstex
));
68 let sum
= sum
+ $
crate::cmsg_aligned_space
!($
restid($restex
));
74 /// Like `cmsg_space`, but doesn't add padding for `cmsghdr` alignment.
77 macro_rules
! cmsg_aligned_space
{
79 (ScmRights($len
:expr
)) => {
80 $
crate::net
::__cmsg_aligned_space(
81 $len
* ::core
::mem
::size_of
::<$
crate::fd
::BorrowedFd
<'
static>>(),
84 (ScmCredentials($len
:expr
)) => {
85 $
crate::net
::__cmsg_aligned_space(
86 $len
* ::core
::mem
::size_of
::<$
crate::net
::UCred
>(),
91 ($firstid
:ident($firstex
:expr
), $
($restid
:ident($restex
:expr
)),*) => {{
92 let sum
= cmsg_aligned_space
!($
firstid($firstex
));
94 let sum
= sum
+ cmsg_aligned_space
!($
restid($restex
));
101 pub const fn __cmsg_space(len
: usize) -> usize {
102 // Add `align_of::<c::cmsghdr>()` so that we can align the user-provided
103 // `&[u8]` to the required alignment boundary.
104 let len
= len
+ align_of
::<c
::cmsghdr
>();
106 __cmsg_aligned_space(len
)
110 pub const fn __cmsg_aligned_space(len
: usize) -> usize {
111 // Convert `len` to `u32` for `CMSG_SPACE`. This would be `try_into()` if
112 // we could call that in a `const fn`.
113 let converted_len
= len
as u32;
114 if converted_len
as usize != len
{
115 unreachable
!(); // `CMSG_SPACE` size overflow
118 unsafe { c::CMSG_SPACE(converted_len) as usize }
121 /// Ancillary message for [`sendmsg`], [`sendmsg_v4`], [`sendmsg_v6`],
122 /// [`sendmsg_unix`], and [`sendmsg_any`].
124 pub enum SendAncillaryMessage
<'slice
, 'fd
> {
125 /// Send file descriptors.
126 #[doc(alias = "SCM_RIGHTS")]
127 ScmRights(&'slice
[BorrowedFd
<'fd
>]),
128 /// Send process credentials.
130 #[doc(alias = "SCM_CREDENTIAL")]
131 ScmCredentials(UCred
),
134 impl SendAncillaryMessage
<'_
, '_
> {
135 /// Get the maximum size of an ancillary message.
137 /// This can be helpful in determining the size of the buffer you allocate.
138 pub const fn size(&self) -> usize {
140 Self::ScmRights(slice
) => cmsg_space
!(ScmRights(slice
.len())),
142 Self::ScmCredentials(_
) => cmsg_space
!(ScmCredentials(1)),
147 /// Ancillary message for [`recvmsg`].
149 pub enum RecvAncillaryMessage
<'a
> {
150 /// Received file descriptors.
151 #[doc(alias = "SCM_RIGHTS")]
152 ScmRights(AncillaryIter
<'a
, OwnedFd
>),
153 /// Received process credentials.
155 #[doc(alias = "SCM_CREDENTIALS")]
156 ScmCredentials(UCred
),
159 /// Buffer for sending ancillary messages with [`sendmsg`], [`sendmsg_v4`],
160 /// [`sendmsg_v6`], [`sendmsg_unix`], and [`sendmsg_any`].
162 /// Use the [`push`] function to add messages to send.
164 /// [`push`]: SendAncillaryBuffer::push
165 pub struct SendAncillaryBuffer
<'buf
, 'slice
, 'fd
> {
166 /// Raw byte buffer for messages.
167 buffer
: &'buf
mut [u8],
169 /// The amount of the buffer that is used.
172 /// Phantom data for lifetime of `&'slice [BorrowedFd<'fd>]`.
173 _phantom
: PhantomData
<&'slice
[BorrowedFd
<'fd
>]>,
176 impl<'buf
> From
<&'buf
mut [u8]> for SendAncillaryBuffer
<'buf
, '_
, '_
> {
177 fn from(buffer
: &'buf
mut [u8]) -> Self {
182 impl Default
for SendAncillaryBuffer
<'_
, '_
, '_
> {
183 fn default() -> Self {
187 _phantom
: PhantomData
,
192 impl<'buf
, 'slice
, 'fd
> SendAncillaryBuffer
<'buf
, 'slice
, 'fd
> {
193 /// Create a new, empty `SendAncillaryBuffer` from a raw byte buffer.
195 /// The buffer size may be computed with [`cmsg_space`], or it may be
196 /// zero for an empty buffer, however in that case, consider `default()`
197 /// instead, or even using [`send`] instead of `sendmsg`.
201 /// Allocate a buffer for a single file descriptor:
203 /// # use rustix::cmsg_space;
204 /// # use rustix::net::SendAncillaryBuffer;
205 /// let mut space = [0; rustix::cmsg_space!(ScmRights(1))];
206 /// let mut cmsg_buffer = SendAncillaryBuffer::new(&mut space);
209 /// Allocate a buffer for credentials:
211 /// # #[cfg(linux_kernel)]
213 /// # use rustix::cmsg_space;
214 /// # use rustix::net::SendAncillaryBuffer;
215 /// let mut space = [0; rustix::cmsg_space!(ScmCredentials(1))];
216 /// let mut cmsg_buffer = SendAncillaryBuffer::new(&mut space);
220 /// Allocate a buffer for two file descriptors and credentials:
222 /// # #[cfg(linux_kernel)]
224 /// # use rustix::cmsg_space;
225 /// # use rustix::net::SendAncillaryBuffer;
226 /// let mut space = [0; rustix::cmsg_space!(ScmRights(2), ScmCredentials(1))];
227 /// let mut cmsg_buffer = SendAncillaryBuffer::new(&mut space);
231 /// [`send`]: crate::net::send
233 pub fn new(buffer
: &'buf
mut [u8]) -> Self {
235 buffer
: align_for_cmsghdr(buffer
),
237 _phantom
: PhantomData
,
241 /// Returns a pointer to the message data.
242 pub(crate) fn as_control_ptr(&mut self) -> *mut u8 {
243 // When the length is zero, we may be using a `&[]` address, which may
244 // be an invalid but non-null pointer, and on some platforms, that
245 // causes `sendmsg` to fail with `EFAULT` or `EINVAL`
246 #[cfg(not(linux_kernel))]
247 if self.length
== 0 {
248 return core
::ptr
::null_mut();
251 self.buffer
.as_mut_ptr()
254 /// Returns the length of the message data.
255 pub(crate) fn control_len(&self) -> usize {
259 /// Delete all messages from the buffer.
260 pub fn clear(&mut self) {
264 /// Add an ancillary message to the buffer.
266 /// Returns `true` if the message was added successfully.
267 pub fn push(&mut self, msg
: SendAncillaryMessage
<'slice
, 'fd
>) -> bool
{
269 SendAncillaryMessage
::ScmRights(fds
) => {
271 unsafe { slice::from_raw_parts(fds.as_ptr().cast::<u8>(), size_of_val(fds)) }
;
272 self.push_ancillary(fds_bytes
, c
::SOL_SOCKET
as _
, c
::SCM_RIGHTS
as _
)
275 SendAncillaryMessage
::ScmCredentials(ucred
) => {
276 let ucred_bytes
= unsafe {
277 slice
::from_raw_parts(addr_of
!(ucred
).cast
::<u8>(), size_of_val(&ucred
))
279 self.push_ancillary(ucred_bytes
, c
::SOL_SOCKET
as _
, c
::SCM_CREDENTIALS
as _
)
284 /// Pushes an ancillary message to the buffer.
285 fn push_ancillary(&mut self, source
: &[u8], cmsg_level
: c
::c_int
, cmsg_type
: c
::c_int
) -> bool
{
290 None
=> return false,
295 // Calculate the length of the message.
296 let source_len
= leap
!(u32::try_from(source
.len()).ok());
298 // Calculate the new length of the buffer.
299 let additional_space
= unsafe { c::CMSG_SPACE(source_len) }
;
300 let new_length
= leap
!(self.length
.checked_add(additional_space
as usize));
301 let buffer
= leap
!(self.buffer
.get_mut(..new_length
));
303 // Fill the new part of the buffer with zeroes.
304 buffer
[self.length
..new_length
].fill(0);
305 self.length
= new_length
;
307 // Get the last header in the buffer.
308 let last_header
= leap
!(messages
::Messages
::new(buffer
).last());
310 // Set the header fields.
311 last_header
.cmsg_len
= unsafe { c::CMSG_LEN(source_len) }
as _
;
312 last_header
.cmsg_level
= cmsg_level
;
313 last_header
.cmsg_type
= cmsg_type
;
315 // Get the pointer to the payload and copy the data.
317 let payload
= c
::CMSG_DATA(last_header
);
318 ptr
::copy_nonoverlapping(source
.as_ptr(), payload
, source_len
as _
);
325 impl<'slice
, 'fd
> Extend
<SendAncillaryMessage
<'slice
, 'fd
>>
326 for SendAncillaryBuffer
<'_
, 'slice
, 'fd
>
328 fn extend
<T
: IntoIterator
<Item
= SendAncillaryMessage
<'slice
, 'fd
>>>(&mut self, iter
: T
) {
329 // TODO: This could be optimized to add every message in one go.
330 iter
.into_iter().all(|msg
| self.push(msg
));
334 /// Buffer for receiving ancillary messages with [`recvmsg`].
336 /// Use the [`drain`] function to iterate over the received messages.
338 /// [`drain`]: RecvAncillaryBuffer::drain
340 pub struct RecvAncillaryBuffer
<'buf
> {
341 /// Raw byte buffer for messages.
342 buffer
: &'buf
mut [u8],
344 /// The portion of the buffer we've read from already.
347 /// The amount of the buffer that is used.
351 impl<'buf
> From
<&'buf
mut [u8]> for RecvAncillaryBuffer
<'buf
> {
352 fn from(buffer
: &'buf
mut [u8]) -> Self {
357 impl<'buf
> RecvAncillaryBuffer
<'buf
> {
358 /// Create a new, empty `RecvAncillaryBuffer` from a raw byte buffer.
360 /// The buffer size may be computed with [`cmsg_space`], or it may be
361 /// zero for an empty buffer, however in that case, consider `default()`
362 /// instead, or even using [`recv`] instead of `recvmsg`.
366 /// Allocate a buffer for a single file descriptor:
368 /// # use rustix::cmsg_space;
369 /// # use rustix::net::RecvAncillaryBuffer;
370 /// let mut space = [0; rustix::cmsg_space!(ScmRights(1))];
371 /// let mut cmsg_buffer = RecvAncillaryBuffer::new(&mut space);
374 /// Allocate a buffer for credentials:
376 /// # #[cfg(linux_kernel)]
378 /// # use rustix::cmsg_space;
379 /// # use rustix::net::RecvAncillaryBuffer;
380 /// let mut space = [0; rustix::cmsg_space!(ScmCredentials(1))];
381 /// let mut cmsg_buffer = RecvAncillaryBuffer::new(&mut space);
385 /// Allocate a buffer for two file descriptors and credentials:
387 /// # #[cfg(linux_kernel)]
389 /// # use rustix::cmsg_space;
390 /// # use rustix::net::RecvAncillaryBuffer;
391 /// let mut space = [0; rustix::cmsg_space!(ScmRights(2), ScmCredentials(1))];
392 /// let mut cmsg_buffer = RecvAncillaryBuffer::new(&mut space);
396 /// [`recv`]: crate::net::recv
398 pub fn new(buffer
: &'buf
mut [u8]) -> Self {
400 buffer
: align_for_cmsghdr(buffer
),
406 /// Returns a pointer to the message data.
407 pub(crate) fn as_control_ptr(&mut self) -> *mut u8 {
408 // When the length is zero, we may be using a `&[]` address, which may
409 // be an invalid but non-null pointer, and on some platforms, that
410 // causes `sendmsg` to fail with `EFAULT` or `EINVAL`
411 #[cfg(not(linux_kernel))]
412 if self.buffer
.is_empty() {
413 return core
::ptr
::null_mut();
416 self.buffer
.as_mut_ptr()
419 /// Returns the length of the message data.
420 pub(crate) fn control_len(&self) -> usize {
424 /// Set the length of the message data.
428 /// The buffer must be filled with valid message data.
429 pub(crate) unsafe fn set_control_len(&mut self, len
: usize) {
434 /// Delete all messages from the buffer.
435 pub(crate) fn clear(&mut self) {
436 self.drain().for_each(drop
);
439 /// Drain all messages from the buffer.
440 pub fn drain(&mut self) -> AncillaryDrain
<'_
> {
442 messages
: messages
::Messages
::new(&mut self.buffer
[self.read
..][..self.length
]),
443 read
: &mut self.read
,
444 length
: &mut self.length
,
449 impl Drop
for RecvAncillaryBuffer
<'_
> {
455 /// Return a slice of `buffer` starting at the first `cmsghdr` alignment
458 fn align_for_cmsghdr(buffer
: &mut [u8]) -> &mut [u8] {
459 // If the buffer is empty, we won't be writing anything into it, so it
460 // doesn't need to be aligned.
461 if buffer
.is_empty() {
465 let align
= align_of
::<c
::cmsghdr
>();
466 let addr
= buffer
.as_ptr() as usize;
467 let adjusted
= (addr
+ (align
- 1)) & align
.wrapping_neg();
468 &mut buffer
[adjusted
- addr
..]
471 /// An iterator that drains messages from a [`RecvAncillaryBuffer`].
472 pub struct AncillaryDrain
<'buf
> {
473 /// Inner iterator over messages.
474 messages
: messages
::Messages
<'buf
>,
476 /// Increment the number of messages we've read.
477 read
: &'buf
mut usize,
479 /// Decrement the total length.
480 length
: &'buf
mut usize,
483 impl<'buf
> AncillaryDrain
<'buf
> {
484 /// A closure that converts a message into a [`RecvAncillaryMessage`].
489 ) -> Option
<RecvAncillaryMessage
<'buf
>> {
491 // Advance the `read` pointer.
492 let msg_len
= msg
.cmsg_len
as usize;
496 // Get a pointer to the payload.
497 let payload
= c
::CMSG_DATA(msg
);
498 let payload_len
= msg
.cmsg_len
as usize - c
::CMSG_LEN(0) as usize;
500 // Get a mutable slice of the payload.
501 let payload
: &'buf
mut [u8] = slice
::from_raw_parts_mut(payload
, payload_len
);
503 // Determine what type it is.
504 let (level
, msg_type
) = (msg
.cmsg_level
, msg
.cmsg_type
);
505 match (level
as _
, msg_type
as _
) {
506 (c
::SOL_SOCKET
, c
::SCM_RIGHTS
) => {
507 // Create an iterator that reads out the file descriptors.
508 let fds
= AncillaryIter
::new(payload
);
510 Some(RecvAncillaryMessage
::ScmRights(fds
))
513 (c
::SOL_SOCKET
, c
::SCM_CREDENTIALS
) => {
514 if payload_len
>= size_of
::<UCred
>() {
515 let ucred
= payload
.as_ptr().cast
::<UCred
>().read_unaligned();
516 Some(RecvAncillaryMessage
::ScmCredentials(ucred
))
527 impl<'buf
> Iterator
for AncillaryDrain
<'buf
> {
528 type Item
= RecvAncillaryMessage
<'buf
>;
530 fn next(&mut self) -> Option
<Self::Item
> {
531 let read
= &mut self.read
;
532 let length
= &mut self.length
;
533 self.messages
.find_map(|ev
| Self::cvt_msg(read
, length
, ev
))
536 fn size_hint(&self) -> (usize, Option
<usize>) {
537 let (_
, max
) = self.messages
.size_hint();
541 fn fold
<B
, F
>(self, init
: B
, f
: F
) -> B
544 F
: FnMut(B
, Self::Item
) -> B
,
546 let read
= self.read
;
547 let length
= self.length
;
549 .filter_map(|ev
| Self::cvt_msg(read
, length
, ev
))
553 fn count(self) -> usize {
554 let read
= self.read
;
555 let length
= self.length
;
557 .filter_map(|ev
| Self::cvt_msg(read
, length
, ev
))
561 fn last(self) -> Option
<Self::Item
>
565 let read
= self.read
;
566 let length
= self.length
;
568 .filter_map(|ev
| Self::cvt_msg(read
, length
, ev
))
572 fn collect
<B
: FromIterator
<Self::Item
>>(self) -> B
576 let read
= self.read
;
577 let length
= self.length
;
579 .filter_map(|ev
| Self::cvt_msg(read
, length
, ev
))
584 impl FusedIterator
for AncillaryDrain
<'_
> {}
586 /// `sendmsg(msghdr)`—Sends a message on a socket.
595 /// - [DragonFly BSD]
598 /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/sendmsg.html
599 /// [Linux]: https://man7.org/linux/man-pages/man2/sendmsg.2.html
600 /// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/sendmsg.2.html
601 /// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=sendmsg&sektion=2
602 /// [NetBSD]: https://man.netbsd.org/sendmsg.2
603 /// [OpenBSD]: https://man.openbsd.org/sendmsg.2
604 /// [DragonFly BSD]: https://man.dragonflybsd.org/?command=sendmsg§ion=2
605 /// [illumos]: https://illumos.org/man/3SOCKET/sendmsg
610 control
: &mut SendAncillaryBuffer
<'_
, '_
, '_
>,
612 ) -> io
::Result
<usize> {
613 backend
::net
::syscalls
::sendmsg(socket
.as_fd(), iov
, control
, flags
)
616 /// `sendmsg(msghdr)`—Sends a message on a socket to a specific IPv4 address.
625 /// - [DragonFly BSD]
628 /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/sendmsg.html
629 /// [Linux]: https://man7.org/linux/man-pages/man2/sendmsg.2.html
630 /// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/sendmsg.2.html
631 /// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=sendmsg&sektion=2
632 /// [NetBSD]: https://man.netbsd.org/sendmsg.2
633 /// [OpenBSD]: https://man.openbsd.org/sendmsg.2
634 /// [DragonFly BSD]: https://man.dragonflybsd.org/?command=sendmsg§ion=2
635 /// [illumos]: https://illumos.org/man/3SOCKET/sendmsg
641 control
: &mut SendAncillaryBuffer
<'_
, '_
, '_
>,
643 ) -> io
::Result
<usize> {
644 backend
::net
::syscalls
::sendmsg_v4(socket
.as_fd(), addr
, iov
, control
, flags
)
647 /// `sendmsg(msghdr)`—Sends a message on a socket to a specific IPv6 address.
656 /// - [DragonFly BSD]
659 /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/sendmsg.html
660 /// [Linux]: https://man7.org/linux/man-pages/man2/sendmsg.2.html
661 /// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/sendmsg.2.html
662 /// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=sendmsg&sektion=2
663 /// [NetBSD]: https://man.netbsd.org/sendmsg.2
664 /// [OpenBSD]: https://man.openbsd.org/sendmsg.2
665 /// [DragonFly BSD]: https://man.dragonflybsd.org/?command=sendmsg§ion=2
666 /// [illumos]: https://illumos.org/man/3SOCKET/sendmsg
672 control
: &mut SendAncillaryBuffer
<'_
, '_
, '_
>,
674 ) -> io
::Result
<usize> {
675 backend
::net
::syscalls
::sendmsg_v6(socket
.as_fd(), addr
, iov
, control
, flags
)
678 /// `sendmsg(msghdr)`—Sends a message on a socket to a specific Unix-domain
688 /// - [DragonFly BSD]
691 /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/sendmsg.html
692 /// [Linux]: https://man7.org/linux/man-pages/man2/sendmsg.2.html
693 /// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/sendmsg.2.html
694 /// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=sendmsg&sektion=2
695 /// [NetBSD]: https://man.netbsd.org/sendmsg.2
696 /// [OpenBSD]: https://man.openbsd.org/sendmsg.2
697 /// [DragonFly BSD]: https://man.dragonflybsd.org/?command=sendmsg§ion=2
698 /// [illumos]: https://illumos.org/man/3SOCKET/sendmsg
703 addr
: &super::SocketAddrUnix
,
705 control
: &mut SendAncillaryBuffer
<'_
, '_
, '_
>,
707 ) -> io
::Result
<usize> {
708 backend
::net
::syscalls
::sendmsg_unix(socket
.as_fd(), addr
, iov
, control
, flags
)
711 /// `sendmsg(msghdr)`—Sends a message on a socket to a specific address.
720 /// - [DragonFly BSD]
723 /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/sendmsg.html
724 /// [Linux]: https://man7.org/linux/man-pages/man2/sendmsg.2.html
725 /// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/sendmsg.2.html
726 /// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=sendmsg&sektion=2
727 /// [NetBSD]: https://man.netbsd.org/sendmsg.2
728 /// [OpenBSD]: https://man.openbsd.org/sendmsg.2
729 /// [DragonFly BSD]: https://man.dragonflybsd.org/?command=sendmsg§ion=2
730 /// [illumos]: https://illumos.org/man/3SOCKET/sendmsg
734 addr
: Option
<&SocketAddrAny
>,
736 control
: &mut SendAncillaryBuffer
<'_
, '_
, '_
>,
738 ) -> io
::Result
<usize> {
740 None
=> backend
::net
::syscalls
::sendmsg(socket
.as_fd(), iov
, control
, flags
),
741 Some(SocketAddrAny
::V4(addr
)) => {
742 backend
::net
::syscalls
::sendmsg_v4(socket
.as_fd(), addr
, iov
, control
, flags
)
744 Some(SocketAddrAny
::V6(addr
)) => {
745 backend
::net
::syscalls
::sendmsg_v6(socket
.as_fd(), addr
, iov
, control
, flags
)
748 Some(SocketAddrAny
::Unix(addr
)) => {
749 backend
::net
::syscalls
::sendmsg_unix(socket
.as_fd(), addr
, iov
, control
, flags
)
754 /// `recvmsg(msghdr)`—Receives a message from a socket.
763 /// - [DragonFly BSD]
766 /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/recvmsg.html
767 /// [Linux]: https://man7.org/linux/man-pages/man2/recvmsg.2.html
768 /// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/recvmsg.2.html
769 /// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=recvmsg&sektion=2
770 /// [NetBSD]: https://man.netbsd.org/recvmsg.2
771 /// [OpenBSD]: https://man.openbsd.org/recvmsg.2
772 /// [DragonFly BSD]: https://man.dragonflybsd.org/?command=recvmsg§ion=2
773 /// [illumos]: https://illumos.org/man/3SOCKET/recvmsg
777 iov
: &mut [IoSliceMut
<'_
>],
778 control
: &mut RecvAncillaryBuffer
<'_
>,
780 ) -> io
::Result
<RecvMsgReturn
> {
781 backend
::net
::syscalls
::recvmsg(socket
.as_fd(), iov
, control
, flags
)
784 /// The result of a successful [`recvmsg`] call.
785 pub struct RecvMsgReturn
{
786 /// The number of bytes received.
789 /// The flags received.
790 pub flags
: RecvFlags
,
792 /// The address of the socket we received from, if any.
793 pub address
: Option
<SocketAddrAny
>,
796 /// An iterator over data in an ancillary buffer.
797 pub struct AncillaryIter
<'data
, T
> {
798 /// The data we're iterating over.
799 data
: &'data
mut [u8],
801 /// The raw data we're removing.
802 _marker
: PhantomData
<T
>,
805 impl<'data
, T
> AncillaryIter
<'data
, T
> {
806 /// Create a new iterator over data in an ancillary buffer.
810 /// The buffer must contain valid ancillary data.
811 unsafe fn new(data
: &'data
mut [u8]) -> Self {
812 assert_eq
!(data
.len() % size_of
::<T
>(), 0);
816 _marker
: PhantomData
,
821 impl<'data
, T
> Drop
for AncillaryIter
<'data
, T
> {
827 impl<T
> Iterator
for AncillaryIter
<'_
, T
> {
830 fn next(&mut self) -> Option
<Self::Item
> {
831 // See if there is a next item.
832 if self.data
.len() < size_of
::<T
>() {
836 // Get the next item.
837 let item
= unsafe { self.data.as_ptr().cast::<T>().read_unaligned() }
;
840 let data
= take(&mut self.data
);
841 self.data
= &mut data
[size_of
::<T
>()..];
846 fn size_hint(&self) -> (usize, Option
<usize>) {
847 let len
= self.len();
851 fn count(self) -> usize {
855 fn last(mut self) -> Option
<Self::Item
> {
860 impl<T
> FusedIterator
for AncillaryIter
<'_
, T
> {}
862 impl<T
> ExactSizeIterator
for AncillaryIter
<'_
, T
> {
863 fn len(&self) -> usize {
864 self.data
.len() / size_of
::<T
>()
868 impl<T
> DoubleEndedIterator
for AncillaryIter
<'_
, T
> {
869 fn next_back(&mut self) -> Option
<Self::Item
> {
870 // See if there is a next item.
871 if self.data
.len() < size_of
::<T
>() {
875 // Get the next item.
877 let ptr
= self.data
.as_ptr().add(self.data
.len() - size_of
::<T
>());
878 ptr
.cast
::<T
>().read_unaligned()
882 let len
= self.data
.len();
883 let data
= take(&mut self.data
);
884 self.data
= &mut data
[..len
- size_of
::<T
>()];
891 use crate::backend
::c
;
892 use crate::backend
::net
::msghdr
;
893 use core
::iter
::FusedIterator
;
894 use core
::marker
::PhantomData
;
895 use core
::ptr
::NonNull
;
897 /// An iterator over the messages in an ancillary buffer.
898 pub(super) struct Messages
<'buf
> {
899 /// The message header we're using to iterate over the messages.
902 /// The current pointer to the next message header to return.
904 /// This has a lifetime of `'buf`.
905 header
: Option
<NonNull
<c
::cmsghdr
>>,
907 /// Capture the original lifetime of the buffer.
908 _buffer
: PhantomData
<&'buf
mut [u8]>,
911 impl<'buf
> Messages
<'buf
> {
912 /// Create a new iterator over messages from a byte buffer.
913 pub(super) fn new(buf
: &'buf
mut [u8]) -> Self {
915 let mut h
= msghdr
::zero_msghdr();
916 h
.msg_control
= buf
.as_mut_ptr().cast();
917 h
.msg_controllen
= buf
.len().try_into().expect("buffer too large for msghdr");
921 // Get the first header.
922 let header
= NonNull
::new(unsafe { c::CMSG_FIRSTHDR(&msghdr) }
);
927 _buffer
: PhantomData
,
932 impl<'a
> Iterator
for Messages
<'a
> {
933 type Item
= &'a
mut c
::cmsghdr
;
936 fn next(&mut self) -> Option
<Self::Item
> {
937 // Get the current header.
938 let header
= self.header?
;
940 // Get the next header.
941 self.header
= NonNull
::new(unsafe { c::CMSG_NXTHDR(&self.msghdr, header.as_ptr()) }
);
943 // If the headers are equal, we're done.
944 if Some(header
) == self.header
{
948 // SAFETY: The lifetime of `header` is tied to this.
949 Some(unsafe { &mut *header.as_ptr() }
)
952 fn size_hint(&self) -> (usize, Option
<usize>) {
953 if self.header
.is_some() {
954 // The remaining buffer *could* be filled with zero-length
956 let max_size
= unsafe { c::CMSG_LEN(0) }
as usize;
957 let remaining_count
= self.msghdr
.msg_controllen
as usize / max_size
;
958 (1, Some(remaining_count
))
965 impl FusedIterator
for Messages
<'_
> {}