1 | use super::socket_addr; |
2 | use crate::net::{SocketAddr, UnixStream}; |
3 | use crate::sys::unix::net::new_socket; |
4 | use std::os::unix::io::{AsRawFd, FromRawFd}; |
5 | use std::os::unix::net; |
6 | use std::path::Path; |
7 | use std::{io, mem}; |
8 | |
9 | pub(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 | |
21 | pub(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 | |
91 | pub(crate) fn local_addr(listener: &net::UnixListener) -> io::Result<SocketAddr> { |
92 | super::local_addr(socket:listener.as_raw_fd()) |
93 | } |
94 | |