rustix/backend/libc/net/
msghdr.rs1use crate::backend::c;
7
8use crate::io::{self, IoSlice, IoSliceMut};
9use crate::net::addr::SocketAddrArg;
10use crate::net::{RecvAncillaryBuffer, SendAncillaryBuffer, SocketAddrBuf};
11
12use core::mem::zeroed;
13
14#[cfg(all(
16 not(any(windows, target_os = "espidf", target_os = "wasi")),
17 any(
18 target_os = "android",
19 all(
20 target_os = "linux",
21 not(target_env = "musl"),
22 not(all(target_env = "uclibc", any(target_arch = "arm", target_arch = "mips")))
23 )
24 )
25))]
26#[inline]
27fn msg_iov_len(len: usize) -> c::size_t {
28 len
29}
30
31#[cfg(all(
33 not(any(
34 windows,
35 target_os = "espidf",
36 target_os = "redox",
37 target_os = "vita",
38 target_os = "wasi"
39 )),
40 not(any(
41 target_os = "android",
42 all(
43 target_os = "linux",
44 not(target_env = "musl"),
45 not(all(target_env = "uclibc", any(target_arch = "arm", target_arch = "mips")))
46 )
47 ))
48))]
49#[inline]
50fn msg_iov_len(len: usize) -> c::c_int {
51 len.try_into().unwrap_or(c::c_int::MAX)
52}
53
54#[cfg(any(
56 bsd,
57 solarish,
58 target_env = "musl",
59 target_os = "aix",
60 target_os = "cygwin",
61 target_os = "emscripten",
62 target_os = "fuchsia",
63 target_os = "haiku",
64 target_os = "hurd",
65 target_os = "nto",
66))]
67#[inline]
68fn msg_control_len(len: usize) -> c::socklen_t {
69 len.try_into().unwrap_or(c::socklen_t::MAX)
70}
71
72#[cfg(not(any(
74 bsd,
75 solarish,
76 windows,
77 target_env = "musl",
78 target_os = "aix",
79 target_os = "cygwin",
80 target_os = "emscripten",
81 target_os = "espidf",
82 target_os = "fuchsia",
83 target_os = "haiku",
84 target_os = "hurd",
85 target_os = "nto",
86 target_os = "redox",
87 target_os = "vita",
88 target_os = "wasi",
89)))]
90#[inline]
91fn msg_control_len(len: usize) -> c::size_t {
92 len
93}
94
95pub(crate) unsafe fn with_recv_msghdr<R>(
105 name: &mut SocketAddrBuf,
106 iov: &mut [IoSliceMut<'_>],
107 control: &mut RecvAncillaryBuffer<'_>,
108 f: impl FnOnce(&mut c::msghdr) -> io::Result<R>,
109) -> io::Result<R> {
110 control.clear();
111
112 let mut msghdr = zero_msghdr();
113 msghdr.msg_name = name.storage.as_mut_ptr().cast();
114 msghdr.msg_namelen = name.len;
115 msghdr.msg_iov = iov.as_mut_ptr().cast();
116 msghdr.msg_iovlen = msg_iov_len(iov.len());
117 msghdr.msg_control = control.as_control_ptr().cast();
118 msghdr.msg_controllen = msg_control_len(control.control_len());
119
120 let res = f(&mut msghdr);
121
122 if res.is_ok() {
124 control.set_control_len(msghdr.msg_controllen as usize);
127 }
128
129 name.len = msghdr.msg_namelen;
130
131 res
132}
133
134pub(crate) fn noaddr_msghdr(
139 iov: &[IoSlice<'_>],
140 control: &mut SendAncillaryBuffer<'_, '_, '_>,
141) -> c::msghdr {
142 let mut h = zero_msghdr();
143 h.msg_iov = iov.as_ptr() as _;
144 h.msg_iovlen = msg_iov_len(iov.len());
145 h.msg_control = control.as_control_ptr().cast();
146 h.msg_controllen = msg_control_len(control.control_len());
147 h
148}
149
150pub(crate) unsafe fn with_msghdr<R>(
161 addr: &impl SocketAddrArg,
162 iov: &[IoSlice<'_>],
163 control: &mut SendAncillaryBuffer<'_, '_, '_>,
164 f: impl FnOnce(&c::msghdr) -> R,
165) -> R {
166 addr.with_sockaddr(|addr_ptr, addr_len| {
167 let mut h = zero_msghdr();
168 h.msg_name = addr_ptr as *mut _;
169 h.msg_namelen = bitcast!(addr_len);
170 h.msg_iov = iov.as_ptr() as _;
171 h.msg_iovlen = msg_iov_len(iov.len());
172 h.msg_control = control.as_control_ptr().cast();
173 h.msg_controllen = msg_control_len(control.control_len());
174 f(&h)
178 })
179}
180
181#[cfg(all(unix, not(target_os = "redox")))]
183pub(crate) fn zero_msghdr() -> c::msghdr {
184 unsafe { zeroed() }
188}