std/os/unix/net/
listener.rs

1use super::{SocketAddr, UnixStream, sockaddr_un};
2use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
3use crate::path::Path;
4use crate::sys::cvt;
5use crate::sys::net::Socket;
6use crate::sys_common::{AsInner, FromInner, IntoInner};
7use crate::{fmt, io, mem};
8
9/// A structure representing a Unix domain socket server.
10///
11/// # Examples
12///
13/// ```no_run
14/// use std::thread;
15/// use std::os::unix::net::{UnixStream, UnixListener};
16///
17/// fn handle_client(stream: UnixStream) {
18///     // ...
19/// }
20///
21/// fn main() -> std::io::Result<()> {
22///     let listener = UnixListener::bind("/path/to/the/socket")?;
23///
24///     // accept connections and process them, spawning a new thread for each one
25///     for stream in listener.incoming() {
26///         match stream {
27///             Ok(stream) => {
28///                 /* connection succeeded */
29///                 thread::spawn(|| handle_client(stream));
30///             }
31///             Err(err) => {
32///                 /* connection failed */
33///                 break;
34///             }
35///         }
36///     }
37///     Ok(())
38/// }
39/// ```
40#[stable(feature = "unix_socket", since = "1.10.0")]
41pub struct UnixListener(Socket);
42
43#[stable(feature = "unix_socket", since = "1.10.0")]
44impl fmt::Debug for UnixListener {
45    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
46        let mut builder = fmt.debug_struct("UnixListener");
47        builder.field("fd", self.0.as_inner());
48        if let Ok(addr) = self.local_addr() {
49            builder.field("local", &addr);
50        }
51        builder.finish()
52    }
53}
54
55impl UnixListener {
56    /// Creates a new `UnixListener` bound to the specified socket.
57    ///
58    /// # Examples
59    ///
60    /// ```no_run
61    /// use std::os::unix::net::UnixListener;
62    ///
63    /// let listener = match UnixListener::bind("/path/to/the/socket") {
64    ///     Ok(sock) => sock,
65    ///     Err(e) => {
66    ///         println!("Couldn't connect: {e:?}");
67    ///         return
68    ///     }
69    /// };
70    /// ```
71    #[stable(feature = "unix_socket", since = "1.10.0")]
72    pub fn bind<P: AsRef<Path>>(path: P) -> io::Result<UnixListener> {
73        unsafe {
74            let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_STREAM)?;
75            let (addr, len) = sockaddr_un(path.as_ref())?;
76            #[cfg(any(
77                target_os = "windows",
78                target_os = "redox",
79                target_os = "espidf",
80                target_os = "horizon"
81            ))]
82            const backlog: core::ffi::c_int = 128;
83            #[cfg(any(
84                // Silently capped to `/proc/sys/net/core/somaxconn`.
85                target_os = "linux",
86                // Silently capped to `kern.ipc.soacceptqueue`.
87                target_os = "freebsd",
88                // Silently capped to `kern.somaxconn sysctl`.
89                target_os = "openbsd",
90                // Silently capped to the default 128.
91                target_vendor = "apple",
92            ))]
93            const backlog: core::ffi::c_int = -1;
94            #[cfg(not(any(
95                target_os = "windows",
96                target_os = "redox",
97                target_os = "espidf",
98                target_os = "horizon",
99                target_os = "linux",
100                target_os = "freebsd",
101                target_os = "openbsd",
102                target_vendor = "apple",
103            )))]
104            const backlog: libc::c_int = libc::SOMAXCONN;
105
106            cvt(libc::bind(inner.as_inner().as_raw_fd(), (&raw const addr) as *const _, len as _))?;
107            cvt(libc::listen(inner.as_inner().as_raw_fd(), backlog))?;
108
109            Ok(UnixListener(inner))
110        }
111    }
112
113    /// Creates a new `UnixListener` bound to the specified [`socket address`].
114    ///
115    /// [`socket address`]: crate::os::unix::net::SocketAddr
116    ///
117    /// # Examples
118    ///
119    /// ```no_run
120    /// use std::os::unix::net::{UnixListener};
121    ///
122    /// fn main() -> std::io::Result<()> {
123    ///     let listener1 = UnixListener::bind("path/to/socket")?;
124    ///     let addr = listener1.local_addr()?;
125    ///
126    ///     let listener2 = match UnixListener::bind_addr(&addr) {
127    ///         Ok(sock) => sock,
128    ///         Err(err) => {
129    ///             println!("Couldn't bind: {err:?}");
130    ///             return Err(err);
131    ///         }
132    ///     };
133    ///     Ok(())
134    /// }
135    /// ```
136    #[stable(feature = "unix_socket_abstract", since = "1.70.0")]
137    pub fn bind_addr(socket_addr: &SocketAddr) -> io::Result<UnixListener> {
138        unsafe {
139            let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_STREAM)?;
140            #[cfg(target_os = "linux")]
141            const backlog: core::ffi::c_int = -1;
142            #[cfg(not(target_os = "linux"))]
143            const backlog: core::ffi::c_int = 128;
144            cvt(libc::bind(
145                inner.as_raw_fd(),
146                (&raw const socket_addr.addr) as *const _,
147                socket_addr.len as _,
148            ))?;
149            cvt(libc::listen(inner.as_raw_fd(), backlog))?;
150            Ok(UnixListener(inner))
151        }
152    }
153
154    /// Accepts a new incoming connection to this listener.
155    ///
156    /// This function will block the calling thread until a new Unix connection
157    /// is established. When established, the corresponding [`UnixStream`] and
158    /// the remote peer's address will be returned.
159    ///
160    /// [`UnixStream`]: crate::os::unix::net::UnixStream
161    ///
162    /// # Examples
163    ///
164    /// ```no_run
165    /// use std::os::unix::net::UnixListener;
166    ///
167    /// fn main() -> std::io::Result<()> {
168    ///     let listener = UnixListener::bind("/path/to/the/socket")?;
169    ///
170    ///     match listener.accept() {
171    ///         Ok((socket, addr)) => println!("Got a client: {addr:?}"),
172    ///         Err(e) => println!("accept function failed: {e:?}"),
173    ///     }
174    ///     Ok(())
175    /// }
176    /// ```
177    #[stable(feature = "unix_socket", since = "1.10.0")]
178    pub fn accept(&self) -> io::Result<(UnixStream, SocketAddr)> {
179        let mut storage: libc::sockaddr_un = unsafe { mem::zeroed() };
180        let mut len = mem::size_of_val(&storage) as libc::socklen_t;
181        let sock = self.0.accept((&raw mut storage) as *mut _, &mut len)?;
182        let addr = SocketAddr::from_parts(storage, len)?;
183        Ok((UnixStream(sock), addr))
184    }
185
186    /// Creates a new independently owned handle to the underlying socket.
187    ///
188    /// The returned `UnixListener` is a reference to the same socket that this
189    /// object references. Both handles can be used to accept incoming
190    /// connections and options set on one listener will affect the other.
191    ///
192    /// # Examples
193    ///
194    /// ```no_run
195    /// use std::os::unix::net::UnixListener;
196    ///
197    /// fn main() -> std::io::Result<()> {
198    ///     let listener = UnixListener::bind("/path/to/the/socket")?;
199    ///     let listener_copy = listener.try_clone().expect("try_clone failed");
200    ///     Ok(())
201    /// }
202    /// ```
203    #[stable(feature = "unix_socket", since = "1.10.0")]
204    pub fn try_clone(&self) -> io::Result<UnixListener> {
205        self.0.duplicate().map(UnixListener)
206    }
207
208    /// Returns the local socket address of this listener.
209    ///
210    /// # Examples
211    ///
212    /// ```no_run
213    /// use std::os::unix::net::UnixListener;
214    ///
215    /// fn main() -> std::io::Result<()> {
216    ///     let listener = UnixListener::bind("/path/to/the/socket")?;
217    ///     let addr = listener.local_addr().expect("Couldn't get local address");
218    ///     Ok(())
219    /// }
220    /// ```
221    #[stable(feature = "unix_socket", since = "1.10.0")]
222    pub fn local_addr(&self) -> io::Result<SocketAddr> {
223        SocketAddr::new(|addr, len| unsafe { libc::getsockname(self.as_raw_fd(), addr, len) })
224    }
225
226    /// Moves the socket into or out of nonblocking mode.
227    ///
228    /// This will result in the `accept` operation becoming nonblocking,
229    /// i.e., immediately returning from their calls. If the IO operation is
230    /// successful, `Ok` is returned and no further action is required. If the
231    /// IO operation could not be completed and needs to be retried, an error
232    /// with kind [`io::ErrorKind::WouldBlock`] is returned.
233    ///
234    /// # Examples
235    ///
236    /// ```no_run
237    /// use std::os::unix::net::UnixListener;
238    ///
239    /// fn main() -> std::io::Result<()> {
240    ///     let listener = UnixListener::bind("/path/to/the/socket")?;
241    ///     listener.set_nonblocking(true).expect("Couldn't set non blocking");
242    ///     Ok(())
243    /// }
244    /// ```
245    #[stable(feature = "unix_socket", since = "1.10.0")]
246    pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
247        self.0.set_nonblocking(nonblocking)
248    }
249
250    /// Returns the value of the `SO_ERROR` option.
251    ///
252    /// # Examples
253    ///
254    /// ```no_run
255    /// use std::os::unix::net::UnixListener;
256    ///
257    /// fn main() -> std::io::Result<()> {
258    ///     let listener = UnixListener::bind("/tmp/sock")?;
259    ///
260    ///     if let Ok(Some(err)) = listener.take_error() {
261    ///         println!("Got error: {err:?}");
262    ///     }
263    ///     Ok(())
264    /// }
265    /// ```
266    ///
267    /// # Platform specific
268    /// On Redox this always returns `None`.
269    #[stable(feature = "unix_socket", since = "1.10.0")]
270    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
271        self.0.take_error()
272    }
273
274    /// Returns an iterator over incoming connections.
275    ///
276    /// The iterator will never return [`None`] and will also not yield the
277    /// peer's [`SocketAddr`] structure.
278    ///
279    /// # Examples
280    ///
281    /// ```no_run
282    /// use std::thread;
283    /// use std::os::unix::net::{UnixStream, UnixListener};
284    ///
285    /// fn handle_client(stream: UnixStream) {
286    ///     // ...
287    /// }
288    ///
289    /// fn main() -> std::io::Result<()> {
290    ///     let listener = UnixListener::bind("/path/to/the/socket")?;
291    ///
292    ///     for stream in listener.incoming() {
293    ///         match stream {
294    ///             Ok(stream) => {
295    ///                 thread::spawn(|| handle_client(stream));
296    ///             }
297    ///             Err(err) => {
298    ///                 break;
299    ///             }
300    ///         }
301    ///     }
302    ///     Ok(())
303    /// }
304    /// ```
305    #[stable(feature = "unix_socket", since = "1.10.0")]
306    pub fn incoming(&self) -> Incoming<'_> {
307        Incoming { listener: self }
308    }
309}
310
311#[stable(feature = "unix_socket", since = "1.10.0")]
312impl AsRawFd for UnixListener {
313    #[inline]
314    fn as_raw_fd(&self) -> RawFd {
315        self.0.as_inner().as_raw_fd()
316    }
317}
318
319#[stable(feature = "unix_socket", since = "1.10.0")]
320impl FromRawFd for UnixListener {
321    #[inline]
322    unsafe fn from_raw_fd(fd: RawFd) -> UnixListener {
323        UnixListener(Socket::from_inner(FromInner::from_inner(OwnedFd::from_raw_fd(fd))))
324    }
325}
326
327#[stable(feature = "unix_socket", since = "1.10.0")]
328impl IntoRawFd for UnixListener {
329    #[inline]
330    fn into_raw_fd(self) -> RawFd {
331        self.0.into_inner().into_inner().into_raw_fd()
332    }
333}
334
335#[stable(feature = "io_safety", since = "1.63.0")]
336impl AsFd for UnixListener {
337    #[inline]
338    fn as_fd(&self) -> BorrowedFd<'_> {
339        self.0.as_inner().as_fd()
340    }
341}
342
343#[stable(feature = "io_safety", since = "1.63.0")]
344impl From<OwnedFd> for UnixListener {
345    #[inline]
346    fn from(fd: OwnedFd) -> UnixListener {
347        UnixListener(Socket::from_inner(FromInner::from_inner(fd)))
348    }
349}
350
351#[stable(feature = "io_safety", since = "1.63.0")]
352impl From<UnixListener> for OwnedFd {
353    /// Takes ownership of a [`UnixListener`]'s socket file descriptor.
354    #[inline]
355    fn from(listener: UnixListener) -> OwnedFd {
356        listener.0.into_inner().into_inner()
357    }
358}
359
360#[stable(feature = "unix_socket", since = "1.10.0")]
361impl<'a> IntoIterator for &'a UnixListener {
362    type Item = io::Result<UnixStream>;
363    type IntoIter = Incoming<'a>;
364
365    fn into_iter(self) -> Incoming<'a> {
366        self.incoming()
367    }
368}
369
370/// An iterator over incoming connections to a [`UnixListener`].
371///
372/// It will never return [`None`].
373///
374/// # Examples
375///
376/// ```no_run
377/// use std::thread;
378/// use std::os::unix::net::{UnixStream, UnixListener};
379///
380/// fn handle_client(stream: UnixStream) {
381///     // ...
382/// }
383///
384/// fn main() -> std::io::Result<()> {
385///     let listener = UnixListener::bind("/path/to/the/socket")?;
386///
387///     for stream in listener.incoming() {
388///         match stream {
389///             Ok(stream) => {
390///                 thread::spawn(|| handle_client(stream));
391///             }
392///             Err(err) => {
393///                 break;
394///             }
395///         }
396///     }
397///     Ok(())
398/// }
399/// ```
400#[derive(Debug)]
401#[must_use = "iterators are lazy and do nothing unless consumed"]
402#[stable(feature = "unix_socket", since = "1.10.0")]
403pub struct Incoming<'a> {
404    listener: &'a UnixListener,
405}
406
407#[stable(feature = "unix_socket", since = "1.10.0")]
408impl<'a> Iterator for Incoming<'a> {
409    type Item = io::Result<UnixStream>;
410
411    fn next(&mut self) -> Option<io::Result<UnixStream>> {
412        Some(self.listener.accept().map(|s| s.0))
413    }
414
415    fn size_hint(&self) -> (usize, Option<usize>) {
416        (usize::MAX, None)
417    }
418}