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 pub(crate) fn new(listener: mio::net::UnixListener) -> io::Result<UnixListener> {
54 let io = PollEvented::new(listener)?;
55 Ok(UnixListener { io })
56 }
57
58 /// Creates a new `UnixListener` bound to the specified path.
59 ///
60 /// # Panics
61 ///
62 /// This function panics if it is not called from within a runtime with
63 /// IO enabled.
64 ///
65 /// The runtime is usually set implicitly when this function is called
66 /// from a future driven by a tokio runtime, otherwise runtime can be set
67 /// explicitly with [`Runtime::enter`](crate::runtime::Runtime::enter) function.
68 #[track_caller]
69 pub fn bind<P>(path: P) -> io::Result<UnixListener>
70 where
71 P: AsRef<Path>,
72 {
73 let listener = mio::net::UnixListener::bind(path)?;
74 let io = PollEvented::new(listener)?;
75 Ok(UnixListener { io })
76 }
77
78 /// Creates new [`UnixListener`] from a [`std::os::unix::net::UnixListener`].
79 ///
80 /// This function is intended to be used to wrap a `UnixListener` from the
81 /// standard library in the Tokio equivalent.
82 ///
83 /// # Notes
84 ///
85 /// The caller is responsible for ensuring that the listener is in
86 /// non-blocking mode. Otherwise all I/O operations on the listener
87 /// will block the thread, which will cause unexpected behavior.
88 /// Non-blocking mode can be set using [`set_nonblocking`].
89 ///
90 /// [`set_nonblocking`]: std::os::unix::net::UnixListener::set_nonblocking
91 ///
92 /// # Examples
93 ///
94 /// ```no_run
95 /// use tokio::net::UnixListener;
96 /// use std::os::unix::net::UnixListener as StdUnixListener;
97 /// # use std::error::Error;
98 ///
99 /// # async fn dox() -> Result<(), Box<dyn Error>> {
100 /// let std_listener = StdUnixListener::bind("/path/to/the/socket")?;
101 /// std_listener.set_nonblocking(true)?;
102 /// let listener = UnixListener::from_std(std_listener)?;
103 /// # Ok(())
104 /// # }
105 /// ```
106 ///
107 /// # Panics
108 ///
109 /// This function panics if it is not called from within a runtime with
110 /// IO enabled.
111 ///
112 /// The runtime is usually set implicitly when this function is called
113 /// from a future driven by a tokio runtime, otherwise runtime can be set
114 /// explicitly with [`Runtime::enter`](crate::runtime::Runtime::enter) function.
115 #[track_caller]
116 pub fn from_std(listener: net::UnixListener) -> io::Result<UnixListener> {
117 let listener = mio::net::UnixListener::from_std(listener);
118 let io = PollEvented::new(listener)?;
119 Ok(UnixListener { io })
120 }
121
122 /// Turns a [`tokio::net::UnixListener`] into a [`std::os::unix::net::UnixListener`].
123 ///
124 /// The returned [`std::os::unix::net::UnixListener`] will have nonblocking mode
125 /// set as `true`. Use [`set_nonblocking`] to change the blocking mode if needed.
126 ///
127 /// # Examples
128 ///
129 /// ```rust,no_run
130 /// # use std::error::Error;
131 /// # async fn dox() -> Result<(), Box<dyn Error>> {
132 /// let tokio_listener = tokio::net::UnixListener::bind("/path/to/the/socket")?;
133 /// let std_listener = tokio_listener.into_std()?;
134 /// std_listener.set_nonblocking(false)?;
135 /// # Ok(())
136 /// # }
137 /// ```
138 ///
139 /// [`tokio::net::UnixListener`]: UnixListener
140 /// [`std::os::unix::net::UnixListener`]: std::os::unix::net::UnixListener
141 /// [`set_nonblocking`]: fn@std::os::unix::net::UnixListener::set_nonblocking
142 pub fn into_std(self) -> io::Result<std::os::unix::net::UnixListener> {
143 self.io
144 .into_inner()
145 .map(IntoRawFd::into_raw_fd)
146 .map(|raw_fd| unsafe { net::UnixListener::from_raw_fd(raw_fd) })
147 }
148
149 /// Returns the local socket address of this listener.
150 pub fn local_addr(&self) -> io::Result<SocketAddr> {
151 self.io.local_addr().map(SocketAddr)
152 }
153
154 /// Returns the value of the `SO_ERROR` option.
155 pub fn take_error(&self) -> io::Result<Option<io::Error>> {
156 self.io.take_error()
157 }
158
159 /// Accepts a new incoming connection to this listener.
160 ///
161 /// # Cancel safety
162 ///
163 /// This method is cancel safe. If the method is used as the event in a
164 /// [`tokio::select!`](crate::select) statement and some other branch
165 /// completes first, then it is guaranteed that no new connections were
166 /// accepted by this method.
167 pub async fn accept(&self) -> io::Result<(UnixStream, SocketAddr)> {
168 let (mio, addr) = self
169 .io
170 .registration()
171 .async_io(Interest::READABLE, || self.io.accept())
172 .await?;
173
174 let addr = SocketAddr(addr);
175 let stream = UnixStream::new(mio)?;
176 Ok((stream, addr))
177 }
178
179 /// Polls to accept a new incoming connection to this listener.
180 ///
181 /// If there is no connection to accept, `Poll::Pending` is returned and the
182 /// current task will be notified by a waker. Note that on multiple calls
183 /// to `poll_accept`, only the `Waker` from the `Context` passed to the most
184 /// recent call is scheduled to receive a wakeup.
185 pub fn poll_accept(&self, cx: &mut Context<'_>) -> Poll<io::Result<(UnixStream, SocketAddr)>> {
186 let (sock, addr) = ready!(self.io.registration().poll_read_io(cx, || self.io.accept()))?;
187 let addr = SocketAddr(addr);
188 let sock = UnixStream::new(sock)?;
189 Poll::Ready(Ok((sock, addr)))
190 }
191}
192
193impl TryFrom<std::os::unix::net::UnixListener> for UnixListener {
194 type Error = io::Error;
195
196 /// Consumes stream, returning the tokio I/O object.
197 ///
198 /// This is equivalent to
199 /// [`UnixListener::from_std(stream)`](UnixListener::from_std).
200 fn try_from(stream: std::os::unix::net::UnixListener) -> io::Result<Self> {
201 Self::from_std(listener:stream)
202 }
203}
204
205impl fmt::Debug for UnixListener {
206 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
207 self.io.fmt(f)
208 }
209}
210
211impl AsRawFd for UnixListener {
212 fn as_raw_fd(&self) -> RawFd {
213 self.io.as_raw_fd()
214 }
215}
216
217impl AsFd for UnixListener {
218 fn as_fd(&self) -> BorrowedFd<'_> {
219 unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) }
220 }
221}
222