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