1use super::socket_addr;
2use crate::net::{SocketAddr, UnixStream};
3use crate::sys::unix::net::new_socket;
4use std::os::unix::io::{AsRawFd, FromRawFd};
5use std::os::unix::net;
6use std::path::Path;
7use std::{io, mem};
8
9pub(crate) fn bind(path: &Path) -> io::Result<net::UnixListener> {
10 let (sockaddr: sockaddr_un, socklen: u32) = socket_addr(path)?;
11 let sockaddr: *const sockaddr = &sockaddr as *const libc::sockaddr_un as *const libc::sockaddr;
12
13 let fd: i32 = new_socket(domain:libc::AF_UNIX, socket_type:libc::SOCK_STREAM)?;
14 let socket: UnixListener = unsafe { net::UnixListener::from_raw_fd(fd) };
15 syscall!(bind(fd, sockaddr, socklen))?;
16 syscall!(listen(fd, 1024))?;
17
18 Ok(socket)
19}
20
21pub(crate) fn accept(listener: &net::UnixListener) -> io::Result<(UnixStream, SocketAddr)> {
22 let sockaddr = mem::MaybeUninit::<libc::sockaddr_un>::zeroed();
23
24 // This is safe to assume because a `libc::sockaddr_un` filled with `0`
25 // bytes is properly initialized.
26 //
27 // `0` is a valid value for `sockaddr_un::sun_family`; it is
28 // `libc::AF_UNSPEC`.
29 //
30 // `[0; 108]` is a valid value for `sockaddr_un::sun_path`; it begins an
31 // abstract path.
32 let mut sockaddr = unsafe { sockaddr.assume_init() };
33
34 sockaddr.sun_family = libc::AF_UNIX as libc::sa_family_t;
35 let mut socklen = mem::size_of_val(&sockaddr) as libc::socklen_t;
36
37 #[cfg(not(any(
38 target_os = "ios",
39 target_os = "macos",
40 target_os = "netbsd",
41 target_os = "redox",
42 target_os = "tvos",
43 target_os = "watchos",
44 // Android x86's seccomp profile forbids calls to `accept4(2)`
45 // See https://github.com/tokio-rs/mio/issues/1445 for details
46 all(target_arch = "x86", target_os = "android"),
47 )))]
48 let socket = {
49 let flags = libc::SOCK_NONBLOCK | libc::SOCK_CLOEXEC;
50 syscall!(accept4(
51 listener.as_raw_fd(),
52 &mut sockaddr as *mut libc::sockaddr_un as *mut libc::sockaddr,
53 &mut socklen,
54 flags
55 ))
56 .map(|socket| unsafe { net::UnixStream::from_raw_fd(socket) })
57 };
58
59 #[cfg(any(
60 target_os = "ios",
61 target_os = "macos",
62 target_os = "netbsd",
63 target_os = "redox",
64 target_os = "tvos",
65 target_os = "watchos",
66 all(target_arch = "x86", target_os = "android")
67 ))]
68 let socket = syscall!(accept(
69 listener.as_raw_fd(),
70 &mut sockaddr as *mut libc::sockaddr_un as *mut libc::sockaddr,
71 &mut socklen,
72 ))
73 .and_then(|socket| {
74 // Ensure the socket is closed if either of the `fcntl` calls
75 // error below.
76 let s = unsafe { net::UnixStream::from_raw_fd(socket) };
77 syscall!(fcntl(socket, libc::F_SETFD, libc::FD_CLOEXEC))?;
78
79 // See https://github.com/tokio-rs/mio/issues/1450
80 #[cfg(all(target_arch = "x86", target_os = "android"))]
81 syscall!(fcntl(socket, libc::F_SETFL, libc::O_NONBLOCK))?;
82
83 Ok(s)
84 });
85
86 socket
87 .map(UnixStream::from_std)
88 .map(|stream| (stream, SocketAddr::from_parts(sockaddr, socklen)))
89}
90
91pub(crate) fn local_addr(listener: &net::UnixListener) -> io::Result<SocketAddr> {
92 super::local_addr(socket:listener.as_raw_fd())
93}
94