/rust/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.47.1/src/net/addr.rs
Line | Count | Source (jump to first uncovered line) |
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 | 0 | pub(crate) fn to_socket_addrs<T>(arg: T) -> T::Future |
25 | 0 | where |
26 | 0 | T: ToSocketAddrs, |
27 | 0 | { |
28 | 0 | arg.to_socket_addrs(sealed::Internal) |
29 | 0 | } |
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 | 0 | fn to_socket_addrs(&self, _: sealed::Internal) -> Self::Future { |
44 | 0 | (**self).to_socket_addrs(sealed::Internal) |
45 | 0 | } |
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 | 0 | fn to_socket_addrs(&self, _: sealed::Internal) -> Self::Future { |
57 | 0 | let iter = Some(*self).into_iter(); |
58 | 0 | future::ready(Ok(iter)) |
59 | 0 | } |
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 | 0 | fn to_socket_addrs(&self, _: sealed::Internal) -> Self::Future { |
71 | 0 | SocketAddr::V4(*self).to_socket_addrs(sealed::Internal) |
72 | 0 | } |
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 | 0 | fn to_socket_addrs(&self, _: sealed::Internal) -> Self::Future { |
84 | 0 | SocketAddr::V6(*self).to_socket_addrs(sealed::Internal) |
85 | 0 | } |
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 | 0 | fn to_socket_addrs(&self, _: sealed::Internal) -> Self::Future { |
97 | 0 | let iter = Some(SocketAddr::from(*self)).into_iter(); |
98 | 0 | future::ready(Ok(iter)) |
99 | 0 | } |
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 | 0 | fn to_socket_addrs(&self, _: sealed::Internal) -> Self::Future { |
111 | 0 | let (ip, port) = *self; |
112 | 0 | SocketAddrV4::new(ip, port).to_socket_addrs(sealed::Internal) |
113 | 0 | } |
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 | 0 | fn to_socket_addrs(&self, _: sealed::Internal) -> Self::Future { |
125 | 0 | let (ip, port) = *self; |
126 | 0 | SocketAddrV6::new(ip, port, 0, 0).to_socket_addrs(sealed::Internal) |
127 | 0 | } |
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 | 0 | fn to_socket_addrs(&self, _: sealed::Internal) -> Self::Future { |
139 | | #[inline] |
140 | 0 | fn slice_to_vec(addrs: &[SocketAddr]) -> Vec<SocketAddr> { |
141 | 0 | addrs.to_vec() |
142 | 0 | } |
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 | 0 | let iter = slice_to_vec(self).into_iter(); |
155 | 0 | future::ready(Ok(iter)) |
156 | 0 | } |
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 | 0 | 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 | 0 | let res: Result<SocketAddr, _> = self.parse(); |
174 | | |
175 | 0 | if let Ok(addr) = res { |
176 | 0 | return MaybeReady(sealed::State::Ready(Some(addr))); |
177 | 0 | } |
178 | 0 |
|
179 | 0 | // Run DNS lookup on the blocking pool |
180 | 0 | let s = self.to_owned(); |
181 | 0 |
|
182 | 0 | MaybeReady(sealed::State::Blocking(spawn_blocking(move || { |
183 | 0 | std::net::ToSocketAddrs::to_socket_addrs(&s) |
184 | 0 | }))) |
185 | 0 | } |
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 | 0 | fn to_socket_addrs(&self, _: sealed::Internal) -> Self::Future { |
197 | | use crate::blocking::spawn_blocking; |
198 | | use sealed::MaybeReady; |
199 | | |
200 | 0 | let (host, port) = *self; |
201 | | |
202 | | // try to parse the host as a regular IP address first |
203 | 0 | if let Ok(addr) = host.parse::<Ipv4Addr>() { |
204 | 0 | let addr = SocketAddrV4::new(addr, port); |
205 | 0 | let addr = SocketAddr::V4(addr); |
206 | 0 |
|
207 | 0 | return MaybeReady(sealed::State::Ready(Some(addr))); |
208 | 0 | } |
209 | | |
210 | 0 | if let Ok(addr) = host.parse::<Ipv6Addr>() { |
211 | 0 | let addr = SocketAddrV6::new(addr, port, 0, 0); |
212 | 0 | let addr = SocketAddr::V6(addr); |
213 | 0 |
|
214 | 0 | return MaybeReady(sealed::State::Ready(Some(addr))); |
215 | 0 | } |
216 | 0 |
|
217 | 0 | let host = host.to_owned(); |
218 | 0 |
|
219 | 0 | MaybeReady(sealed::State::Blocking(spawn_blocking(move || { |
220 | 0 | std::net::ToSocketAddrs::to_socket_addrs(&(&host[..], port)) |
221 | 0 | }))) |
222 | 0 | } |
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 | 0 | fn to_socket_addrs(&self, _: sealed::Internal) -> Self::Future { |
234 | 0 | (self.0.as_str(), self.1).to_socket_addrs(sealed::Internal) |
235 | 0 | } |
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 | 0 | fn to_socket_addrs(&self, _: sealed::Internal) -> Self::Future { |
247 | 0 | self[..].to_socket_addrs(sealed::Internal) |
248 | 0 | } |
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::{ready,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 | 0 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { |
301 | 0 | match self.0 { |
302 | 0 | State::Ready(ref mut i) => { |
303 | 0 | let iter = OneOrMore::One(i.take().into_iter()); |
304 | 0 | Poll::Ready(Ok(iter)) |
305 | | } |
306 | 0 | State::Blocking(ref mut rx) => { |
307 | 0 | let res = ready!(Pin::new(rx).poll(cx))?.map(OneOrMore::More); |
308 | 0 |
|
309 | 0 | Poll::Ready(res) |
310 | | } |
311 | | } |
312 | 0 | } |
313 | | } |
314 | | |
315 | | impl Iterator for OneOrMore { |
316 | | type Item = SocketAddr; |
317 | | |
318 | 0 | fn next(&mut self) -> Option<Self::Item> { |
319 | 0 | match self { |
320 | 0 | OneOrMore::One(i) => i.next(), |
321 | 0 | OneOrMore::More(i) => i.next(), |
322 | | } |
323 | 0 | } |
324 | | |
325 | 0 | fn size_hint(&self) -> (usize, Option<usize>) { |
326 | 0 | match self { |
327 | 0 | OneOrMore::One(i) => i.size_hint(), |
328 | 0 | OneOrMore::More(i) => i.size_hint(), |
329 | | } |
330 | 0 | } |
331 | | } |
332 | | } |
333 | | } |