-
Notifications
You must be signed in to change notification settings - Fork 135
/
msghdr.rs
126 lines (112 loc) · 4.06 KB
/
msghdr.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
//! 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.
use super::super::c;
use super::super::conv::{msg_control_len, msg_iov_len};
use super::super::net::write_sockaddr::{encode_sockaddr_v4, encode_sockaddr_v6};
use crate::io::{self, IoSlice, IoSliceMut};
use crate::net::{RecvAncillaryBuffer, SendAncillaryBuffer, SocketAddrV4, SocketAddrV6};
use crate::utils::as_ptr;
use core::convert::TryInto;
use core::mem::{size_of, zeroed, MaybeUninit};
/// Create a message header intended to receive a datagram.
pub(crate) fn with_recv_msghdr<R>(
name: &mut MaybeUninit<c::sockaddr_storage>,
iov: &mut [IoSliceMut<'_>],
control: &mut RecvAncillaryBuffer<'_>,
f: impl FnOnce(&mut c::msghdr) -> io::Result<R>,
) -> io::Result<R> {
control.clear();
let namelen = size_of::<c::sockaddr_storage>() as c::socklen_t;
let mut msghdr = {
let mut h: c::msghdr = unsafe { zeroed() };
h.msg_name = name.as_mut_ptr().cast();
h.msg_namelen = namelen;
h.msg_iov = iov.as_mut_ptr().cast();
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
};
let res = f(&mut msghdr);
// Reset the control length.
if res.is_ok() {
unsafe {
control.set_control_len(msghdr.msg_controllen.try_into().unwrap_or(usize::MAX));
}
}
res
}
/// Create a message header intended to send without an address.
pub(crate) fn with_noaddr_msghdr<R>(
iov: &[IoSlice<'_>],
control: &mut SendAncillaryBuffer<'_, '_, '_>,
f: impl FnOnce(c::msghdr) -> R,
) -> R {
f({
let mut h: c::msghdr = unsafe { zeroed() };
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 an IPv4 address.
pub(crate) fn with_v4_msghdr<R>(
addr: &SocketAddrV4,
iov: &[IoSlice<'_>],
control: &mut SendAncillaryBuffer<'_, '_, '_>,
f: impl FnOnce(c::msghdr) -> R,
) -> R {
let encoded = unsafe { encode_sockaddr_v4(addr) };
f({
let mut h: c::msghdr = unsafe { zeroed() };
h.msg_name = as_ptr(&encoded) as _;
h.msg_namelen = size_of::<SocketAddrV4>() as _;
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 an IPv6 address.
pub(crate) fn with_v6_msghdr<R>(
addr: &SocketAddrV6,
iov: &[IoSlice<'_>],
control: &mut SendAncillaryBuffer<'_, '_, '_>,
f: impl FnOnce(c::msghdr) -> R,
) -> R {
let encoded = unsafe { encode_sockaddr_v6(addr) };
f({
let mut h: c::msghdr = unsafe { zeroed() };
h.msg_name = as_ptr(&encoded) as _;
h.msg_namelen = size_of::<SocketAddrV6>() as _;
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 a Unix address.
#[cfg(all(unix, not(target_os = "redox")))]
pub(crate) fn with_unix_msghdr<R>(
addr: &crate::net::SocketAddrUnix,
iov: &[IoSlice<'_>],
control: &mut SendAncillaryBuffer<'_, '_, '_>,
f: impl FnOnce(c::msghdr) -> R,
) -> R {
f({
let mut h: c::msghdr = unsafe { zeroed() };
h.msg_name = as_ptr(&addr.unix) as _;
h.msg_namelen = addr.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());
h
})
}