• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
to_socket_addrs(&self, _: sealed::Internal) -> Self::Future43     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 
to_socket_addrs(&self, _: sealed::Internal) -> Self::Future56     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 
to_socket_addrs(&self, _: sealed::Internal) -> Self::Future70     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 
to_socket_addrs(&self, _: sealed::Internal) -> Self::Future83     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 
to_socket_addrs(&self, _: sealed::Internal) -> Self::Future96     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 
to_socket_addrs(&self, _: sealed::Internal) -> Self::Future110     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 
to_socket_addrs(&self, _: sealed::Internal) -> Self::Future124     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 
to_socket_addrs(&self, _: sealed::Internal) -> Self::Future138     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 
to_socket_addrs(&self, internal: Internal) -> Self::Future266         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