[go: up one dir, main page]

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