1 | use crate::io::{Interest, PollEvented}; |
2 | use crate::net::unix::{SocketAddr, UnixStream}; |
3 | |
4 | use std::fmt; |
5 | use std::io; |
6 | use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd}; |
7 | use std::os::unix::net; |
8 | use std::path::Path; |
9 | use std::task::{Context, Poll}; |
10 | |
11 | cfg_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 | |
52 | impl 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 | |
193 | impl 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 | |
205 | impl fmt::Debug for UnixListener { |
206 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
207 | self.io.fmt(f) |
208 | } |
209 | } |
210 | |
211 | impl AsRawFd for UnixListener { |
212 | fn as_raw_fd(&self) -> RawFd { |
213 | self.io.as_raw_fd() |
214 | } |
215 | } |
216 | |
217 | impl AsFd for UnixListener { |
218 | fn as_fd(&self) -> BorrowedFd<'_> { |
219 | unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) } |
220 | } |
221 | } |
222 | |