Skip to main content

std/os/unix/net/
listener.rs

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