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