1 | use std::future; |
2 | use std::io; |
3 | use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6}; |
4 | |
5 | /// Converts or resolves without blocking to one or more `SocketAddr` values. |
6 | /// |
7 | /// # DNS |
8 | /// |
9 | /// Implementations of `ToSocketAddrs` for string types require a DNS lookup. |
10 | /// |
11 | /// # Calling |
12 | /// |
13 | /// Currently, this trait is only used as an argument to Tokio functions that |
14 | /// need to reference a target socket address. To perform a `SocketAddr` |
15 | /// conversion directly, use [`lookup_host()`](super::lookup_host()). |
16 | /// |
17 | /// This trait is sealed and is intended to be opaque. The details of the trait |
18 | /// will change. Stabilization is pending enhancements to the Rust language. |
19 | pub trait ToSocketAddrs: sealed::ToSocketAddrsPriv {} |
20 | |
21 | type ReadyFuture<T> = future::Ready<io::Result<T>>; |
22 | |
23 | cfg_net! { |
24 | pub(crate) fn to_socket_addrs<T>(arg: T) -> T::Future |
25 | where |
26 | T: ToSocketAddrs, |
27 | { |
28 | arg.to_socket_addrs(sealed::Internal) |
29 | } |
30 | } |
31 | |
32 | // ===== impl &impl ToSocketAddrs ===== |
33 | |
34 | impl<T: ToSocketAddrs + ?Sized> ToSocketAddrs for &T {} |
35 | |
36 | impl<T> sealed::ToSocketAddrsPriv for &T |
37 | where |
38 | T: sealed::ToSocketAddrsPriv + ?Sized, |
39 | { |
40 | type Iter = T::Iter; |
41 | type Future = T::Future; |
42 | |
43 | fn to_socket_addrs(&self, _: sealed::Internal) -> Self::Future { |
44 | (**self).to_socket_addrs(sealed::Internal) |
45 | } |
46 | } |
47 | |
48 | // ===== impl SocketAddr ===== |
49 | |
50 | impl ToSocketAddrs for SocketAddr {} |
51 | |
52 | impl sealed::ToSocketAddrsPriv for SocketAddr { |
53 | type Iter = std::option::IntoIter<SocketAddr>; |
54 | type Future = ReadyFuture<Self::Iter>; |
55 | |
56 | fn to_socket_addrs(&self, _: sealed::Internal) -> Self::Future { |
57 | let iter = Some(*self).into_iter(); |
58 | future::ready(Ok(iter)) |
59 | } |
60 | } |
61 | |
62 | // ===== impl SocketAddrV4 ===== |
63 | |
64 | impl ToSocketAddrs for SocketAddrV4 {} |
65 | |
66 | impl sealed::ToSocketAddrsPriv for SocketAddrV4 { |
67 | type Iter = std::option::IntoIter<SocketAddr>; |
68 | type Future = ReadyFuture<Self::Iter>; |
69 | |
70 | fn to_socket_addrs(&self, _: sealed::Internal) -> Self::Future { |
71 | SocketAddr::V4(*self).to_socket_addrs(sealed::Internal) |
72 | } |
73 | } |
74 | |
75 | // ===== impl SocketAddrV6 ===== |
76 | |
77 | impl ToSocketAddrs for SocketAddrV6 {} |
78 | |
79 | impl sealed::ToSocketAddrsPriv for SocketAddrV6 { |
80 | type Iter = std::option::IntoIter<SocketAddr>; |
81 | type Future = ReadyFuture<Self::Iter>; |
82 | |
83 | fn to_socket_addrs(&self, _: sealed::Internal) -> Self::Future { |
84 | SocketAddr::V6(*self).to_socket_addrs(sealed::Internal) |
85 | } |
86 | } |
87 | |
88 | // ===== impl (IpAddr, u16) ===== |
89 | |
90 | impl ToSocketAddrs for (IpAddr, u16) {} |
91 | |
92 | impl sealed::ToSocketAddrsPriv for (IpAddr, u16) { |
93 | type Iter = std::option::IntoIter<SocketAddr>; |
94 | type Future = ReadyFuture<Self::Iter>; |
95 | |
96 | fn to_socket_addrs(&self, _: sealed::Internal) -> Self::Future { |
97 | let iter = Some(SocketAddr::from(*self)).into_iter(); |
98 | future::ready(Ok(iter)) |
99 | } |
100 | } |
101 | |
102 | // ===== impl (Ipv4Addr, u16) ===== |
103 | |
104 | impl ToSocketAddrs for (Ipv4Addr, u16) {} |
105 | |
106 | impl sealed::ToSocketAddrsPriv for (Ipv4Addr, u16) { |
107 | type Iter = std::option::IntoIter<SocketAddr>; |
108 | type Future = ReadyFuture<Self::Iter>; |
109 | |
110 | fn to_socket_addrs(&self, _: sealed::Internal) -> Self::Future { |
111 | let (ip, port) = *self; |
112 | SocketAddrV4::new(ip, port).to_socket_addrs(sealed::Internal) |
113 | } |
114 | } |
115 | |
116 | // ===== impl (Ipv6Addr, u16) ===== |
117 | |
118 | impl ToSocketAddrs for (Ipv6Addr, u16) {} |
119 | |
120 | impl sealed::ToSocketAddrsPriv for (Ipv6Addr, u16) { |
121 | type Iter = std::option::IntoIter<SocketAddr>; |
122 | type Future = ReadyFuture<Self::Iter>; |
123 | |
124 | fn to_socket_addrs(&self, _: sealed::Internal) -> Self::Future { |
125 | let (ip, port) = *self; |
126 | SocketAddrV6::new(ip, port, 0, 0).to_socket_addrs(sealed::Internal) |
127 | } |
128 | } |
129 | |
130 | // ===== impl &[SocketAddr] ===== |
131 | |
132 | impl ToSocketAddrs for &[SocketAddr] {} |
133 | |
134 | impl sealed::ToSocketAddrsPriv for &[SocketAddr] { |
135 | type Iter = std::vec::IntoIter<SocketAddr>; |
136 | type Future = ReadyFuture<Self::Iter>; |
137 | |
138 | fn to_socket_addrs(&self, _: sealed::Internal) -> Self::Future { |
139 | #[inline ] |
140 | fn slice_to_vec(addrs: &[SocketAddr]) -> Vec<SocketAddr> { |
141 | addrs.to_vec() |
142 | } |
143 | |
144 | // This uses a helper method because clippy doesn't like the `to_vec()` |
145 | // call here (it will allocate, whereas `self.iter().copied()` would |
146 | // not), but it's actually necessary in order to ensure that the |
147 | // returned iterator is valid for the `'static` lifetime, which the |
148 | // borrowed `slice::Iter` iterator would not be. |
149 | // |
150 | // Note that we can't actually add an `allow` attribute for |
151 | // `clippy::unnecessary_to_owned` here, as Tokio's CI runs clippy lints |
152 | // on Rust 1.52 to avoid breaking LTS releases of Tokio. Users of newer |
153 | // Rust versions who see this lint should just ignore it. |
154 | let iter = slice_to_vec(self).into_iter(); |
155 | future::ready(Ok(iter)) |
156 | } |
157 | } |
158 | |
159 | cfg_net! { |
160 | // ===== impl str ===== |
161 | |
162 | impl ToSocketAddrs for str {} |
163 | |
164 | impl sealed::ToSocketAddrsPriv for str { |
165 | type Iter = sealed::OneOrMore; |
166 | type Future = sealed::MaybeReady; |
167 | |
168 | fn to_socket_addrs(&self, _: sealed::Internal) -> Self::Future { |
169 | use crate::blocking::spawn_blocking; |
170 | use sealed::MaybeReady; |
171 | |
172 | // First check if the input parses as a socket address |
173 | let res: Result<SocketAddr, _> = self.parse(); |
174 | |
175 | if let Ok(addr) = res { |
176 | return MaybeReady(sealed::State::Ready(Some(addr))); |
177 | } |
178 | |
179 | // Run DNS lookup on the blocking pool |
180 | let s = self.to_owned(); |
181 | |
182 | MaybeReady(sealed::State::Blocking(spawn_blocking(move || { |
183 | std::net::ToSocketAddrs::to_socket_addrs(&s) |
184 | }))) |
185 | } |
186 | } |
187 | |
188 | // ===== impl (&str, u16) ===== |
189 | |
190 | impl ToSocketAddrs for (&str, u16) {} |
191 | |
192 | impl sealed::ToSocketAddrsPriv for (&str, u16) { |
193 | type Iter = sealed::OneOrMore; |
194 | type Future = sealed::MaybeReady; |
195 | |
196 | fn to_socket_addrs(&self, _: sealed::Internal) -> Self::Future { |
197 | use crate::blocking::spawn_blocking; |
198 | use sealed::MaybeReady; |
199 | |
200 | let (host, port) = *self; |
201 | |
202 | // try to parse the host as a regular IP address first |
203 | if let Ok(addr) = host.parse::<Ipv4Addr>() { |
204 | let addr = SocketAddrV4::new(addr, port); |
205 | let addr = SocketAddr::V4(addr); |
206 | |
207 | return MaybeReady(sealed::State::Ready(Some(addr))); |
208 | } |
209 | |
210 | if let Ok(addr) = host.parse::<Ipv6Addr>() { |
211 | let addr = SocketAddrV6::new(addr, port, 0, 0); |
212 | let addr = SocketAddr::V6(addr); |
213 | |
214 | return MaybeReady(sealed::State::Ready(Some(addr))); |
215 | } |
216 | |
217 | let host = host.to_owned(); |
218 | |
219 | MaybeReady(sealed::State::Blocking(spawn_blocking(move || { |
220 | std::net::ToSocketAddrs::to_socket_addrs(&(&host[..], port)) |
221 | }))) |
222 | } |
223 | } |
224 | |
225 | // ===== impl (String, u16) ===== |
226 | |
227 | impl ToSocketAddrs for (String, u16) {} |
228 | |
229 | impl sealed::ToSocketAddrsPriv for (String, u16) { |
230 | type Iter = sealed::OneOrMore; |
231 | type Future = sealed::MaybeReady; |
232 | |
233 | fn to_socket_addrs(&self, _: sealed::Internal) -> Self::Future { |
234 | (self.0.as_str(), self.1).to_socket_addrs(sealed::Internal) |
235 | } |
236 | } |
237 | |
238 | // ===== impl String ===== |
239 | |
240 | impl ToSocketAddrs for String {} |
241 | |
242 | impl sealed::ToSocketAddrsPriv for String { |
243 | type Iter = <str as sealed::ToSocketAddrsPriv>::Iter; |
244 | type Future = <str as sealed::ToSocketAddrsPriv>::Future; |
245 | |
246 | fn to_socket_addrs(&self, _: sealed::Internal) -> Self::Future { |
247 | self[..].to_socket_addrs(sealed::Internal) |
248 | } |
249 | } |
250 | } |
251 | |
252 | pub(crate) mod sealed { |
253 | //! The contents of this trait are intended to remain private and __not__ |
254 | //! part of the `ToSocketAddrs` public API. The details will change over |
255 | //! time. |
256 | |
257 | use std::future::Future; |
258 | use std::io; |
259 | use std::net::SocketAddr; |
260 | |
261 | #[doc (hidden)] |
262 | pub trait ToSocketAddrsPriv { |
263 | type Iter: Iterator<Item = SocketAddr> + Send + 'static; |
264 | type Future: Future<Output = io::Result<Self::Iter>> + Send + 'static; |
265 | |
266 | fn to_socket_addrs(&self, internal: Internal) -> Self::Future; |
267 | } |
268 | |
269 | #[allow (missing_debug_implementations)] |
270 | pub struct Internal; |
271 | |
272 | cfg_net! { |
273 | use crate::blocking::JoinHandle; |
274 | |
275 | use std::option; |
276 | use std::pin::Pin; |
277 | use std::task::{Context, Poll}; |
278 | use std::vec; |
279 | |
280 | #[doc (hidden)] |
281 | #[derive(Debug)] |
282 | pub struct MaybeReady(pub(super) State); |
283 | |
284 | #[derive(Debug)] |
285 | pub(super) enum State { |
286 | Ready(Option<SocketAddr>), |
287 | Blocking(JoinHandle<io::Result<vec::IntoIter<SocketAddr>>>), |
288 | } |
289 | |
290 | #[doc (hidden)] |
291 | #[derive(Debug)] |
292 | pub enum OneOrMore { |
293 | One(option::IntoIter<SocketAddr>), |
294 | More(vec::IntoIter<SocketAddr>), |
295 | } |
296 | |
297 | impl Future for MaybeReady { |
298 | type Output = io::Result<OneOrMore>; |
299 | |
300 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { |
301 | match self.0 { |
302 | State::Ready(ref mut i) => { |
303 | let iter = OneOrMore::One(i.take().into_iter()); |
304 | Poll::Ready(Ok(iter)) |
305 | } |
306 | State::Blocking(ref mut rx) => { |
307 | let res = ready!(Pin::new(rx).poll(cx))?.map(OneOrMore::More); |
308 | |
309 | Poll::Ready(res) |
310 | } |
311 | } |
312 | } |
313 | } |
314 | |
315 | impl Iterator for OneOrMore { |
316 | type Item = SocketAddr; |
317 | |
318 | fn next(&mut self) -> Option<Self::Item> { |
319 | match self { |
320 | OneOrMore::One(i) => i.next(), |
321 | OneOrMore::More(i) => i.next(), |
322 | } |
323 | } |
324 | |
325 | fn size_hint(&self) -> (usize, Option<usize>) { |
326 | match self { |
327 | OneOrMore::One(i) => i.size_hint(), |
328 | OneOrMore::More(i) => i.size_hint(), |
329 | } |
330 | } |
331 | } |
332 | } |
333 | } |
334 | |