1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2018 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker
5*bb4ee6a4SAndroid Build Coastguard Worker use std::cmp::Ordering;
6*bb4ee6a4SAndroid Build Coastguard Worker use std::convert::TryFrom;
7*bb4ee6a4SAndroid Build Coastguard Worker use std::ffi::OsString;
8*bb4ee6a4SAndroid Build Coastguard Worker use std::fs::remove_file;
9*bb4ee6a4SAndroid Build Coastguard Worker use std::io;
10*bb4ee6a4SAndroid Build Coastguard Worker use std::mem;
11*bb4ee6a4SAndroid Build Coastguard Worker use std::mem::size_of;
12*bb4ee6a4SAndroid Build Coastguard Worker use std::net::Ipv4Addr;
13*bb4ee6a4SAndroid Build Coastguard Worker use std::net::Ipv6Addr;
14*bb4ee6a4SAndroid Build Coastguard Worker use std::net::SocketAddr;
15*bb4ee6a4SAndroid Build Coastguard Worker use std::net::SocketAddrV4;
16*bb4ee6a4SAndroid Build Coastguard Worker use std::net::SocketAddrV6;
17*bb4ee6a4SAndroid Build Coastguard Worker use std::net::TcpListener;
18*bb4ee6a4SAndroid Build Coastguard Worker use std::net::TcpStream;
19*bb4ee6a4SAndroid Build Coastguard Worker use std::net::ToSocketAddrs;
20*bb4ee6a4SAndroid Build Coastguard Worker use std::ops::Deref;
21*bb4ee6a4SAndroid Build Coastguard Worker use std::os::fd::OwnedFd;
22*bb4ee6a4SAndroid Build Coastguard Worker use std::os::unix::ffi::OsStringExt;
23*bb4ee6a4SAndroid Build Coastguard Worker use std::path::Path;
24*bb4ee6a4SAndroid Build Coastguard Worker use std::path::PathBuf;
25*bb4ee6a4SAndroid Build Coastguard Worker use std::ptr::null_mut;
26*bb4ee6a4SAndroid Build Coastguard Worker use std::time::Duration;
27*bb4ee6a4SAndroid Build Coastguard Worker use std::time::Instant;
28*bb4ee6a4SAndroid Build Coastguard Worker
29*bb4ee6a4SAndroid Build Coastguard Worker use libc::c_int;
30*bb4ee6a4SAndroid Build Coastguard Worker use libc::recvfrom;
31*bb4ee6a4SAndroid Build Coastguard Worker use libc::sa_family_t;
32*bb4ee6a4SAndroid Build Coastguard Worker use libc::sockaddr;
33*bb4ee6a4SAndroid Build Coastguard Worker use libc::sockaddr_in;
34*bb4ee6a4SAndroid Build Coastguard Worker use libc::sockaddr_in6;
35*bb4ee6a4SAndroid Build Coastguard Worker use libc::socklen_t;
36*bb4ee6a4SAndroid Build Coastguard Worker use libc::AF_INET;
37*bb4ee6a4SAndroid Build Coastguard Worker use libc::AF_INET6;
38*bb4ee6a4SAndroid Build Coastguard Worker use libc::MSG_PEEK;
39*bb4ee6a4SAndroid Build Coastguard Worker use libc::MSG_TRUNC;
40*bb4ee6a4SAndroid Build Coastguard Worker use log::warn;
41*bb4ee6a4SAndroid Build Coastguard Worker use serde::Deserialize;
42*bb4ee6a4SAndroid Build Coastguard Worker use serde::Serialize;
43*bb4ee6a4SAndroid Build Coastguard Worker
44*bb4ee6a4SAndroid Build Coastguard Worker use crate::descriptor::AsRawDescriptor;
45*bb4ee6a4SAndroid Build Coastguard Worker use crate::descriptor::FromRawDescriptor;
46*bb4ee6a4SAndroid Build Coastguard Worker use crate::descriptor::IntoRawDescriptor;
47*bb4ee6a4SAndroid Build Coastguard Worker use crate::handle_eintr_errno;
48*bb4ee6a4SAndroid Build Coastguard Worker use crate::sys::sockaddr_un;
49*bb4ee6a4SAndroid Build Coastguard Worker use crate::sys::sockaddrv4_to_lib_c;
50*bb4ee6a4SAndroid Build Coastguard Worker use crate::sys::sockaddrv6_to_lib_c;
51*bb4ee6a4SAndroid Build Coastguard Worker use crate::Error;
52*bb4ee6a4SAndroid Build Coastguard Worker use crate::RawDescriptor;
53*bb4ee6a4SAndroid Build Coastguard Worker use crate::SafeDescriptor;
54*bb4ee6a4SAndroid Build Coastguard Worker
55*bb4ee6a4SAndroid Build Coastguard Worker /// Assist in handling both IP version 4 and IP version 6.
56*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Debug, Copy, Clone, PartialEq, Eq)]
57*bb4ee6a4SAndroid Build Coastguard Worker pub enum InetVersion {
58*bb4ee6a4SAndroid Build Coastguard Worker V4,
59*bb4ee6a4SAndroid Build Coastguard Worker V6,
60*bb4ee6a4SAndroid Build Coastguard Worker }
61*bb4ee6a4SAndroid Build Coastguard Worker
62*bb4ee6a4SAndroid Build Coastguard Worker impl InetVersion {
from_sockaddr(s: &SocketAddr) -> Self63*bb4ee6a4SAndroid Build Coastguard Worker pub fn from_sockaddr(s: &SocketAddr) -> Self {
64*bb4ee6a4SAndroid Build Coastguard Worker match s {
65*bb4ee6a4SAndroid Build Coastguard Worker SocketAddr::V4(_) => InetVersion::V4,
66*bb4ee6a4SAndroid Build Coastguard Worker SocketAddr::V6(_) => InetVersion::V6,
67*bb4ee6a4SAndroid Build Coastguard Worker }
68*bb4ee6a4SAndroid Build Coastguard Worker }
69*bb4ee6a4SAndroid Build Coastguard Worker }
70*bb4ee6a4SAndroid Build Coastguard Worker
71*bb4ee6a4SAndroid Build Coastguard Worker impl From<InetVersion> for sa_family_t {
from(v: InetVersion) -> sa_family_t72*bb4ee6a4SAndroid Build Coastguard Worker fn from(v: InetVersion) -> sa_family_t {
73*bb4ee6a4SAndroid Build Coastguard Worker match v {
74*bb4ee6a4SAndroid Build Coastguard Worker InetVersion::V4 => AF_INET as sa_family_t,
75*bb4ee6a4SAndroid Build Coastguard Worker InetVersion::V6 => AF_INET6 as sa_family_t,
76*bb4ee6a4SAndroid Build Coastguard Worker }
77*bb4ee6a4SAndroid Build Coastguard Worker }
78*bb4ee6a4SAndroid Build Coastguard Worker }
79*bb4ee6a4SAndroid Build Coastguard Worker
socket( domain: c_int, sock_type: c_int, protocol: c_int, ) -> io::Result<SafeDescriptor>80*bb4ee6a4SAndroid Build Coastguard Worker pub(in crate::sys) fn socket(
81*bb4ee6a4SAndroid Build Coastguard Worker domain: c_int,
82*bb4ee6a4SAndroid Build Coastguard Worker sock_type: c_int,
83*bb4ee6a4SAndroid Build Coastguard Worker protocol: c_int,
84*bb4ee6a4SAndroid Build Coastguard Worker ) -> io::Result<SafeDescriptor> {
85*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
86*bb4ee6a4SAndroid Build Coastguard Worker // Safe socket initialization since we handle the returned error.
87*bb4ee6a4SAndroid Build Coastguard Worker match unsafe { libc::socket(domain, sock_type, protocol) } {
88*bb4ee6a4SAndroid Build Coastguard Worker -1 => Err(io::Error::last_os_error()),
89*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
90*bb4ee6a4SAndroid Build Coastguard Worker // Safe because we own the file descriptor.
91*bb4ee6a4SAndroid Build Coastguard Worker fd => Ok(unsafe { SafeDescriptor::from_raw_descriptor(fd) }),
92*bb4ee6a4SAndroid Build Coastguard Worker }
93*bb4ee6a4SAndroid Build Coastguard Worker }
94*bb4ee6a4SAndroid Build Coastguard Worker
socketpair( domain: c_int, sock_type: c_int, protocol: c_int, ) -> io::Result<(SafeDescriptor, SafeDescriptor)>95*bb4ee6a4SAndroid Build Coastguard Worker pub(in crate::sys) fn socketpair(
96*bb4ee6a4SAndroid Build Coastguard Worker domain: c_int,
97*bb4ee6a4SAndroid Build Coastguard Worker sock_type: c_int,
98*bb4ee6a4SAndroid Build Coastguard Worker protocol: c_int,
99*bb4ee6a4SAndroid Build Coastguard Worker ) -> io::Result<(SafeDescriptor, SafeDescriptor)> {
100*bb4ee6a4SAndroid Build Coastguard Worker let mut fds = [0, 0];
101*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
102*bb4ee6a4SAndroid Build Coastguard Worker // Safe because we give enough space to store all the fds and we check the return value.
103*bb4ee6a4SAndroid Build Coastguard Worker match unsafe { libc::socketpair(domain, sock_type, protocol, fds.as_mut_ptr()) } {
104*bb4ee6a4SAndroid Build Coastguard Worker -1 => Err(io::Error::last_os_error()),
105*bb4ee6a4SAndroid Build Coastguard Worker _ => Ok(
106*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
107*bb4ee6a4SAndroid Build Coastguard Worker // Safe because we own the file descriptors.
108*bb4ee6a4SAndroid Build Coastguard Worker unsafe {
109*bb4ee6a4SAndroid Build Coastguard Worker (
110*bb4ee6a4SAndroid Build Coastguard Worker SafeDescriptor::from_raw_descriptor(fds[0]),
111*bb4ee6a4SAndroid Build Coastguard Worker SafeDescriptor::from_raw_descriptor(fds[1]),
112*bb4ee6a4SAndroid Build Coastguard Worker )
113*bb4ee6a4SAndroid Build Coastguard Worker },
114*bb4ee6a4SAndroid Build Coastguard Worker ),
115*bb4ee6a4SAndroid Build Coastguard Worker }
116*bb4ee6a4SAndroid Build Coastguard Worker }
117*bb4ee6a4SAndroid Build Coastguard Worker
118*bb4ee6a4SAndroid Build Coastguard Worker /// A TCP socket.
119*bb4ee6a4SAndroid Build Coastguard Worker ///
120*bb4ee6a4SAndroid Build Coastguard Worker /// Do not use this class unless you need to change socket options or query the
121*bb4ee6a4SAndroid Build Coastguard Worker /// state of the socket prior to calling listen or connect. Instead use either TcpStream or
122*bb4ee6a4SAndroid Build Coastguard Worker /// TcpListener.
123*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Debug)]
124*bb4ee6a4SAndroid Build Coastguard Worker pub struct TcpSocket {
125*bb4ee6a4SAndroid Build Coastguard Worker pub(in crate::sys) inet_version: InetVersion,
126*bb4ee6a4SAndroid Build Coastguard Worker pub(in crate::sys) descriptor: SafeDescriptor,
127*bb4ee6a4SAndroid Build Coastguard Worker }
128*bb4ee6a4SAndroid Build Coastguard Worker
129*bb4ee6a4SAndroid Build Coastguard Worker impl TcpSocket {
bind<A: ToSocketAddrs>(&mut self, addr: A) -> io::Result<()>130*bb4ee6a4SAndroid Build Coastguard Worker pub fn bind<A: ToSocketAddrs>(&mut self, addr: A) -> io::Result<()> {
131*bb4ee6a4SAndroid Build Coastguard Worker let sockaddr = addr
132*bb4ee6a4SAndroid Build Coastguard Worker .to_socket_addrs()
133*bb4ee6a4SAndroid Build Coastguard Worker .map_err(|_| io::Error::from_raw_os_error(libc::EINVAL))?
134*bb4ee6a4SAndroid Build Coastguard Worker .next()
135*bb4ee6a4SAndroid Build Coastguard Worker .unwrap();
136*bb4ee6a4SAndroid Build Coastguard Worker
137*bb4ee6a4SAndroid Build Coastguard Worker let ret = match sockaddr {
138*bb4ee6a4SAndroid Build Coastguard Worker SocketAddr::V4(a) => {
139*bb4ee6a4SAndroid Build Coastguard Worker let sin = sockaddrv4_to_lib_c(&a);
140*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
141*bb4ee6a4SAndroid Build Coastguard Worker // Safe because this doesn't modify any memory and we check the return value.
142*bb4ee6a4SAndroid Build Coastguard Worker unsafe {
143*bb4ee6a4SAndroid Build Coastguard Worker libc::bind(
144*bb4ee6a4SAndroid Build Coastguard Worker self.as_raw_descriptor(),
145*bb4ee6a4SAndroid Build Coastguard Worker &sin as *const sockaddr_in as *const sockaddr,
146*bb4ee6a4SAndroid Build Coastguard Worker size_of::<sockaddr_in>() as socklen_t,
147*bb4ee6a4SAndroid Build Coastguard Worker )
148*bb4ee6a4SAndroid Build Coastguard Worker }
149*bb4ee6a4SAndroid Build Coastguard Worker }
150*bb4ee6a4SAndroid Build Coastguard Worker SocketAddr::V6(a) => {
151*bb4ee6a4SAndroid Build Coastguard Worker let sin6 = sockaddrv6_to_lib_c(&a);
152*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
153*bb4ee6a4SAndroid Build Coastguard Worker // Safe because this doesn't modify any memory and we check the return value.
154*bb4ee6a4SAndroid Build Coastguard Worker unsafe {
155*bb4ee6a4SAndroid Build Coastguard Worker libc::bind(
156*bb4ee6a4SAndroid Build Coastguard Worker self.as_raw_descriptor(),
157*bb4ee6a4SAndroid Build Coastguard Worker &sin6 as *const sockaddr_in6 as *const sockaddr,
158*bb4ee6a4SAndroid Build Coastguard Worker size_of::<sockaddr_in6>() as socklen_t,
159*bb4ee6a4SAndroid Build Coastguard Worker )
160*bb4ee6a4SAndroid Build Coastguard Worker }
161*bb4ee6a4SAndroid Build Coastguard Worker }
162*bb4ee6a4SAndroid Build Coastguard Worker };
163*bb4ee6a4SAndroid Build Coastguard Worker if ret < 0 {
164*bb4ee6a4SAndroid Build Coastguard Worker let bind_err = io::Error::last_os_error();
165*bb4ee6a4SAndroid Build Coastguard Worker Err(bind_err)
166*bb4ee6a4SAndroid Build Coastguard Worker } else {
167*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
168*bb4ee6a4SAndroid Build Coastguard Worker }
169*bb4ee6a4SAndroid Build Coastguard Worker }
170*bb4ee6a4SAndroid Build Coastguard Worker
connect<A: ToSocketAddrs>(self, addr: A) -> io::Result<TcpStream>171*bb4ee6a4SAndroid Build Coastguard Worker pub fn connect<A: ToSocketAddrs>(self, addr: A) -> io::Result<TcpStream> {
172*bb4ee6a4SAndroid Build Coastguard Worker let sockaddr = addr
173*bb4ee6a4SAndroid Build Coastguard Worker .to_socket_addrs()
174*bb4ee6a4SAndroid Build Coastguard Worker .map_err(|_| io::Error::from_raw_os_error(libc::EINVAL))?
175*bb4ee6a4SAndroid Build Coastguard Worker .next()
176*bb4ee6a4SAndroid Build Coastguard Worker .unwrap();
177*bb4ee6a4SAndroid Build Coastguard Worker
178*bb4ee6a4SAndroid Build Coastguard Worker let ret = match sockaddr {
179*bb4ee6a4SAndroid Build Coastguard Worker SocketAddr::V4(a) => {
180*bb4ee6a4SAndroid Build Coastguard Worker let sin = sockaddrv4_to_lib_c(&a);
181*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
182*bb4ee6a4SAndroid Build Coastguard Worker // Safe because this doesn't modify any memory and we check the return value.
183*bb4ee6a4SAndroid Build Coastguard Worker unsafe {
184*bb4ee6a4SAndroid Build Coastguard Worker libc::connect(
185*bb4ee6a4SAndroid Build Coastguard Worker self.as_raw_descriptor(),
186*bb4ee6a4SAndroid Build Coastguard Worker &sin as *const sockaddr_in as *const sockaddr,
187*bb4ee6a4SAndroid Build Coastguard Worker size_of::<sockaddr_in>() as socklen_t,
188*bb4ee6a4SAndroid Build Coastguard Worker )
189*bb4ee6a4SAndroid Build Coastguard Worker }
190*bb4ee6a4SAndroid Build Coastguard Worker }
191*bb4ee6a4SAndroid Build Coastguard Worker SocketAddr::V6(a) => {
192*bb4ee6a4SAndroid Build Coastguard Worker let sin6 = sockaddrv6_to_lib_c(&a);
193*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
194*bb4ee6a4SAndroid Build Coastguard Worker // Safe because this doesn't modify any memory and we check the return value.
195*bb4ee6a4SAndroid Build Coastguard Worker unsafe {
196*bb4ee6a4SAndroid Build Coastguard Worker libc::connect(
197*bb4ee6a4SAndroid Build Coastguard Worker self.as_raw_descriptor(),
198*bb4ee6a4SAndroid Build Coastguard Worker &sin6 as *const sockaddr_in6 as *const sockaddr,
199*bb4ee6a4SAndroid Build Coastguard Worker size_of::<sockaddr_in>() as socklen_t,
200*bb4ee6a4SAndroid Build Coastguard Worker )
201*bb4ee6a4SAndroid Build Coastguard Worker }
202*bb4ee6a4SAndroid Build Coastguard Worker }
203*bb4ee6a4SAndroid Build Coastguard Worker };
204*bb4ee6a4SAndroid Build Coastguard Worker
205*bb4ee6a4SAndroid Build Coastguard Worker if ret < 0 {
206*bb4ee6a4SAndroid Build Coastguard Worker let connect_err = io::Error::last_os_error();
207*bb4ee6a4SAndroid Build Coastguard Worker Err(connect_err)
208*bb4ee6a4SAndroid Build Coastguard Worker } else {
209*bb4ee6a4SAndroid Build Coastguard Worker Ok(TcpStream::from(self.descriptor))
210*bb4ee6a4SAndroid Build Coastguard Worker }
211*bb4ee6a4SAndroid Build Coastguard Worker }
212*bb4ee6a4SAndroid Build Coastguard Worker
listen(self) -> io::Result<TcpListener>213*bb4ee6a4SAndroid Build Coastguard Worker pub fn listen(self) -> io::Result<TcpListener> {
214*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
215*bb4ee6a4SAndroid Build Coastguard Worker // Safe because this doesn't modify any memory and we check the return value.
216*bb4ee6a4SAndroid Build Coastguard Worker let ret = unsafe { libc::listen(self.as_raw_descriptor(), 1) };
217*bb4ee6a4SAndroid Build Coastguard Worker if ret < 0 {
218*bb4ee6a4SAndroid Build Coastguard Worker let listen_err = io::Error::last_os_error();
219*bb4ee6a4SAndroid Build Coastguard Worker Err(listen_err)
220*bb4ee6a4SAndroid Build Coastguard Worker } else {
221*bb4ee6a4SAndroid Build Coastguard Worker Ok(TcpListener::from(self.descriptor))
222*bb4ee6a4SAndroid Build Coastguard Worker }
223*bb4ee6a4SAndroid Build Coastguard Worker }
224*bb4ee6a4SAndroid Build Coastguard Worker
225*bb4ee6a4SAndroid Build Coastguard Worker /// Returns the port that this socket is bound to. This can only succeed after bind is called.
local_port(&self) -> io::Result<u16>226*bb4ee6a4SAndroid Build Coastguard Worker pub fn local_port(&self) -> io::Result<u16> {
227*bb4ee6a4SAndroid Build Coastguard Worker match self.inet_version {
228*bb4ee6a4SAndroid Build Coastguard Worker InetVersion::V4 => {
229*bb4ee6a4SAndroid Build Coastguard Worker let mut sin = sockaddrv4_to_lib_c(&SocketAddrV4::new(Ipv4Addr::new(0, 0, 0, 0), 0));
230*bb4ee6a4SAndroid Build Coastguard Worker
231*bb4ee6a4SAndroid Build Coastguard Worker let mut addrlen = size_of::<sockaddr_in>() as socklen_t;
232*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
233*bb4ee6a4SAndroid Build Coastguard Worker // Safe because we give a valid pointer for addrlen and check the length.
234*bb4ee6a4SAndroid Build Coastguard Worker let ret = unsafe {
235*bb4ee6a4SAndroid Build Coastguard Worker // Get the socket address that was actually bound.
236*bb4ee6a4SAndroid Build Coastguard Worker libc::getsockname(
237*bb4ee6a4SAndroid Build Coastguard Worker self.as_raw_descriptor(),
238*bb4ee6a4SAndroid Build Coastguard Worker &mut sin as *mut sockaddr_in as *mut sockaddr,
239*bb4ee6a4SAndroid Build Coastguard Worker &mut addrlen as *mut socklen_t,
240*bb4ee6a4SAndroid Build Coastguard Worker )
241*bb4ee6a4SAndroid Build Coastguard Worker };
242*bb4ee6a4SAndroid Build Coastguard Worker if ret < 0 {
243*bb4ee6a4SAndroid Build Coastguard Worker let getsockname_err = io::Error::last_os_error();
244*bb4ee6a4SAndroid Build Coastguard Worker Err(getsockname_err)
245*bb4ee6a4SAndroid Build Coastguard Worker } else {
246*bb4ee6a4SAndroid Build Coastguard Worker // If this doesn't match, it's not safe to get the port out of the sockaddr.
247*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(addrlen as usize, size_of::<sockaddr_in>());
248*bb4ee6a4SAndroid Build Coastguard Worker
249*bb4ee6a4SAndroid Build Coastguard Worker Ok(u16::from_be(sin.sin_port))
250*bb4ee6a4SAndroid Build Coastguard Worker }
251*bb4ee6a4SAndroid Build Coastguard Worker }
252*bb4ee6a4SAndroid Build Coastguard Worker InetVersion::V6 => {
253*bb4ee6a4SAndroid Build Coastguard Worker let mut sin6 = sockaddrv6_to_lib_c(&SocketAddrV6::new(
254*bb4ee6a4SAndroid Build Coastguard Worker Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0),
255*bb4ee6a4SAndroid Build Coastguard Worker 0,
256*bb4ee6a4SAndroid Build Coastguard Worker 0,
257*bb4ee6a4SAndroid Build Coastguard Worker 0,
258*bb4ee6a4SAndroid Build Coastguard Worker ));
259*bb4ee6a4SAndroid Build Coastguard Worker
260*bb4ee6a4SAndroid Build Coastguard Worker let mut addrlen = size_of::<sockaddr_in6>() as socklen_t;
261*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
262*bb4ee6a4SAndroid Build Coastguard Worker // Safe because we give a valid pointer for addrlen and check the length.
263*bb4ee6a4SAndroid Build Coastguard Worker let ret = unsafe {
264*bb4ee6a4SAndroid Build Coastguard Worker // Get the socket address that was actually bound.
265*bb4ee6a4SAndroid Build Coastguard Worker libc::getsockname(
266*bb4ee6a4SAndroid Build Coastguard Worker self.as_raw_descriptor(),
267*bb4ee6a4SAndroid Build Coastguard Worker &mut sin6 as *mut sockaddr_in6 as *mut sockaddr,
268*bb4ee6a4SAndroid Build Coastguard Worker &mut addrlen as *mut socklen_t,
269*bb4ee6a4SAndroid Build Coastguard Worker )
270*bb4ee6a4SAndroid Build Coastguard Worker };
271*bb4ee6a4SAndroid Build Coastguard Worker if ret < 0 {
272*bb4ee6a4SAndroid Build Coastguard Worker let getsockname_err = io::Error::last_os_error();
273*bb4ee6a4SAndroid Build Coastguard Worker Err(getsockname_err)
274*bb4ee6a4SAndroid Build Coastguard Worker } else {
275*bb4ee6a4SAndroid Build Coastguard Worker // If this doesn't match, it's not safe to get the port out of the sockaddr.
276*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(addrlen as usize, size_of::<sockaddr_in>());
277*bb4ee6a4SAndroid Build Coastguard Worker
278*bb4ee6a4SAndroid Build Coastguard Worker Ok(u16::from_be(sin6.sin6_port))
279*bb4ee6a4SAndroid Build Coastguard Worker }
280*bb4ee6a4SAndroid Build Coastguard Worker }
281*bb4ee6a4SAndroid Build Coastguard Worker }
282*bb4ee6a4SAndroid Build Coastguard Worker }
283*bb4ee6a4SAndroid Build Coastguard Worker }
284*bb4ee6a4SAndroid Build Coastguard Worker
285*bb4ee6a4SAndroid Build Coastguard Worker impl AsRawDescriptor for TcpSocket {
as_raw_descriptor(&self) -> RawDescriptor286*bb4ee6a4SAndroid Build Coastguard Worker fn as_raw_descriptor(&self) -> RawDescriptor {
287*bb4ee6a4SAndroid Build Coastguard Worker self.descriptor.as_raw_descriptor()
288*bb4ee6a4SAndroid Build Coastguard Worker }
289*bb4ee6a4SAndroid Build Coastguard Worker }
290*bb4ee6a4SAndroid Build Coastguard Worker
291*bb4ee6a4SAndroid Build Coastguard Worker // Offset of sun_path in structure sockaddr_un.
sun_path_offset() -> usize292*bb4ee6a4SAndroid Build Coastguard Worker pub(in crate::sys) fn sun_path_offset() -> usize {
293*bb4ee6a4SAndroid Build Coastguard Worker // Prefer 0 to null() so that we do not need to subtract from the `sub_path` pointer.
294*bb4ee6a4SAndroid Build Coastguard Worker #[allow(clippy::zero_ptr)]
295*bb4ee6a4SAndroid Build Coastguard Worker let addr = 0 as *const libc::sockaddr_un;
296*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
297*bb4ee6a4SAndroid Build Coastguard Worker // Safe because we only use the dereference to create a pointer to the desired field in
298*bb4ee6a4SAndroid Build Coastguard Worker // calculating the offset.
299*bb4ee6a4SAndroid Build Coastguard Worker unsafe { &(*addr).sun_path as *const _ as usize }
300*bb4ee6a4SAndroid Build Coastguard Worker }
301*bb4ee6a4SAndroid Build Coastguard Worker
302*bb4ee6a4SAndroid Build Coastguard Worker /// A Unix `SOCK_SEQPACKET` socket point to given `path`
303*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Debug, Serialize, Deserialize)]
304*bb4ee6a4SAndroid Build Coastguard Worker pub struct UnixSeqpacket(SafeDescriptor);
305*bb4ee6a4SAndroid Build Coastguard Worker
306*bb4ee6a4SAndroid Build Coastguard Worker impl UnixSeqpacket {
307*bb4ee6a4SAndroid Build Coastguard Worker /// Open a `SOCK_SEQPACKET` connection to socket named by `path`.
308*bb4ee6a4SAndroid Build Coastguard Worker ///
309*bb4ee6a4SAndroid Build Coastguard Worker /// # Arguments
310*bb4ee6a4SAndroid Build Coastguard Worker /// * `path` - Path to `SOCK_SEQPACKET` socket
311*bb4ee6a4SAndroid Build Coastguard Worker ///
312*bb4ee6a4SAndroid Build Coastguard Worker /// # Returns
313*bb4ee6a4SAndroid Build Coastguard Worker /// A `UnixSeqpacket` structure point to the socket
314*bb4ee6a4SAndroid Build Coastguard Worker ///
315*bb4ee6a4SAndroid Build Coastguard Worker /// # Errors
316*bb4ee6a4SAndroid Build Coastguard Worker /// Return `io::Error` when error occurs.
connect<P: AsRef<Path>>(path: P) -> io::Result<Self>317*bb4ee6a4SAndroid Build Coastguard Worker pub fn connect<P: AsRef<Path>>(path: P) -> io::Result<Self> {
318*bb4ee6a4SAndroid Build Coastguard Worker let descriptor = socket(libc::AF_UNIX, libc::SOCK_SEQPACKET, 0)?;
319*bb4ee6a4SAndroid Build Coastguard Worker let (addr, len) = sockaddr_un(path.as_ref())?;
320*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
321*bb4ee6a4SAndroid Build Coastguard Worker // Safe connect since we handle the error and use the right length generated from
322*bb4ee6a4SAndroid Build Coastguard Worker // `sockaddr_un`.
323*bb4ee6a4SAndroid Build Coastguard Worker unsafe {
324*bb4ee6a4SAndroid Build Coastguard Worker let ret = libc::connect(
325*bb4ee6a4SAndroid Build Coastguard Worker descriptor.as_raw_descriptor(),
326*bb4ee6a4SAndroid Build Coastguard Worker &addr as *const _ as *const _,
327*bb4ee6a4SAndroid Build Coastguard Worker len,
328*bb4ee6a4SAndroid Build Coastguard Worker );
329*bb4ee6a4SAndroid Build Coastguard Worker if ret < 0 {
330*bb4ee6a4SAndroid Build Coastguard Worker return Err(io::Error::last_os_error());
331*bb4ee6a4SAndroid Build Coastguard Worker }
332*bb4ee6a4SAndroid Build Coastguard Worker }
333*bb4ee6a4SAndroid Build Coastguard Worker Ok(UnixSeqpacket(descriptor))
334*bb4ee6a4SAndroid Build Coastguard Worker }
335*bb4ee6a4SAndroid Build Coastguard Worker
336*bb4ee6a4SAndroid Build Coastguard Worker /// Clone the underlying FD.
try_clone(&self) -> io::Result<Self>337*bb4ee6a4SAndroid Build Coastguard Worker pub fn try_clone(&self) -> io::Result<Self> {
338*bb4ee6a4SAndroid Build Coastguard Worker Ok(Self(self.0.try_clone()?))
339*bb4ee6a4SAndroid Build Coastguard Worker }
340*bb4ee6a4SAndroid Build Coastguard Worker
341*bb4ee6a4SAndroid Build Coastguard Worker /// Gets the number of bytes that can be read from this socket without blocking.
get_readable_bytes(&self) -> io::Result<usize>342*bb4ee6a4SAndroid Build Coastguard Worker pub fn get_readable_bytes(&self) -> io::Result<usize> {
343*bb4ee6a4SAndroid Build Coastguard Worker let mut byte_count = 0i32;
344*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
345*bb4ee6a4SAndroid Build Coastguard Worker // Safe because self has valid raw descriptor and return value are checked.
346*bb4ee6a4SAndroid Build Coastguard Worker let ret = unsafe { libc::ioctl(self.as_raw_descriptor(), libc::FIONREAD, &mut byte_count) };
347*bb4ee6a4SAndroid Build Coastguard Worker if ret < 0 {
348*bb4ee6a4SAndroid Build Coastguard Worker Err(io::Error::last_os_error())
349*bb4ee6a4SAndroid Build Coastguard Worker } else {
350*bb4ee6a4SAndroid Build Coastguard Worker Ok(byte_count as usize)
351*bb4ee6a4SAndroid Build Coastguard Worker }
352*bb4ee6a4SAndroid Build Coastguard Worker }
353*bb4ee6a4SAndroid Build Coastguard Worker
354*bb4ee6a4SAndroid Build Coastguard Worker /// Gets the number of bytes in the next packet. This blocks as if `recv` were called,
355*bb4ee6a4SAndroid Build Coastguard Worker /// respecting the blocking and timeout settings of the underlying socket.
next_packet_size(&self) -> io::Result<usize>356*bb4ee6a4SAndroid Build Coastguard Worker pub fn next_packet_size(&self) -> io::Result<usize> {
357*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(not(debug_assertions))]
358*bb4ee6a4SAndroid Build Coastguard Worker let buf = null_mut();
359*bb4ee6a4SAndroid Build Coastguard Worker // Work around for qemu's syscall translation which will reject null pointers in recvfrom.
360*bb4ee6a4SAndroid Build Coastguard Worker // This only matters for running the unit tests for a non-native architecture. See the
361*bb4ee6a4SAndroid Build Coastguard Worker // upstream thread for the qemu fix:
362*bb4ee6a4SAndroid Build Coastguard Worker // https://lists.nongnu.org/archive/html/qemu-devel/2021-03/msg09027.html
363*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(debug_assertions)]
364*bb4ee6a4SAndroid Build Coastguard Worker let buf = &mut 0 as *mut _ as *mut _;
365*bb4ee6a4SAndroid Build Coastguard Worker
366*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
367*bb4ee6a4SAndroid Build Coastguard Worker // This form of recvfrom doesn't modify any data because all null pointers are used. We only
368*bb4ee6a4SAndroid Build Coastguard Worker // use the return value and check for errors on an FD owned by this structure.
369*bb4ee6a4SAndroid Build Coastguard Worker let ret = unsafe {
370*bb4ee6a4SAndroid Build Coastguard Worker recvfrom(
371*bb4ee6a4SAndroid Build Coastguard Worker self.as_raw_descriptor(),
372*bb4ee6a4SAndroid Build Coastguard Worker buf,
373*bb4ee6a4SAndroid Build Coastguard Worker 0,
374*bb4ee6a4SAndroid Build Coastguard Worker MSG_TRUNC | MSG_PEEK,
375*bb4ee6a4SAndroid Build Coastguard Worker null_mut(),
376*bb4ee6a4SAndroid Build Coastguard Worker null_mut(),
377*bb4ee6a4SAndroid Build Coastguard Worker )
378*bb4ee6a4SAndroid Build Coastguard Worker };
379*bb4ee6a4SAndroid Build Coastguard Worker if ret < 0 {
380*bb4ee6a4SAndroid Build Coastguard Worker Err(io::Error::last_os_error())
381*bb4ee6a4SAndroid Build Coastguard Worker } else {
382*bb4ee6a4SAndroid Build Coastguard Worker Ok(ret as usize)
383*bb4ee6a4SAndroid Build Coastguard Worker }
384*bb4ee6a4SAndroid Build Coastguard Worker }
385*bb4ee6a4SAndroid Build Coastguard Worker
386*bb4ee6a4SAndroid Build Coastguard Worker /// Write data from a given buffer to the socket fd
387*bb4ee6a4SAndroid Build Coastguard Worker ///
388*bb4ee6a4SAndroid Build Coastguard Worker /// # Arguments
389*bb4ee6a4SAndroid Build Coastguard Worker /// * `buf` - A reference to the data buffer.
390*bb4ee6a4SAndroid Build Coastguard Worker ///
391*bb4ee6a4SAndroid Build Coastguard Worker /// # Returns
392*bb4ee6a4SAndroid Build Coastguard Worker /// * `usize` - The size of bytes written to the buffer.
393*bb4ee6a4SAndroid Build Coastguard Worker ///
394*bb4ee6a4SAndroid Build Coastguard Worker /// # Errors
395*bb4ee6a4SAndroid Build Coastguard Worker /// Returns error when `libc::write` failed.
send(&self, buf: &[u8]) -> io::Result<usize>396*bb4ee6a4SAndroid Build Coastguard Worker pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
397*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
398*bb4ee6a4SAndroid Build Coastguard Worker // Safe since we make sure the input `count` == `buf.len()` and handle the returned error.
399*bb4ee6a4SAndroid Build Coastguard Worker unsafe {
400*bb4ee6a4SAndroid Build Coastguard Worker let ret = libc::write(
401*bb4ee6a4SAndroid Build Coastguard Worker self.as_raw_descriptor(),
402*bb4ee6a4SAndroid Build Coastguard Worker buf.as_ptr() as *const _,
403*bb4ee6a4SAndroid Build Coastguard Worker buf.len(),
404*bb4ee6a4SAndroid Build Coastguard Worker );
405*bb4ee6a4SAndroid Build Coastguard Worker if ret < 0 {
406*bb4ee6a4SAndroid Build Coastguard Worker Err(io::Error::last_os_error())
407*bb4ee6a4SAndroid Build Coastguard Worker } else {
408*bb4ee6a4SAndroid Build Coastguard Worker Ok(ret as usize)
409*bb4ee6a4SAndroid Build Coastguard Worker }
410*bb4ee6a4SAndroid Build Coastguard Worker }
411*bb4ee6a4SAndroid Build Coastguard Worker }
412*bb4ee6a4SAndroid Build Coastguard Worker
413*bb4ee6a4SAndroid Build Coastguard Worker /// Read data from the socket fd to a given buffer
414*bb4ee6a4SAndroid Build Coastguard Worker ///
415*bb4ee6a4SAndroid Build Coastguard Worker /// # Arguments
416*bb4ee6a4SAndroid Build Coastguard Worker /// * `buf` - A mut reference to the data buffer.
417*bb4ee6a4SAndroid Build Coastguard Worker ///
418*bb4ee6a4SAndroid Build Coastguard Worker /// # Returns
419*bb4ee6a4SAndroid Build Coastguard Worker /// * `usize` - The size of bytes read to the buffer.
420*bb4ee6a4SAndroid Build Coastguard Worker ///
421*bb4ee6a4SAndroid Build Coastguard Worker /// # Errors
422*bb4ee6a4SAndroid Build Coastguard Worker /// Returns error when `libc::read` failed.
recv(&self, buf: &mut [u8]) -> io::Result<usize>423*bb4ee6a4SAndroid Build Coastguard Worker pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
424*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
425*bb4ee6a4SAndroid Build Coastguard Worker // Safe since we make sure the input `count` == `buf.len()` and handle the returned error.
426*bb4ee6a4SAndroid Build Coastguard Worker unsafe {
427*bb4ee6a4SAndroid Build Coastguard Worker let ret = libc::read(
428*bb4ee6a4SAndroid Build Coastguard Worker self.as_raw_descriptor(),
429*bb4ee6a4SAndroid Build Coastguard Worker buf.as_mut_ptr() as *mut _,
430*bb4ee6a4SAndroid Build Coastguard Worker buf.len(),
431*bb4ee6a4SAndroid Build Coastguard Worker );
432*bb4ee6a4SAndroid Build Coastguard Worker if ret < 0 {
433*bb4ee6a4SAndroid Build Coastguard Worker Err(io::Error::last_os_error())
434*bb4ee6a4SAndroid Build Coastguard Worker } else {
435*bb4ee6a4SAndroid Build Coastguard Worker Ok(ret as usize)
436*bb4ee6a4SAndroid Build Coastguard Worker }
437*bb4ee6a4SAndroid Build Coastguard Worker }
438*bb4ee6a4SAndroid Build Coastguard Worker }
439*bb4ee6a4SAndroid Build Coastguard Worker
440*bb4ee6a4SAndroid Build Coastguard Worker /// Read data from the socket fd to a given `Vec`, resizing it to the received packet's size.
441*bb4ee6a4SAndroid Build Coastguard Worker ///
442*bb4ee6a4SAndroid Build Coastguard Worker /// # Arguments
443*bb4ee6a4SAndroid Build Coastguard Worker /// * `buf` - A mut reference to a `Vec` to resize and read into.
444*bb4ee6a4SAndroid Build Coastguard Worker ///
445*bb4ee6a4SAndroid Build Coastguard Worker /// # Errors
446*bb4ee6a4SAndroid Build Coastguard Worker /// Returns error when `libc::read` or `get_readable_bytes` failed.
recv_to_vec(&self, buf: &mut Vec<u8>) -> io::Result<()>447*bb4ee6a4SAndroid Build Coastguard Worker pub fn recv_to_vec(&self, buf: &mut Vec<u8>) -> io::Result<()> {
448*bb4ee6a4SAndroid Build Coastguard Worker let packet_size = self.next_packet_size()?;
449*bb4ee6a4SAndroid Build Coastguard Worker buf.resize(packet_size, 0);
450*bb4ee6a4SAndroid Build Coastguard Worker let read_bytes = self.recv(buf)?;
451*bb4ee6a4SAndroid Build Coastguard Worker buf.resize(read_bytes, 0);
452*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
453*bb4ee6a4SAndroid Build Coastguard Worker }
454*bb4ee6a4SAndroid Build Coastguard Worker
455*bb4ee6a4SAndroid Build Coastguard Worker /// Read data from the socket fd to a new `Vec`.
456*bb4ee6a4SAndroid Build Coastguard Worker ///
457*bb4ee6a4SAndroid Build Coastguard Worker /// # Returns
458*bb4ee6a4SAndroid Build Coastguard Worker /// * `vec` - A new `Vec` with the entire received packet.
459*bb4ee6a4SAndroid Build Coastguard Worker ///
460*bb4ee6a4SAndroid Build Coastguard Worker /// # Errors
461*bb4ee6a4SAndroid Build Coastguard Worker /// Returns error when `libc::read` or `get_readable_bytes` failed.
recv_as_vec(&self) -> io::Result<Vec<u8>>462*bb4ee6a4SAndroid Build Coastguard Worker pub fn recv_as_vec(&self) -> io::Result<Vec<u8>> {
463*bb4ee6a4SAndroid Build Coastguard Worker let mut buf = Vec::new();
464*bb4ee6a4SAndroid Build Coastguard Worker self.recv_to_vec(&mut buf)?;
465*bb4ee6a4SAndroid Build Coastguard Worker Ok(buf)
466*bb4ee6a4SAndroid Build Coastguard Worker }
467*bb4ee6a4SAndroid Build Coastguard Worker
468*bb4ee6a4SAndroid Build Coastguard Worker #[allow(clippy::useless_conversion)]
set_timeout(&self, timeout: Option<Duration>, kind: libc::c_int) -> io::Result<()>469*bb4ee6a4SAndroid Build Coastguard Worker fn set_timeout(&self, timeout: Option<Duration>, kind: libc::c_int) -> io::Result<()> {
470*bb4ee6a4SAndroid Build Coastguard Worker let timeval = match timeout {
471*bb4ee6a4SAndroid Build Coastguard Worker Some(t) => {
472*bb4ee6a4SAndroid Build Coastguard Worker if t.as_secs() == 0 && t.subsec_micros() == 0 {
473*bb4ee6a4SAndroid Build Coastguard Worker return Err(io::Error::new(
474*bb4ee6a4SAndroid Build Coastguard Worker io::ErrorKind::InvalidInput,
475*bb4ee6a4SAndroid Build Coastguard Worker "zero timeout duration is invalid",
476*bb4ee6a4SAndroid Build Coastguard Worker ));
477*bb4ee6a4SAndroid Build Coastguard Worker }
478*bb4ee6a4SAndroid Build Coastguard Worker // subsec_micros fits in i32 because it is defined to be less than one million.
479*bb4ee6a4SAndroid Build Coastguard Worker let nsec = t.subsec_micros() as i32;
480*bb4ee6a4SAndroid Build Coastguard Worker libc::timeval {
481*bb4ee6a4SAndroid Build Coastguard Worker tv_sec: t.as_secs() as libc::time_t,
482*bb4ee6a4SAndroid Build Coastguard Worker tv_usec: libc::suseconds_t::from(nsec),
483*bb4ee6a4SAndroid Build Coastguard Worker }
484*bb4ee6a4SAndroid Build Coastguard Worker }
485*bb4ee6a4SAndroid Build Coastguard Worker None => libc::timeval {
486*bb4ee6a4SAndroid Build Coastguard Worker tv_sec: 0,
487*bb4ee6a4SAndroid Build Coastguard Worker tv_usec: 0,
488*bb4ee6a4SAndroid Build Coastguard Worker },
489*bb4ee6a4SAndroid Build Coastguard Worker };
490*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
491*bb4ee6a4SAndroid Build Coastguard Worker // Safe because we own the fd, and the length of the pointer's data is the same as the
492*bb4ee6a4SAndroid Build Coastguard Worker // passed in length parameter. The level argument is valid, the kind is assumed to be valid,
493*bb4ee6a4SAndroid Build Coastguard Worker // and the return value is checked.
494*bb4ee6a4SAndroid Build Coastguard Worker let ret = unsafe {
495*bb4ee6a4SAndroid Build Coastguard Worker libc::setsockopt(
496*bb4ee6a4SAndroid Build Coastguard Worker self.as_raw_descriptor(),
497*bb4ee6a4SAndroid Build Coastguard Worker libc::SOL_SOCKET,
498*bb4ee6a4SAndroid Build Coastguard Worker kind,
499*bb4ee6a4SAndroid Build Coastguard Worker &timeval as *const libc::timeval as *const libc::c_void,
500*bb4ee6a4SAndroid Build Coastguard Worker mem::size_of::<libc::timeval>() as libc::socklen_t,
501*bb4ee6a4SAndroid Build Coastguard Worker )
502*bb4ee6a4SAndroid Build Coastguard Worker };
503*bb4ee6a4SAndroid Build Coastguard Worker if ret < 0 {
504*bb4ee6a4SAndroid Build Coastguard Worker Err(io::Error::last_os_error())
505*bb4ee6a4SAndroid Build Coastguard Worker } else {
506*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
507*bb4ee6a4SAndroid Build Coastguard Worker }
508*bb4ee6a4SAndroid Build Coastguard Worker }
509*bb4ee6a4SAndroid Build Coastguard Worker
510*bb4ee6a4SAndroid Build Coastguard Worker /// Sets or removes the timeout for read/recv operations on this socket.
set_read_timeout(&self, timeout: Option<Duration>) -> io::Result<()>511*bb4ee6a4SAndroid Build Coastguard Worker pub fn set_read_timeout(&self, timeout: Option<Duration>) -> io::Result<()> {
512*bb4ee6a4SAndroid Build Coastguard Worker self.set_timeout(timeout, libc::SO_RCVTIMEO)
513*bb4ee6a4SAndroid Build Coastguard Worker }
514*bb4ee6a4SAndroid Build Coastguard Worker
515*bb4ee6a4SAndroid Build Coastguard Worker /// Sets or removes the timeout for write/send operations on this socket.
set_write_timeout(&self, timeout: Option<Duration>) -> io::Result<()>516*bb4ee6a4SAndroid Build Coastguard Worker pub fn set_write_timeout(&self, timeout: Option<Duration>) -> io::Result<()> {
517*bb4ee6a4SAndroid Build Coastguard Worker self.set_timeout(timeout, libc::SO_SNDTIMEO)
518*bb4ee6a4SAndroid Build Coastguard Worker }
519*bb4ee6a4SAndroid Build Coastguard Worker
520*bb4ee6a4SAndroid Build Coastguard Worker /// Sets the blocking mode for this socket.
set_nonblocking(&self, nonblocking: bool) -> io::Result<()>521*bb4ee6a4SAndroid Build Coastguard Worker pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
522*bb4ee6a4SAndroid Build Coastguard Worker let mut nonblocking = nonblocking as libc::c_int;
523*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
524*bb4ee6a4SAndroid Build Coastguard Worker // Safe because the return value is checked, and this ioctl call sets the nonblocking mode
525*bb4ee6a4SAndroid Build Coastguard Worker // and does not continue holding the file descriptor after the call.
526*bb4ee6a4SAndroid Build Coastguard Worker let ret = unsafe { libc::ioctl(self.as_raw_descriptor(), libc::FIONBIO, &mut nonblocking) };
527*bb4ee6a4SAndroid Build Coastguard Worker if ret < 0 {
528*bb4ee6a4SAndroid Build Coastguard Worker Err(io::Error::last_os_error())
529*bb4ee6a4SAndroid Build Coastguard Worker } else {
530*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
531*bb4ee6a4SAndroid Build Coastguard Worker }
532*bb4ee6a4SAndroid Build Coastguard Worker }
533*bb4ee6a4SAndroid Build Coastguard Worker }
534*bb4ee6a4SAndroid Build Coastguard Worker
535*bb4ee6a4SAndroid Build Coastguard Worker impl From<UnixSeqpacket> for SafeDescriptor {
from(s: UnixSeqpacket) -> Self536*bb4ee6a4SAndroid Build Coastguard Worker fn from(s: UnixSeqpacket) -> Self {
537*bb4ee6a4SAndroid Build Coastguard Worker s.0
538*bb4ee6a4SAndroid Build Coastguard Worker }
539*bb4ee6a4SAndroid Build Coastguard Worker }
540*bb4ee6a4SAndroid Build Coastguard Worker
541*bb4ee6a4SAndroid Build Coastguard Worker impl From<SafeDescriptor> for UnixSeqpacket {
from(s: SafeDescriptor) -> Self542*bb4ee6a4SAndroid Build Coastguard Worker fn from(s: SafeDescriptor) -> Self {
543*bb4ee6a4SAndroid Build Coastguard Worker Self(s)
544*bb4ee6a4SAndroid Build Coastguard Worker }
545*bb4ee6a4SAndroid Build Coastguard Worker }
546*bb4ee6a4SAndroid Build Coastguard Worker
547*bb4ee6a4SAndroid Build Coastguard Worker impl FromRawDescriptor for UnixSeqpacket {
from_raw_descriptor(descriptor: RawDescriptor) -> Self548*bb4ee6a4SAndroid Build Coastguard Worker unsafe fn from_raw_descriptor(descriptor: RawDescriptor) -> Self {
549*bb4ee6a4SAndroid Build Coastguard Worker Self(SafeDescriptor::from_raw_descriptor(descriptor))
550*bb4ee6a4SAndroid Build Coastguard Worker }
551*bb4ee6a4SAndroid Build Coastguard Worker }
552*bb4ee6a4SAndroid Build Coastguard Worker
553*bb4ee6a4SAndroid Build Coastguard Worker impl AsRawDescriptor for UnixSeqpacket {
as_raw_descriptor(&self) -> RawDescriptor554*bb4ee6a4SAndroid Build Coastguard Worker fn as_raw_descriptor(&self) -> RawDescriptor {
555*bb4ee6a4SAndroid Build Coastguard Worker self.0.as_raw_descriptor()
556*bb4ee6a4SAndroid Build Coastguard Worker }
557*bb4ee6a4SAndroid Build Coastguard Worker }
558*bb4ee6a4SAndroid Build Coastguard Worker
559*bb4ee6a4SAndroid Build Coastguard Worker impl IntoRawDescriptor for UnixSeqpacket {
into_raw_descriptor(self) -> RawDescriptor560*bb4ee6a4SAndroid Build Coastguard Worker fn into_raw_descriptor(self) -> RawDescriptor {
561*bb4ee6a4SAndroid Build Coastguard Worker self.0.into_raw_descriptor()
562*bb4ee6a4SAndroid Build Coastguard Worker }
563*bb4ee6a4SAndroid Build Coastguard Worker }
564*bb4ee6a4SAndroid Build Coastguard Worker
565*bb4ee6a4SAndroid Build Coastguard Worker impl io::Read for UnixSeqpacket {
read(&mut self, buf: &mut [u8]) -> io::Result<usize>566*bb4ee6a4SAndroid Build Coastguard Worker fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
567*bb4ee6a4SAndroid Build Coastguard Worker self.recv(buf)
568*bb4ee6a4SAndroid Build Coastguard Worker }
569*bb4ee6a4SAndroid Build Coastguard Worker }
570*bb4ee6a4SAndroid Build Coastguard Worker
571*bb4ee6a4SAndroid Build Coastguard Worker impl io::Write for UnixSeqpacket {
write(&mut self, buf: &[u8]) -> io::Result<usize>572*bb4ee6a4SAndroid Build Coastguard Worker fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
573*bb4ee6a4SAndroid Build Coastguard Worker self.send(buf)
574*bb4ee6a4SAndroid Build Coastguard Worker }
575*bb4ee6a4SAndroid Build Coastguard Worker
flush(&mut self) -> io::Result<()>576*bb4ee6a4SAndroid Build Coastguard Worker fn flush(&mut self) -> io::Result<()> {
577*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
578*bb4ee6a4SAndroid Build Coastguard Worker }
579*bb4ee6a4SAndroid Build Coastguard Worker }
580*bb4ee6a4SAndroid Build Coastguard Worker
581*bb4ee6a4SAndroid Build Coastguard Worker /// Like a `UnixListener` but for accepting `UnixSeqpacket` type sockets.
582*bb4ee6a4SAndroid Build Coastguard Worker pub struct UnixSeqpacketListener {
583*bb4ee6a4SAndroid Build Coastguard Worker descriptor: SafeDescriptor,
584*bb4ee6a4SAndroid Build Coastguard Worker no_path: bool,
585*bb4ee6a4SAndroid Build Coastguard Worker }
586*bb4ee6a4SAndroid Build Coastguard Worker
587*bb4ee6a4SAndroid Build Coastguard Worker impl UnixSeqpacketListener {
588*bb4ee6a4SAndroid Build Coastguard Worker /// Creates a new `UnixSeqpacketListener` bound to the given path.
bind<P: AsRef<Path>>(path: P) -> io::Result<Self>589*bb4ee6a4SAndroid Build Coastguard Worker pub fn bind<P: AsRef<Path>>(path: P) -> io::Result<Self> {
590*bb4ee6a4SAndroid Build Coastguard Worker if path.as_ref().starts_with("/proc/self/fd/") {
591*bb4ee6a4SAndroid Build Coastguard Worker let fd = path
592*bb4ee6a4SAndroid Build Coastguard Worker .as_ref()
593*bb4ee6a4SAndroid Build Coastguard Worker .file_name()
594*bb4ee6a4SAndroid Build Coastguard Worker .expect("Failed to get fd filename")
595*bb4ee6a4SAndroid Build Coastguard Worker .to_str()
596*bb4ee6a4SAndroid Build Coastguard Worker .expect("fd filename should be unicode")
597*bb4ee6a4SAndroid Build Coastguard Worker .parse::<i32>()
598*bb4ee6a4SAndroid Build Coastguard Worker .expect("fd should be an integer");
599*bb4ee6a4SAndroid Build Coastguard Worker let mut result: c_int = 0;
600*bb4ee6a4SAndroid Build Coastguard Worker let mut result_len = size_of::<c_int>() as libc::socklen_t;
601*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY: Safe because fd and other args are valid and the return value is checked.
602*bb4ee6a4SAndroid Build Coastguard Worker let ret = unsafe {
603*bb4ee6a4SAndroid Build Coastguard Worker libc::getsockopt(
604*bb4ee6a4SAndroid Build Coastguard Worker fd,
605*bb4ee6a4SAndroid Build Coastguard Worker libc::SOL_SOCKET,
606*bb4ee6a4SAndroid Build Coastguard Worker libc::SO_ACCEPTCONN,
607*bb4ee6a4SAndroid Build Coastguard Worker &mut result as *mut _ as *mut libc::c_void,
608*bb4ee6a4SAndroid Build Coastguard Worker &mut result_len,
609*bb4ee6a4SAndroid Build Coastguard Worker )
610*bb4ee6a4SAndroid Build Coastguard Worker };
611*bb4ee6a4SAndroid Build Coastguard Worker if ret < 0 {
612*bb4ee6a4SAndroid Build Coastguard Worker return Err(io::Error::last_os_error());
613*bb4ee6a4SAndroid Build Coastguard Worker }
614*bb4ee6a4SAndroid Build Coastguard Worker if result != 1 {
615*bb4ee6a4SAndroid Build Coastguard Worker return Err(io::Error::new(
616*bb4ee6a4SAndroid Build Coastguard Worker io::ErrorKind::InvalidInput,
617*bb4ee6a4SAndroid Build Coastguard Worker "specified descriptor is not a listening socket",
618*bb4ee6a4SAndroid Build Coastguard Worker ));
619*bb4ee6a4SAndroid Build Coastguard Worker }
620*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
621*bb4ee6a4SAndroid Build Coastguard Worker // Safe because we validated the socket file descriptor.
622*bb4ee6a4SAndroid Build Coastguard Worker let descriptor = unsafe { SafeDescriptor::from_raw_descriptor(fd) };
623*bb4ee6a4SAndroid Build Coastguard Worker return Ok(UnixSeqpacketListener {
624*bb4ee6a4SAndroid Build Coastguard Worker descriptor,
625*bb4ee6a4SAndroid Build Coastguard Worker no_path: true,
626*bb4ee6a4SAndroid Build Coastguard Worker });
627*bb4ee6a4SAndroid Build Coastguard Worker }
628*bb4ee6a4SAndroid Build Coastguard Worker
629*bb4ee6a4SAndroid Build Coastguard Worker let descriptor = socket(libc::AF_UNIX, libc::SOCK_SEQPACKET, 0)?;
630*bb4ee6a4SAndroid Build Coastguard Worker let (addr, len) = sockaddr_un(path.as_ref())?;
631*bb4ee6a4SAndroid Build Coastguard Worker
632*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
633*bb4ee6a4SAndroid Build Coastguard Worker // Safe connect since we handle the error and use the right length generated from
634*bb4ee6a4SAndroid Build Coastguard Worker // `sockaddr_un`.
635*bb4ee6a4SAndroid Build Coastguard Worker unsafe {
636*bb4ee6a4SAndroid Build Coastguard Worker let ret = handle_eintr_errno!(libc::bind(
637*bb4ee6a4SAndroid Build Coastguard Worker descriptor.as_raw_descriptor(),
638*bb4ee6a4SAndroid Build Coastguard Worker &addr as *const _ as *const _,
639*bb4ee6a4SAndroid Build Coastguard Worker len
640*bb4ee6a4SAndroid Build Coastguard Worker ));
641*bb4ee6a4SAndroid Build Coastguard Worker if ret < 0 {
642*bb4ee6a4SAndroid Build Coastguard Worker return Err(io::Error::last_os_error());
643*bb4ee6a4SAndroid Build Coastguard Worker }
644*bb4ee6a4SAndroid Build Coastguard Worker let ret = handle_eintr_errno!(libc::listen(descriptor.as_raw_descriptor(), 128));
645*bb4ee6a4SAndroid Build Coastguard Worker if ret < 0 {
646*bb4ee6a4SAndroid Build Coastguard Worker return Err(io::Error::last_os_error());
647*bb4ee6a4SAndroid Build Coastguard Worker }
648*bb4ee6a4SAndroid Build Coastguard Worker }
649*bb4ee6a4SAndroid Build Coastguard Worker Ok(UnixSeqpacketListener {
650*bb4ee6a4SAndroid Build Coastguard Worker descriptor,
651*bb4ee6a4SAndroid Build Coastguard Worker no_path: false,
652*bb4ee6a4SAndroid Build Coastguard Worker })
653*bb4ee6a4SAndroid Build Coastguard Worker }
654*bb4ee6a4SAndroid Build Coastguard Worker
accept_with_timeout(&self, timeout: Duration) -> io::Result<UnixSeqpacket>655*bb4ee6a4SAndroid Build Coastguard Worker pub fn accept_with_timeout(&self, timeout: Duration) -> io::Result<UnixSeqpacket> {
656*bb4ee6a4SAndroid Build Coastguard Worker let start = Instant::now();
657*bb4ee6a4SAndroid Build Coastguard Worker
658*bb4ee6a4SAndroid Build Coastguard Worker loop {
659*bb4ee6a4SAndroid Build Coastguard Worker let mut fds = libc::pollfd {
660*bb4ee6a4SAndroid Build Coastguard Worker fd: self.as_raw_descriptor(),
661*bb4ee6a4SAndroid Build Coastguard Worker events: libc::POLLIN,
662*bb4ee6a4SAndroid Build Coastguard Worker revents: 0,
663*bb4ee6a4SAndroid Build Coastguard Worker };
664*bb4ee6a4SAndroid Build Coastguard Worker let elapsed = Instant::now().saturating_duration_since(start);
665*bb4ee6a4SAndroid Build Coastguard Worker let remaining = timeout.checked_sub(elapsed).unwrap_or(Duration::ZERO);
666*bb4ee6a4SAndroid Build Coastguard Worker let cur_timeout_ms = i32::try_from(remaining.as_millis()).unwrap_or(i32::MAX);
667*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
668*bb4ee6a4SAndroid Build Coastguard Worker // Safe because we give a valid pointer to a list (of 1) FD and we check
669*bb4ee6a4SAndroid Build Coastguard Worker // the return value.
670*bb4ee6a4SAndroid Build Coastguard Worker match unsafe { libc::poll(&mut fds, 1, cur_timeout_ms) }.cmp(&0) {
671*bb4ee6a4SAndroid Build Coastguard Worker Ordering::Greater => return self.accept(),
672*bb4ee6a4SAndroid Build Coastguard Worker Ordering::Equal => return Err(io::Error::from_raw_os_error(libc::ETIMEDOUT)),
673*bb4ee6a4SAndroid Build Coastguard Worker Ordering::Less => {
674*bb4ee6a4SAndroid Build Coastguard Worker if Error::last() != Error::new(libc::EINTR) {
675*bb4ee6a4SAndroid Build Coastguard Worker return Err(io::Error::last_os_error());
676*bb4ee6a4SAndroid Build Coastguard Worker }
677*bb4ee6a4SAndroid Build Coastguard Worker }
678*bb4ee6a4SAndroid Build Coastguard Worker }
679*bb4ee6a4SAndroid Build Coastguard Worker }
680*bb4ee6a4SAndroid Build Coastguard Worker }
681*bb4ee6a4SAndroid Build Coastguard Worker
682*bb4ee6a4SAndroid Build Coastguard Worker /// Gets the path that this listener is bound to.
path(&self) -> io::Result<PathBuf>683*bb4ee6a4SAndroid Build Coastguard Worker pub fn path(&self) -> io::Result<PathBuf> {
684*bb4ee6a4SAndroid Build Coastguard Worker let mut addr = sockaddr_un(Path::new(""))?.0;
685*bb4ee6a4SAndroid Build Coastguard Worker if self.no_path {
686*bb4ee6a4SAndroid Build Coastguard Worker return Err(io::Error::new(
687*bb4ee6a4SAndroid Build Coastguard Worker io::ErrorKind::InvalidInput,
688*bb4ee6a4SAndroid Build Coastguard Worker "socket has no path",
689*bb4ee6a4SAndroid Build Coastguard Worker ));
690*bb4ee6a4SAndroid Build Coastguard Worker }
691*bb4ee6a4SAndroid Build Coastguard Worker let sun_path_offset = (&addr.sun_path as *const _ as usize
692*bb4ee6a4SAndroid Build Coastguard Worker - &addr.sun_family as *const _ as usize)
693*bb4ee6a4SAndroid Build Coastguard Worker as libc::socklen_t;
694*bb4ee6a4SAndroid Build Coastguard Worker let mut len = mem::size_of::<libc::sockaddr_un>() as libc::socklen_t;
695*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
696*bb4ee6a4SAndroid Build Coastguard Worker // Safe because the length given matches the length of the data of the given pointer, and we
697*bb4ee6a4SAndroid Build Coastguard Worker // check the return value.
698*bb4ee6a4SAndroid Build Coastguard Worker let ret = unsafe {
699*bb4ee6a4SAndroid Build Coastguard Worker handle_eintr_errno!(libc::getsockname(
700*bb4ee6a4SAndroid Build Coastguard Worker self.as_raw_descriptor(),
701*bb4ee6a4SAndroid Build Coastguard Worker &mut addr as *mut libc::sockaddr_un as *mut libc::sockaddr,
702*bb4ee6a4SAndroid Build Coastguard Worker &mut len
703*bb4ee6a4SAndroid Build Coastguard Worker ))
704*bb4ee6a4SAndroid Build Coastguard Worker };
705*bb4ee6a4SAndroid Build Coastguard Worker if ret < 0 {
706*bb4ee6a4SAndroid Build Coastguard Worker return Err(io::Error::last_os_error());
707*bb4ee6a4SAndroid Build Coastguard Worker }
708*bb4ee6a4SAndroid Build Coastguard Worker if addr.sun_family != libc::AF_UNIX as libc::sa_family_t
709*bb4ee6a4SAndroid Build Coastguard Worker || addr.sun_path[0] == 0
710*bb4ee6a4SAndroid Build Coastguard Worker || len < 1 + sun_path_offset
711*bb4ee6a4SAndroid Build Coastguard Worker {
712*bb4ee6a4SAndroid Build Coastguard Worker return Err(io::Error::new(
713*bb4ee6a4SAndroid Build Coastguard Worker io::ErrorKind::InvalidInput,
714*bb4ee6a4SAndroid Build Coastguard Worker "getsockname on socket returned invalid value",
715*bb4ee6a4SAndroid Build Coastguard Worker ));
716*bb4ee6a4SAndroid Build Coastguard Worker }
717*bb4ee6a4SAndroid Build Coastguard Worker
718*bb4ee6a4SAndroid Build Coastguard Worker let path_os_str = OsString::from_vec(
719*bb4ee6a4SAndroid Build Coastguard Worker addr.sun_path[..(len - sun_path_offset - 1) as usize]
720*bb4ee6a4SAndroid Build Coastguard Worker .iter()
721*bb4ee6a4SAndroid Build Coastguard Worker .map(|&c| c as _)
722*bb4ee6a4SAndroid Build Coastguard Worker .collect(),
723*bb4ee6a4SAndroid Build Coastguard Worker );
724*bb4ee6a4SAndroid Build Coastguard Worker Ok(path_os_str.into())
725*bb4ee6a4SAndroid Build Coastguard Worker }
726*bb4ee6a4SAndroid Build Coastguard Worker
727*bb4ee6a4SAndroid Build Coastguard Worker /// Sets the blocking mode for this socket.
set_nonblocking(&self, nonblocking: bool) -> io::Result<()>728*bb4ee6a4SAndroid Build Coastguard Worker pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
729*bb4ee6a4SAndroid Build Coastguard Worker let mut nonblocking = nonblocking as libc::c_int;
730*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
731*bb4ee6a4SAndroid Build Coastguard Worker // Safe because the return value is checked, and this ioctl call sets the nonblocking mode
732*bb4ee6a4SAndroid Build Coastguard Worker // and does not continue holding the file descriptor after the call.
733*bb4ee6a4SAndroid Build Coastguard Worker let ret = unsafe { libc::ioctl(self.as_raw_descriptor(), libc::FIONBIO, &mut nonblocking) };
734*bb4ee6a4SAndroid Build Coastguard Worker if ret < 0 {
735*bb4ee6a4SAndroid Build Coastguard Worker Err(io::Error::last_os_error())
736*bb4ee6a4SAndroid Build Coastguard Worker } else {
737*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
738*bb4ee6a4SAndroid Build Coastguard Worker }
739*bb4ee6a4SAndroid Build Coastguard Worker }
740*bb4ee6a4SAndroid Build Coastguard Worker }
741*bb4ee6a4SAndroid Build Coastguard Worker
742*bb4ee6a4SAndroid Build Coastguard Worker impl AsRawDescriptor for UnixSeqpacketListener {
as_raw_descriptor(&self) -> RawDescriptor743*bb4ee6a4SAndroid Build Coastguard Worker fn as_raw_descriptor(&self) -> RawDescriptor {
744*bb4ee6a4SAndroid Build Coastguard Worker self.descriptor.as_raw_descriptor()
745*bb4ee6a4SAndroid Build Coastguard Worker }
746*bb4ee6a4SAndroid Build Coastguard Worker }
747*bb4ee6a4SAndroid Build Coastguard Worker
748*bb4ee6a4SAndroid Build Coastguard Worker impl From<UnixSeqpacketListener> for OwnedFd {
from(val: UnixSeqpacketListener) -> Self749*bb4ee6a4SAndroid Build Coastguard Worker fn from(val: UnixSeqpacketListener) -> Self {
750*bb4ee6a4SAndroid Build Coastguard Worker val.descriptor.into()
751*bb4ee6a4SAndroid Build Coastguard Worker }
752*bb4ee6a4SAndroid Build Coastguard Worker }
753*bb4ee6a4SAndroid Build Coastguard Worker
754*bb4ee6a4SAndroid Build Coastguard Worker /// Used to attempt to clean up a `UnixSeqpacketListener` after it is dropped.
755*bb4ee6a4SAndroid Build Coastguard Worker pub struct UnlinkUnixSeqpacketListener(pub UnixSeqpacketListener);
756*bb4ee6a4SAndroid Build Coastguard Worker
757*bb4ee6a4SAndroid Build Coastguard Worker impl AsRawDescriptor for UnlinkUnixSeqpacketListener {
as_raw_descriptor(&self) -> RawDescriptor758*bb4ee6a4SAndroid Build Coastguard Worker fn as_raw_descriptor(&self) -> RawDescriptor {
759*bb4ee6a4SAndroid Build Coastguard Worker self.0.as_raw_descriptor()
760*bb4ee6a4SAndroid Build Coastguard Worker }
761*bb4ee6a4SAndroid Build Coastguard Worker }
762*bb4ee6a4SAndroid Build Coastguard Worker
763*bb4ee6a4SAndroid Build Coastguard Worker impl AsRef<UnixSeqpacketListener> for UnlinkUnixSeqpacketListener {
as_ref(&self) -> &UnixSeqpacketListener764*bb4ee6a4SAndroid Build Coastguard Worker fn as_ref(&self) -> &UnixSeqpacketListener {
765*bb4ee6a4SAndroid Build Coastguard Worker &self.0
766*bb4ee6a4SAndroid Build Coastguard Worker }
767*bb4ee6a4SAndroid Build Coastguard Worker }
768*bb4ee6a4SAndroid Build Coastguard Worker
769*bb4ee6a4SAndroid Build Coastguard Worker impl Deref for UnlinkUnixSeqpacketListener {
770*bb4ee6a4SAndroid Build Coastguard Worker type Target = UnixSeqpacketListener;
deref(&self) -> &Self::Target771*bb4ee6a4SAndroid Build Coastguard Worker fn deref(&self) -> &Self::Target {
772*bb4ee6a4SAndroid Build Coastguard Worker &self.0
773*bb4ee6a4SAndroid Build Coastguard Worker }
774*bb4ee6a4SAndroid Build Coastguard Worker }
775*bb4ee6a4SAndroid Build Coastguard Worker
776*bb4ee6a4SAndroid Build Coastguard Worker impl Drop for UnlinkUnixSeqpacketListener {
drop(&mut self)777*bb4ee6a4SAndroid Build Coastguard Worker fn drop(&mut self) {
778*bb4ee6a4SAndroid Build Coastguard Worker if let Ok(path) = self.0.path() {
779*bb4ee6a4SAndroid Build Coastguard Worker if let Err(e) = remove_file(path) {
780*bb4ee6a4SAndroid Build Coastguard Worker warn!("failed to remove control socket file: {:?}", e);
781*bb4ee6a4SAndroid Build Coastguard Worker }
782*bb4ee6a4SAndroid Build Coastguard Worker }
783*bb4ee6a4SAndroid Build Coastguard Worker }
784*bb4ee6a4SAndroid Build Coastguard Worker }
785*bb4ee6a4SAndroid Build Coastguard Worker
786*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(test)]
787*bb4ee6a4SAndroid Build Coastguard Worker mod tests {
788*bb4ee6a4SAndroid Build Coastguard Worker use super::*;
789*bb4ee6a4SAndroid Build Coastguard Worker
790*bb4ee6a4SAndroid Build Coastguard Worker #[test]
sockaddr_un_zero_length_input()791*bb4ee6a4SAndroid Build Coastguard Worker fn sockaddr_un_zero_length_input() {
792*bb4ee6a4SAndroid Build Coastguard Worker let _res = sockaddr_un(Path::new("")).expect("sockaddr_un failed");
793*bb4ee6a4SAndroid Build Coastguard Worker }
794*bb4ee6a4SAndroid Build Coastguard Worker
795*bb4ee6a4SAndroid Build Coastguard Worker #[test]
sockaddr_un_long_input_err()796*bb4ee6a4SAndroid Build Coastguard Worker fn sockaddr_un_long_input_err() {
797*bb4ee6a4SAndroid Build Coastguard Worker let res = sockaddr_un(Path::new(&"a".repeat(108)));
798*bb4ee6a4SAndroid Build Coastguard Worker assert!(res.is_err());
799*bb4ee6a4SAndroid Build Coastguard Worker }
800*bb4ee6a4SAndroid Build Coastguard Worker
801*bb4ee6a4SAndroid Build Coastguard Worker #[test]
sockaddr_un_long_input_pass()802*bb4ee6a4SAndroid Build Coastguard Worker fn sockaddr_un_long_input_pass() {
803*bb4ee6a4SAndroid Build Coastguard Worker let _res = sockaddr_un(Path::new(&"a".repeat(107))).expect("sockaddr_un failed");
804*bb4ee6a4SAndroid Build Coastguard Worker }
805*bb4ee6a4SAndroid Build Coastguard Worker
806*bb4ee6a4SAndroid Build Coastguard Worker #[test]
sockaddr_un_len_check()807*bb4ee6a4SAndroid Build Coastguard Worker fn sockaddr_un_len_check() {
808*bb4ee6a4SAndroid Build Coastguard Worker let (_addr, len) = sockaddr_un(Path::new(&"a".repeat(50))).expect("sockaddr_un failed");
809*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(len, (sun_path_offset() + 50 + 1) as u32);
810*bb4ee6a4SAndroid Build Coastguard Worker }
811*bb4ee6a4SAndroid Build Coastguard Worker
812*bb4ee6a4SAndroid Build Coastguard Worker #[test]
813*bb4ee6a4SAndroid Build Coastguard Worker #[allow(clippy::unnecessary_cast)]
814*bb4ee6a4SAndroid Build Coastguard Worker // c_char is u8 on aarch64 and i8 on x86, so clippy's suggested fix of changing
815*bb4ee6a4SAndroid Build Coastguard Worker // `'a' as libc::c_char` below to `b'a'` won't work everywhere.
816*bb4ee6a4SAndroid Build Coastguard Worker #[allow(clippy::char_lit_as_u8)]
sockaddr_un_pass()817*bb4ee6a4SAndroid Build Coastguard Worker fn sockaddr_un_pass() {
818*bb4ee6a4SAndroid Build Coastguard Worker let path_size = 50;
819*bb4ee6a4SAndroid Build Coastguard Worker let (addr, len) =
820*bb4ee6a4SAndroid Build Coastguard Worker sockaddr_un(Path::new(&"a".repeat(path_size))).expect("sockaddr_un failed");
821*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(len, (sun_path_offset() + path_size + 1) as u32);
822*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(addr.sun_family, libc::AF_UNIX as libc::sa_family_t);
823*bb4ee6a4SAndroid Build Coastguard Worker
824*bb4ee6a4SAndroid Build Coastguard Worker // Check `sun_path` in returned `sockaddr_un`
825*bb4ee6a4SAndroid Build Coastguard Worker let mut ref_sun_path = [0 as libc::c_char; 108];
826*bb4ee6a4SAndroid Build Coastguard Worker for path in ref_sun_path.iter_mut().take(path_size) {
827*bb4ee6a4SAndroid Build Coastguard Worker *path = 'a' as libc::c_char;
828*bb4ee6a4SAndroid Build Coastguard Worker }
829*bb4ee6a4SAndroid Build Coastguard Worker
830*bb4ee6a4SAndroid Build Coastguard Worker for (addr_char, ref_char) in addr.sun_path.iter().zip(ref_sun_path.iter()) {
831*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(addr_char, ref_char);
832*bb4ee6a4SAndroid Build Coastguard Worker }
833*bb4ee6a4SAndroid Build Coastguard Worker }
834*bb4ee6a4SAndroid Build Coastguard Worker }
835