tokio/net/unix/
listener.rs

1use crate::io::{Interest, PollEvented};
2use crate::net::unix::{SocketAddr, UnixStream};
3
4use std::fmt;
5use std::io;
6#[cfg(target_os = "android")]
7use std::os::android::net::SocketAddrExt;
8#[cfg(target_os = "linux")]
9use std::os::linux::net::SocketAddrExt;
10#[cfg(any(target_os = "linux", target_os = "android"))]
11use std::os::unix::ffi::OsStrExt;
12use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd};
13use std::os::unix::net::{self, SocketAddr as StdSocketAddr};
14use std::path::Path;
15use std::task::{ready, Context, Poll};
16
17cfg_net_unix! {
18    /// A Unix socket which can accept connections from other Unix sockets.
19    ///
20    /// You can accept a new connection by using the [`accept`](`UnixListener::accept`) method.
21    ///
22    /// A `UnixListener` can be turned into a `Stream` with [`UnixListenerStream`].
23    ///
24    /// [`UnixListenerStream`]: https://docs.rs/tokio-stream/0.1/tokio_stream/wrappers/struct.UnixListenerStream.html
25    ///
26    /// # Errors
27    ///
28    /// Note that accepting a connection can lead to various errors and not all
29    /// of them are necessarily fatal ‒ for example having too many open file
30    /// descriptors or the other side closing the connection while it waits in
31    /// an accept queue. These would terminate the stream if not handled in any
32    /// way.
33    ///
34    /// # Examples
35    ///
36    /// ```no_run
37    /// use tokio::net::UnixListener;
38    ///
39    /// #[tokio::main]
40    /// async fn main() {
41    ///     let listener = UnixListener::bind("/path/to/the/socket").unwrap();
42    ///     loop {
43    ///         match listener.accept().await {
44    ///             Ok((stream, _addr)) => {
45    ///                 println!("new client!");
46    ///             }
47    ///             Err(e) => { /* connection failed */ }
48    ///         }
49    ///     }
50    /// }
51    /// ```
52    #[cfg_attr(docsrs, doc(alias = "uds"))]
53    pub struct UnixListener {
54        io: PollEvented<mio::net::UnixListener>,
55    }
56}
57
58impl UnixListener {
59    pub(crate) fn new(listener: mio::net::UnixListener) -> io::Result<UnixListener> {
60        let io = PollEvented::new(listener)?;
61        Ok(UnixListener { io })
62    }
63
64    /// Creates a new `UnixListener` bound to the specified path.
65    ///
66    /// # Panics
67    ///
68    /// This function panics if it is not called from within a runtime with
69    /// IO enabled.
70    ///
71    /// The runtime is usually set implicitly when this function is called
72    /// from a future driven by a tokio runtime, otherwise runtime can be set
73    /// explicitly with [`Runtime::enter`](crate::runtime::Runtime::enter) function.
74    #[track_caller]
75    pub fn bind<P>(path: P) -> io::Result<UnixListener>
76    where
77        P: AsRef<Path>,
78    {
79        // For now, we handle abstract socket paths on linux here.
80        #[cfg(any(target_os = "linux", target_os = "android"))]
81        let addr = {
82            let os_str_bytes = path.as_ref().as_os_str().as_bytes();
83            if os_str_bytes.starts_with(b"\0") {
84                StdSocketAddr::from_abstract_name(&os_str_bytes[1..])?
85            } else {
86                StdSocketAddr::from_pathname(path)?
87            }
88        };
89        #[cfg(not(any(target_os = "linux", target_os = "android")))]
90        let addr = StdSocketAddr::from_pathname(path)?;
91
92        let listener = mio::net::UnixListener::bind_addr(&addr)?;
93        let io = PollEvented::new(listener)?;
94        Ok(UnixListener { io })
95    }
96
97    /// Creates new [`UnixListener`] from a [`std::os::unix::net::UnixListener`].
98    ///
99    /// This function is intended to be used to wrap a `UnixListener` from the
100    /// standard library in the Tokio equivalent.
101    ///
102    /// # Notes
103    ///
104    /// The caller is responsible for ensuring that the listener is in
105    /// non-blocking mode. Otherwise all I/O operations on the listener
106    /// will block the thread, which will cause unexpected behavior.
107    /// Non-blocking mode can be set using [`set_nonblocking`].
108    ///
109    /// [`set_nonblocking`]: std::os::unix::net::UnixListener::set_nonblocking
110    ///
111    /// # Examples
112    ///
113    /// ```no_run
114    /// use tokio::net::UnixListener;
115    /// use std::os::unix::net::UnixListener as StdUnixListener;
116    /// # use std::error::Error;
117    ///
118    /// # async fn dox() -> Result<(), Box<dyn Error>> {
119    /// let std_listener = StdUnixListener::bind("/path/to/the/socket")?;
120    /// std_listener.set_nonblocking(true)?;
121    /// let listener = UnixListener::from_std(std_listener)?;
122    /// # Ok(())
123    /// # }
124    /// ```
125    ///
126    /// # Panics
127    ///
128    /// This function panics if it is not called from within a runtime with
129    /// IO enabled.
130    ///
131    /// The runtime is usually set implicitly when this function is called
132    /// from a future driven by a tokio runtime, otherwise runtime can be set
133    /// explicitly with [`Runtime::enter`](crate::runtime::Runtime::enter) function.
134    #[track_caller]
135    pub fn from_std(listener: net::UnixListener) -> io::Result<UnixListener> {
136        let listener = mio::net::UnixListener::from_std(listener);
137        let io = PollEvented::new(listener)?;
138        Ok(UnixListener { io })
139    }
140
141    /// Turns a [`tokio::net::UnixListener`] into a [`std::os::unix::net::UnixListener`].
142    ///
143    /// The returned [`std::os::unix::net::UnixListener`] will have nonblocking mode
144    /// set as `true`. Use [`set_nonblocking`] to change the blocking mode if needed.
145    ///
146    /// # Examples
147    ///
148    /// ```rust,no_run
149    /// # use std::error::Error;
150    /// # async fn dox() -> Result<(), Box<dyn Error>> {
151    /// let tokio_listener = tokio::net::UnixListener::bind("/path/to/the/socket")?;
152    /// let std_listener = tokio_listener.into_std()?;
153    /// std_listener.set_nonblocking(false)?;
154    /// # Ok(())
155    /// # }
156    /// ```
157    ///
158    /// [`tokio::net::UnixListener`]: UnixListener
159    /// [`std::os::unix::net::UnixListener`]: std::os::unix::net::UnixListener
160    /// [`set_nonblocking`]: fn@std::os::unix::net::UnixListener::set_nonblocking
161    pub fn into_std(self) -> io::Result<std::os::unix::net::UnixListener> {
162        self.io
163            .into_inner()
164            .map(IntoRawFd::into_raw_fd)
165            .map(|raw_fd| unsafe { net::UnixListener::from_raw_fd(raw_fd) })
166    }
167
168    /// Returns the local socket address of this listener.
169    pub fn local_addr(&self) -> io::Result<SocketAddr> {
170        self.io.local_addr().map(SocketAddr)
171    }
172
173    /// Returns the value of the `SO_ERROR` option.
174    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
175        self.io.take_error()
176    }
177
178    /// Accepts a new incoming connection to this listener.
179    ///
180    /// # Cancel safety
181    ///
182    /// This method is cancel safe. If the method is used as the event in a
183    /// [`tokio::select!`](crate::select) statement and some other branch
184    /// completes first, then it is guaranteed that no new connections were
185    /// accepted by this method.
186    pub async fn accept(&self) -> io::Result<(UnixStream, SocketAddr)> {
187        let (mio, addr) = self
188            .io
189            .registration()
190            .async_io(Interest::READABLE, || self.io.accept())
191            .await?;
192
193        let addr = SocketAddr(addr);
194        let stream = UnixStream::new(mio)?;
195        Ok((stream, addr))
196    }
197
198    /// Polls to accept a new incoming connection to this listener.
199    ///
200    /// If there is no connection to accept, `Poll::Pending` is returned and the
201    /// current task will be notified by a waker.  Note that on multiple calls
202    /// to `poll_accept`, only the `Waker` from the `Context` passed to the most
203    /// recent call is scheduled to receive a wakeup.
204    pub fn poll_accept(&self, cx: &mut Context<'_>) -> Poll<io::Result<(UnixStream, SocketAddr)>> {
205        let (sock, addr) = ready!(self.io.registration().poll_read_io(cx, || self.io.accept()))?;
206        let addr = SocketAddr(addr);
207        let sock = UnixStream::new(sock)?;
208        Poll::Ready(Ok((sock, addr)))
209    }
210}
211
212impl TryFrom<std::os::unix::net::UnixListener> for UnixListener {
213    type Error = io::Error;
214
215    /// Consumes stream, returning the tokio I/O object.
216    ///
217    /// This is equivalent to
218    /// [`UnixListener::from_std(stream)`](UnixListener::from_std).
219    fn try_from(stream: std::os::unix::net::UnixListener) -> io::Result<Self> {
220        Self::from_std(stream)
221    }
222}
223
224impl fmt::Debug for UnixListener {
225    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
226        self.io.fmt(f)
227    }
228}
229
230impl AsRawFd for UnixListener {
231    fn as_raw_fd(&self) -> RawFd {
232        self.io.as_raw_fd()
233    }
234}
235
236impl AsFd for UnixListener {
237    fn as_fd(&self) -> BorrowedFd<'_> {
238        unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) }
239    }
240}