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 #[cfg(any(
23 target_os = "windows",
24 target_os = "redox",
25 target_os = "espidf",
26 target_os = "horizon"
27 ))]
28 let backlog = 128;
29 #[cfg(any(
30 target_os = "linux",
31 target_os = "freebsd",
32 target_os = "openbsd",
33 target_vendor = "apple"
34 ))]
35 let backlog = -1;
36 #[cfg(not(any(
37 target_os = "linux",
38 target_os = "freebsd",
39 target_os = "openbsd",
40 target_vendor = "apple",
41 target_os = "windows",
42 target_os = "redox",
43 target_os = "espidf",
44 target_os = "horizon"
45 )))]
46 let backlog = libc::SOMAXCONN;
47
48 syscall!(listen(fd, backlog))?;
49
50 Ok(socket)
51}
52
53pub(crate) fn accept(listener: &net::UnixListener) -> io::Result<(UnixStream, SocketAddr)> {
54 let mut sockaddr = unsafe { mem::zeroed::<libc::sockaddr_un>() };
62
63 let mut socklen = mem::size_of_val(&sockaddr) as libc::socklen_t;
64
65 #[cfg(not(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 target_os = "horizon",
79 all(target_arch = "x86", target_os = "android"),
82 )))]
83 let socket = {
84 let flags = libc::SOCK_NONBLOCK | libc::SOCK_CLOEXEC;
85 syscall!(accept4(
86 listener.as_raw_fd(),
87 &mut sockaddr as *mut libc::sockaddr_un as *mut libc::sockaddr,
88 &mut socklen,
89 flags
90 ))
91 .map(|socket| unsafe { net::UnixStream::from_raw_fd(socket) })
92 };
93
94 #[cfg(any(
95 target_os = "aix",
96 target_os = "haiku",
97 target_os = "ios",
98 target_os = "macos",
99 target_os = "netbsd",
100 target_os = "redox",
101 target_os = "tvos",
102 target_os = "visionos",
103 target_os = "watchos",
104 target_os = "espidf",
105 target_os = "vita",
106 target_os = "nto",
107 target_os = "horizon",
108 all(target_arch = "x86", target_os = "android")
109 ))]
110 let socket = syscall!(accept(
111 listener.as_raw_fd(),
112 &mut sockaddr as *mut libc::sockaddr_un as *mut libc::sockaddr,
113 &mut socklen,
114 ))
115 .and_then(|socket| {
116 let s = unsafe { net::UnixStream::from_raw_fd(socket) };
119 #[cfg(not(any(target_os = "espidf", target_os = "vita")))]
120 syscall!(fcntl(socket, libc::F_SETFD, libc::FD_CLOEXEC))?;
121
122 #[cfg(any(
124 all(target_arch = "x86", target_os = "android"),
125 target_os = "espidf",
126 target_os = "vita",
127 target_os = "nto",
128 ))]
129 syscall!(fcntl(socket, libc::F_SETFL, libc::O_NONBLOCK))?;
130
131 Ok(s)
132 });
133
134 let socket = socket.map(UnixStream::from_std)?;
135
136 #[allow(unused_mut)] let mut path_len = socklen as usize - path_offset(&sockaddr);
138 if sockaddr.sun_path[0] == 0 {
141 path_len = 0;
142 }
143 let mut path =
145 unsafe { &*(&sockaddr.sun_path[..path_len] as *const [libc::c_char] as *const [u8]) };
146 if let Some(0) = path.last() {
148 path = &path[..path.len() - 1];
149 }
150 let address = SocketAddr::from_pathname(Path::new(OsStr::from_bytes(path)))?;
151 Ok((socket, address))
152}