1use std::future;
2use std::io;
3use 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.
19pub trait ToSocketAddrs: sealed::ToSocketAddrsPriv {}
20
21type ReadyFuture<T> = future::Ready<io::Result<T>>;
22
23cfg_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
34impl<T: ToSocketAddrs + ?Sized> ToSocketAddrs for &T {}
35
36impl<T> sealed::ToSocketAddrsPriv for &T
37where
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
50impl ToSocketAddrs for SocketAddr {}
51
52impl 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: IntoIter = Some(*self).into_iter();
58 future::ready(Ok(iter))
59 }
60}
61
62// ===== impl SocketAddrV4 =====
63
64impl ToSocketAddrs for SocketAddrV4 {}
65
66impl 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
77impl ToSocketAddrs for SocketAddrV6 {}
78
79impl 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
90impl ToSocketAddrs for (IpAddr, u16) {}
91
92impl 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: IntoIter = Some(SocketAddr::from(*self)).into_iter();
98 future::ready(Ok(iter))
99 }
100}
101
102// ===== impl (Ipv4Addr, u16) =====
103
104impl ToSocketAddrs for (Ipv4Addr, u16) {}
105
106impl 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: Ipv4Addr, port: u16) = *self;
112 SocketAddrV4::new(ip, port).to_socket_addrs(sealed::Internal)
113 }
114}
115
116// ===== impl (Ipv6Addr, u16) =====
117
118impl ToSocketAddrs for (Ipv6Addr, u16) {}
119
120impl 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: Ipv6Addr, port: u16) = *self;
126 SocketAddrV6::new(ip, port, flowinfo:0, scope_id:0).to_socket_addrs(sealed::Internal)
127 }
128}
129
130// ===== impl &[SocketAddr] =====
131
132impl ToSocketAddrs for &[SocketAddr] {}
133
134impl 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: IntoIter = slice_to_vec(self).into_iter();
155 future::ready(Ok(iter))
156 }
157}
158
159cfg_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
252pub(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