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