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};
11
12pub(crate) fn bind_addr(address: &SocketAddr) -> io::Result<net::UnixListener> {
13 let fd = new_socket(libc::AF_UNIX, libc::SOCK_STREAM)?;
14 let socket = unsafe { net::UnixListener::from_raw_fd(fd) };
15
16 let (unix_address, addrlen) = unix_addr(address);
17 let sockaddr = &unix_address as *const libc::sockaddr_un as *const libc::sockaddr;
18 syscall!(bind(fd, sockaddr, addrlen))?;
19 let backlog = if cfg!(any(
22 target_os = "windows",
23 target_os = "redox",
24 target_os = "espidf",
25 target_os = "horizon"
26 )) {
27 128
28 } else if cfg!(any(
29 target_os = "linux",
30 target_os = "freebsd",
31 target_os = "openbsd",
32 target_vendor = "apple"
33 )) {
34 -1
35 } else {
36 libc::SOMAXCONN
37 };
38 syscall!(listen(fd, backlog))?;
39
40 Ok(socket)
41}
42
43pub(crate) fn accept(listener: &net::UnixListener) -> io::Result<(UnixStream, SocketAddr)> {
44 let mut sockaddr = unsafe { mem::zeroed::<libc::sockaddr_un>() };
52
53 let mut socklen = mem::size_of_val(&sockaddr) as libc::socklen_t;
54
55 #[cfg(not(any(
56 target_os = "aix",
57 target_os = "haiku",
58 target_os = "ios",
59 target_os = "macos",
60 target_os = "netbsd",
61 target_os = "redox",
62 target_os = "tvos",
63 target_os = "visionos",
64 target_os = "watchos",
65 target_os = "espidf",
66 target_os = "vita",
67 target_os = "nto",
68 all(target_arch = "x86", target_os = "android"),
71 )))]
72 let socket = {
73 let flags = libc::SOCK_NONBLOCK | libc::SOCK_CLOEXEC;
74 syscall!(accept4(
75 listener.as_raw_fd(),
76 &mut sockaddr as *mut libc::sockaddr_un as *mut libc::sockaddr,
77 &mut socklen,
78 flags
79 ))
80 .map(|socket| unsafe { net::UnixStream::from_raw_fd(socket) })
81 };
82
83 #[cfg(any(
84 target_os = "aix",
85 target_os = "haiku",
86 target_os = "ios",
87 target_os = "macos",
88 target_os = "netbsd",
89 target_os = "redox",
90 target_os = "tvos",
91 target_os = "visionos",
92 target_os = "watchos",
93 target_os = "espidf",
94 target_os = "vita",
95 target_os = "nto",
96 all(target_arch = "x86", target_os = "android")
97 ))]
98 let socket = syscall!(accept(
99 listener.as_raw_fd(),
100 &mut sockaddr as *mut libc::sockaddr_un as *mut libc::sockaddr,
101 &mut socklen,
102 ))
103 .and_then(|socket| {
104 let s = unsafe { net::UnixStream::from_raw_fd(socket) };
107 #[cfg(not(any(target_os = "espidf", target_os = "vita")))]
108 syscall!(fcntl(socket, libc::F_SETFD, libc::FD_CLOEXEC))?;
109
110 #[cfg(any(
112 all(target_arch = "x86", target_os = "android"),
113 target_os = "espidf",
114 target_os = "vita",
115 target_os = "nto",
116 ))]
117 syscall!(fcntl(socket, libc::F_SETFL, libc::O_NONBLOCK))?;
118
119 Ok(s)
120 });
121
122 let socket = socket.map(UnixStream::from_std)?;
123
124 #[allow(unused_mut)] let mut path_len = socklen as usize - path_offset(&sockaddr);
126 if sockaddr.sun_path[0] == 0 {
129 path_len = 0;
130 }
131 let mut path =
133 unsafe { &*(&sockaddr.sun_path[..path_len] as *const [libc::c_char] as *const [u8]) };
134 if let Some(0) = path.last() {
136 path = &path[..path.len() - 1];
137 }
138 let address = SocketAddr::from_pathname(Path::new(OsStr::from_bytes(path)))?;
139 Ok((socket, address))
140}