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 | /// 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 | |
188 | impl 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 | |
200 | impl fmt::Debug for UnixListener { |
201 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
202 | self.io.fmt(f) |
203 | } |
204 | } |
205 | |
206 | impl AsRawFd for UnixListener { |
207 | fn as_raw_fd(&self) -> RawFd { |
208 | self.io.as_raw_fd() |
209 | } |
210 | } |
211 | |
212 | impl AsFd for UnixListener { |
213 | fn as_fd(&self) -> BorrowedFd<'_> { |
214 | unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) } |
215 | } |
216 | } |
217 | |