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 target_os = "redox",
20 all(
21 target_os = "linux",
22 not(target_env = "musl"),
23 not(all(target_env = "uclibc", any(target_arch = "arm", target_arch = "mips")))
24 )
25 )
26))]
27#[inline]
28fn msg_iov_len(len: usize) -> c::size_t {
29 len
30}
31
32#[cfg(all(
34 not(any(windows, target_os = "espidf", target_os = "vita", target_os = "wasi")),
35 not(any(
36 target_os = "android",
37 target_os = "redox",
38 all(
39 target_os = "linux",
40 not(target_env = "musl"),
41 not(all(target_env = "uclibc", any(target_arch = "arm", target_arch = "mips")))
42 )
43 ))
44))]
45#[inline]
46fn msg_iov_len(len: usize) -> c::c_int {
47 len.try_into().unwrap_or(c::c_int::MAX)
48}
49
50#[cfg(any(
52 bsd,
53 solarish,
54 target_env = "musl",
55 target_os = "aix",
56 target_os = "cygwin",
57 target_os = "emscripten",
58 target_os = "fuchsia",
59 target_os = "haiku",
60 target_os = "hurd",
61 target_os = "nto",
62))]
63#[inline]
64fn msg_control_len(len: usize) -> c::socklen_t {
65 len.try_into().unwrap_or(c::socklen_t::MAX)
66}
67
68#[cfg(not(any(
70 bsd,
71 solarish,
72 windows,
73 target_env = "musl",
74 target_os = "aix",
75 target_os = "cygwin",
76 target_os = "emscripten",
77 target_os = "espidf",
78 target_os = "fuchsia",
79 target_os = "haiku",
80 target_os = "hurd",
81 target_os = "nto",
82 target_os = "vita",
83 target_os = "wasi",
84)))]
85#[inline]
86fn msg_control_len(len: usize) -> c::size_t {
87 len
88}
89
90pub(crate) unsafe fn with_recv_msghdr<R>(
100 name: &mut SocketAddrBuf,
101 iov: &mut [IoSliceMut<'_>],
102 control: &mut RecvAncillaryBuffer<'_>,
103 f: impl FnOnce(&mut c::msghdr) -> io::Result<R>,
104) -> io::Result<R> {
105 control.clear();
106
107 let mut msghdr = zero_msghdr();
108 msghdr.msg_name = name.storage.as_mut_ptr().cast();
109 msghdr.msg_namelen = name.len;
110 msghdr.msg_iov = iov.as_mut_ptr().cast();
111 msghdr.msg_iovlen = msg_iov_len(iov.len());
112 msghdr.msg_control = control.as_control_ptr().cast();
113 msghdr.msg_controllen = msg_control_len(control.control_len());
114
115 let res = f(&mut msghdr);
116
117 if res.is_ok() {
119 control.set_control_len(msghdr.msg_controllen as usize);
122 }
123
124 name.len = msghdr.msg_namelen;
125
126 res
127}
128
129pub(crate) fn noaddr_msghdr(
134 iov: &[IoSlice<'_>],
135 control: &mut SendAncillaryBuffer<'_, '_, '_>,
136) -> c::msghdr {
137 let mut h = zero_msghdr();
138 h.msg_iov = iov.as_ptr() as _;
139 h.msg_iovlen = msg_iov_len(iov.len());
140 h.msg_control = control.as_control_ptr().cast();
141 h.msg_controllen = msg_control_len(control.control_len());
142 h
143}
144
145pub(crate) unsafe fn with_msghdr<R>(
156 addr: &impl SocketAddrArg,
157 iov: &[IoSlice<'_>],
158 control: &mut SendAncillaryBuffer<'_, '_, '_>,
159 f: impl FnOnce(&c::msghdr) -> R,
160) -> R {
161 addr.with_sockaddr(|addr_ptr, addr_len| {
162 let mut h = zero_msghdr();
163 h.msg_name = addr_ptr as *mut _;
164 h.msg_namelen = bitcast!(addr_len);
165 h.msg_iov = iov.as_ptr() as _;
166 h.msg_iovlen = msg_iov_len(iov.len());
167 h.msg_control = control.as_control_ptr().cast();
168 h.msg_controllen = msg_control_len(control.control_len());
169 f(&h)
173 })
174}
175
176#[cfg(unix)]
178pub(crate) fn zero_msghdr() -> c::msghdr {
179 unsafe { zeroed() }
183}