hyper_util/client/legacy/connect/
dns.rs1use std::error::Error;
25use std::future::Future;
26use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs};
27use std::pin::Pin;
28use std::str::FromStr;
29use std::task::{self, Poll};
30use std::{fmt, io, vec};
31
32use tokio::task::JoinHandle;
33use tower_service::Service;
34use tracing::debug_span;
35
36pub(super) use self::sealed::Resolve;
37
38#[derive(Clone, Hash, Eq, PartialEq)]
40pub struct Name {
41 host: Box<str>,
42}
43
44#[derive(Clone)]
46pub struct GaiResolver {
47 _priv: (),
48}
49
50pub struct GaiAddrs {
52 inner: SocketAddrs,
53}
54
55pub struct GaiFuture {
57 inner: JoinHandle<Result<SocketAddrs, io::Error>>,
58}
59
60impl Name {
61 pub(super) fn new(host: Box<str>) -> Name {
62 Name { host }
63 }
64
65 pub fn as_str(&self) -> &str {
67 &self.host
68 }
69}
70
71impl fmt::Debug for Name {
72 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
73 fmt::Debug::fmt(&self.host, f)
74 }
75}
76
77impl fmt::Display for Name {
78 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
79 fmt::Display::fmt(&self.host, f)
80 }
81}
82
83impl FromStr for Name {
84 type Err = InvalidNameError;
85
86 fn from_str(host: &str) -> Result<Self, Self::Err> {
87 Ok(Name::new(host.into()))
89 }
90}
91
92#[derive(Debug)]
94pub struct InvalidNameError(());
95
96impl fmt::Display for InvalidNameError {
97 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
98 f.write_str("Not a valid domain name")
99 }
100}
101
102impl Error for InvalidNameError {}
103
104impl GaiResolver {
105 pub fn new() -> Self {
107 GaiResolver { _priv: () }
108 }
109}
110
111impl Service<Name> for GaiResolver {
112 type Response = GaiAddrs;
113 type Error = io::Error;
114 type Future = GaiFuture;
115
116 fn poll_ready(&mut self, _cx: &mut task::Context<'_>) -> Poll<Result<(), io::Error>> {
117 Poll::Ready(Ok(()))
118 }
119
120 fn call(&mut self, name: Name) -> Self::Future {
121 let span = debug_span!("resolve", host = %name.host);
122 let blocking = tokio::task::spawn_blocking(move || {
123 let _enter = span.enter();
124 (&*name.host, 0)
125 .to_socket_addrs()
126 .map(|i| SocketAddrs { iter: i })
127 });
128
129 GaiFuture { inner: blocking }
130 }
131}
132
133impl fmt::Debug for GaiResolver {
134 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
135 f.pad("GaiResolver")
136 }
137}
138
139impl Future for GaiFuture {
140 type Output = Result<GaiAddrs, io::Error>;
141
142 fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> {
143 Pin::new(&mut self.inner).poll(cx).map(|res| match res {
144 Ok(Ok(addrs)) => Ok(GaiAddrs { inner: addrs }),
145 Ok(Err(err)) => Err(err),
146 Err(join_err) => {
147 if join_err.is_cancelled() {
148 Err(io::Error::new(io::ErrorKind::Interrupted, join_err))
149 } else {
150 panic!("gai background task failed: {:?}", join_err)
151 }
152 }
153 })
154 }
155}
156
157impl fmt::Debug for GaiFuture {
158 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
159 f.pad("GaiFuture")
160 }
161}
162
163impl Drop for GaiFuture {
164 fn drop(&mut self) {
165 self.inner.abort();
166 }
167}
168
169impl Iterator for GaiAddrs {
170 type Item = SocketAddr;
171
172 fn next(&mut self) -> Option<Self::Item> {
173 self.inner.next()
174 }
175}
176
177impl fmt::Debug for GaiAddrs {
178 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
179 f.pad("GaiAddrs")
180 }
181}
182
183pub(super) struct SocketAddrs {
184 iter: vec::IntoIter<SocketAddr>,
185}
186
187impl SocketAddrs {
188 pub(super) fn new(addrs: Vec<SocketAddr>) -> Self {
189 SocketAddrs {
190 iter: addrs.into_iter(),
191 }
192 }
193
194 pub(super) fn try_parse(host: &str, port: u16) -> Option<SocketAddrs> {
195 if let Ok(addr) = host.parse::<Ipv4Addr>() {
196 let addr = SocketAddrV4::new(addr, port);
197 return Some(SocketAddrs {
198 iter: vec![SocketAddr::V4(addr)].into_iter(),
199 });
200 }
201 if let Ok(addr) = host.parse::<Ipv6Addr>() {
202 let addr = SocketAddrV6::new(addr, port, 0, 0);
203 return Some(SocketAddrs {
204 iter: vec![SocketAddr::V6(addr)].into_iter(),
205 });
206 }
207 None
208 }
209
210 #[inline]
211 fn filter(self, predicate: impl FnMut(&SocketAddr) -> bool) -> SocketAddrs {
212 SocketAddrs::new(self.iter.filter(predicate).collect())
213 }
214
215 pub(super) fn split_by_preference(
216 self,
217 local_addr_ipv4: Option<Ipv4Addr>,
218 local_addr_ipv6: Option<Ipv6Addr>,
219 ) -> (SocketAddrs, SocketAddrs) {
220 match (local_addr_ipv4, local_addr_ipv6) {
221 (Some(_), None) => (self.filter(SocketAddr::is_ipv4), SocketAddrs::new(vec![])),
222 (None, Some(_)) => (self.filter(SocketAddr::is_ipv6), SocketAddrs::new(vec![])),
223 _ => {
224 let preferring_v6 = self
225 .iter
226 .as_slice()
227 .first()
228 .map(SocketAddr::is_ipv6)
229 .unwrap_or(false);
230
231 let (preferred, fallback) = self
232 .iter
233 .partition::<Vec<_>, _>(|addr| addr.is_ipv6() == preferring_v6);
234
235 (SocketAddrs::new(preferred), SocketAddrs::new(fallback))
236 }
237 }
238 }
239
240 pub(super) fn is_empty(&self) -> bool {
241 self.iter.as_slice().is_empty()
242 }
243
244 pub(super) fn len(&self) -> usize {
245 self.iter.as_slice().len()
246 }
247}
248
249impl Iterator for SocketAddrs {
250 type Item = SocketAddr;
251 #[inline]
252 fn next(&mut self) -> Option<SocketAddr> {
253 self.iter.next()
254 }
255}
256
257mod sealed {
258 use std::future::Future;
259 use std::task::{self, Poll};
260
261 use super::{Name, SocketAddr};
262 use tower_service::Service;
263
264 pub trait Resolve {
266 type Addrs: Iterator<Item = SocketAddr>;
267 type Error: Into<Box<dyn std::error::Error + Send + Sync>>;
268 type Future: Future<Output = Result<Self::Addrs, Self::Error>>;
269
270 fn poll_ready(&mut self, cx: &mut task::Context<'_>) -> Poll<Result<(), Self::Error>>;
271 fn resolve(&mut self, name: Name) -> Self::Future;
272 }
273
274 impl<S> Resolve for S
275 where
276 S: Service<Name>,
277 S::Response: Iterator<Item = SocketAddr>,
278 S::Error: Into<Box<dyn std::error::Error + Send + Sync>>,
279 {
280 type Addrs = S::Response;
281 type Error = S::Error;
282 type Future = S::Future;
283
284 fn poll_ready(&mut self, cx: &mut task::Context<'_>) -> Poll<Result<(), Self::Error>> {
285 Service::poll_ready(self, cx)
286 }
287
288 fn resolve(&mut self, name: Name) -> Self::Future {
289 Service::call(self, name)
290 }
291 }
292}
293
294pub(super) async fn resolve<R>(resolver: &mut R, name: Name) -> Result<R::Addrs, R::Error>
295where
296 R: Resolve,
297{
298 futures_util::future::poll_fn(|cx| resolver.poll_ready(cx)).await?;
299 resolver.resolve(name).await
300}
301
302#[cfg(test)]
303mod tests {
304 use super::*;
305 use std::net::{Ipv4Addr, Ipv6Addr};
306
307 #[test]
308 fn test_ip_addrs_split_by_preference() {
309 let ip_v4 = Ipv4Addr::new(127, 0, 0, 1);
310 let ip_v6 = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
311 let v4_addr = (ip_v4, 80).into();
312 let v6_addr = (ip_v6, 80).into();
313
314 let (mut preferred, mut fallback) = SocketAddrs {
315 iter: vec![v4_addr, v6_addr].into_iter(),
316 }
317 .split_by_preference(None, None);
318 assert!(preferred.next().unwrap().is_ipv4());
319 assert!(fallback.next().unwrap().is_ipv6());
320
321 let (mut preferred, mut fallback) = SocketAddrs {
322 iter: vec![v6_addr, v4_addr].into_iter(),
323 }
324 .split_by_preference(None, None);
325 assert!(preferred.next().unwrap().is_ipv6());
326 assert!(fallback.next().unwrap().is_ipv4());
327
328 let (mut preferred, mut fallback) = SocketAddrs {
329 iter: vec![v4_addr, v6_addr].into_iter(),
330 }
331 .split_by_preference(Some(ip_v4), Some(ip_v6));
332 assert!(preferred.next().unwrap().is_ipv4());
333 assert!(fallback.next().unwrap().is_ipv6());
334
335 let (mut preferred, mut fallback) = SocketAddrs {
336 iter: vec![v6_addr, v4_addr].into_iter(),
337 }
338 .split_by_preference(Some(ip_v4), Some(ip_v6));
339 assert!(preferred.next().unwrap().is_ipv6());
340 assert!(fallback.next().unwrap().is_ipv4());
341
342 let (mut preferred, fallback) = SocketAddrs {
343 iter: vec![v4_addr, v6_addr].into_iter(),
344 }
345 .split_by_preference(Some(ip_v4), None);
346 assert!(preferred.next().unwrap().is_ipv4());
347 assert!(fallback.is_empty());
348
349 let (mut preferred, fallback) = SocketAddrs {
350 iter: vec![v4_addr, v6_addr].into_iter(),
351 }
352 .split_by_preference(None, Some(ip_v6));
353 assert!(preferred.next().unwrap().is_ipv6());
354 assert!(fallback.is_empty());
355 }
356
357 #[test]
358 fn test_name_from_str() {
359 const DOMAIN: &str = "test.example.com";
360 let name = Name::from_str(DOMAIN).expect("Should be a valid domain");
361 assert_eq!(name.as_str(), DOMAIN);
362 assert_eq!(name.to_string(), DOMAIN);
363 }
364}