mio/sys/unix/uds/
listener.rs1use std::ffi::OsStr;
2use std::os::fd::{AsRawFd, FromRawFd};
3use std::os::unix::ffi::OsStrExt;
4use std::os::unix::net::{self, SocketAddr};
5use std::path::Path;
6use std::{io, mem};
7
8use crate::net::UnixStream;
9use crate::sys::unix::net::new_socket;
10use crate::sys::unix::uds::{path_offset, unix_addr};
11use crate::sys::LISTEN_BACKLOG_SIZE;
12
13pub(crate) fn bind_addr(address: &SocketAddr) -> io::Result<net::UnixListener> {
14 let fd = new_socket(libc::AF_UNIX, libc::SOCK_STREAM)?;
15 let socket = unsafe { net::UnixListener::from_raw_fd(fd) };
16
17 let (unix_address, addrlen) = unix_addr(address);
18 let sockaddr = &unix_address as *const libc::sockaddr_un as *const libc::sockaddr;
19 syscall!(bind(fd, sockaddr, addrlen))?;
20 syscall!(listen(fd, LISTEN_BACKLOG_SIZE))?;
21
22 Ok(socket)
23}
24
25pub(crate) fn accept(listener: &net::UnixListener) -> io::Result<(UnixStream, SocketAddr)> {
26 let mut sockaddr = unsafe { mem::zeroed::<libc::sockaddr_un>() };
34
35 let mut socklen = mem::size_of_val(&sockaddr) as libc::socklen_t;
36
37 #[cfg(not(any(
38 target_os = "aix",
39 target_os = "haiku",
40 target_os = "ios",
41 target_os = "macos",
42 target_os = "netbsd",
43 target_os = "redox",
44 target_os = "tvos",
45 target_os = "visionos",
46 target_os = "watchos",
47 target_os = "espidf",
48 target_os = "vita",
49 target_os = "nto",
50 all(target_arch = "x86", target_os = "android"),
53 )))]
54 let socket = {
55 let flags = libc::SOCK_NONBLOCK | libc::SOCK_CLOEXEC;
56 syscall!(accept4(
57 listener.as_raw_fd(),
58 &mut sockaddr as *mut libc::sockaddr_un as *mut libc::sockaddr,
59 &mut socklen,
60 flags
61 ))
62 .map(|socket| unsafe { net::UnixStream::from_raw_fd(socket) })
63 };
64
65 #[cfg(any(
66 target_os = "aix",
67 target_os = "haiku",
68 target_os = "ios",
69 target_os = "macos",
70 target_os = "netbsd",
71 target_os = "redox",
72 target_os = "tvos",
73 target_os = "visionos",
74 target_os = "watchos",
75 target_os = "espidf",
76 target_os = "vita",
77 target_os = "nto",
78 all(target_arch = "x86", target_os = "android")
79 ))]
80 let socket = syscall!(accept(
81 listener.as_raw_fd(),
82 &mut sockaddr as *mut libc::sockaddr_un as *mut libc::sockaddr,
83 &mut socklen,
84 ))
85 .and_then(|socket| {
86 let s = unsafe { net::UnixStream::from_raw_fd(socket) };
89 #[cfg(not(any(target_os = "espidf", target_os = "vita")))]
90 syscall!(fcntl(socket, libc::F_SETFD, libc::FD_CLOEXEC))?;
91
92 #[cfg(any(
94 all(target_arch = "x86", target_os = "android"),
95 target_os = "espidf",
96 target_os = "vita",
97 target_os = "nto",
98 ))]
99 syscall!(fcntl(socket, libc::F_SETFL, libc::O_NONBLOCK))?;
100
101 Ok(s)
102 });
103
104 let socket = socket.map(UnixStream::from_std)?;
105
106 #[allow(unused_mut)] let mut path_len = socklen as usize - path_offset(&sockaddr);
108 if sockaddr.sun_path[0] == 0 {
111 path_len = 0;
112 }
113 let mut path =
115 unsafe { &*(&sockaddr.sun_path[..path_len] as *const [libc::c_char] as *const [u8]) };
116 if let Some(0) = path.last() {
118 path = &path[..path.len() - 1];
119 }
120 let address = SocketAddr::from_pathname(Path::new(OsStr::from_bytes(path)))?;
121 Ok((socket, address))
122}