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 syscall!(listen(fd, 1024))?;
20
21 Ok(socket)
22}
23
24pub(crate) fn accept(listener: &net::UnixListener) -> io::Result<(UnixStream, SocketAddr)> {
25 let mut sockaddr = unsafe { mem::zeroed::<libc::sockaddr_un>() };
33
34 let mut socklen = mem::size_of_val(&sockaddr) as libc::socklen_t;
35
36 #[cfg(not(any(
37 target_os = "aix",
38 target_os = "haiku",
39 target_os = "ios",
40 target_os = "macos",
41 target_os = "netbsd",
42 target_os = "redox",
43 target_os = "tvos",
44 target_os = "visionos",
45 target_os = "watchos",
46 target_os = "espidf",
47 target_os = "vita",
48 target_os = "nto",
49 all(target_arch = "x86", target_os = "android"),
52 )))]
53 let socket = {
54 let flags = libc::SOCK_NONBLOCK | libc::SOCK_CLOEXEC;
55 syscall!(accept4(
56 listener.as_raw_fd(),
57 &mut sockaddr as *mut libc::sockaddr_un as *mut libc::sockaddr,
58 &mut socklen,
59 flags
60 ))
61 .map(|socket| unsafe { net::UnixStream::from_raw_fd(socket) })
62 };
63
64 #[cfg(any(
65 target_os = "aix",
66 target_os = "haiku",
67 target_os = "ios",
68 target_os = "macos",
69 target_os = "netbsd",
70 target_os = "redox",
71 target_os = "tvos",
72 target_os = "visionos",
73 target_os = "watchos",
74 target_os = "espidf",
75 target_os = "vita",
76 target_os = "nto",
77 all(target_arch = "x86", target_os = "android")
78 ))]
79 let socket = syscall!(accept(
80 listener.as_raw_fd(),
81 &mut sockaddr as *mut libc::sockaddr_un as *mut libc::sockaddr,
82 &mut socklen,
83 ))
84 .and_then(|socket| {
85 let s = unsafe { net::UnixStream::from_raw_fd(socket) };
88 #[cfg(not(any(target_os = "espidf", target_os = "vita")))]
89 syscall!(fcntl(socket, libc::F_SETFD, libc::FD_CLOEXEC))?;
90
91 #[cfg(any(
93 all(target_arch = "x86", target_os = "android"),
94 target_os = "espidf",
95 target_os = "vita",
96 target_os = "nto",
97 ))]
98 syscall!(fcntl(socket, libc::F_SETFL, libc::O_NONBLOCK))?;
99
100 Ok(s)
101 });
102
103 let socket = socket.map(UnixStream::from_std)?;
104
105 #[allow(unused_mut)] let mut path_len = socklen as usize - path_offset(&sockaddr);
107 if sockaddr.sun_path[0] == 0 {
110 path_len = 0;
111 }
112 let mut path =
114 unsafe { &*(&sockaddr.sun_path[..path_len] as *const [libc::c_char] as *const [u8]) };
115 if let Some(0) = path.last() {
117 path = &path[..path.len() - 1];
118 }
119 let address = SocketAddr::from_pathname(Path::new(OsStr::from_bytes(path)))?;
120 Ok((socket, address))
121}