Skip to main content

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