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