1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
use std::{io, net::SocketAddr, vec};
use dns_lookup::AddrInfoHints;
use hyper::client::connect::dns::Name;
use tokio::task::JoinHandle;
use crate::background;
#[derive(Debug, Builder, Default)]
pub struct System {
pub addr_info_hints: Option<AddrInfoHints>,
pub service: Option<String>,
}
impl background::Resolve for System {
type Iter = vec::IntoIter<SocketAddr>;
fn resolve(&mut self, name: Name) -> JoinHandle<io::Result<Self::Iter>> {
let addr_info_hints = self.addr_info_hints;
tokio::task::spawn_blocking(move || {
debug!("resolving host={:?}", name);
let iter = dns_lookup::getaddrinfo(Some(name.as_str()), None, addr_info_hints)?;
let list = iter
.map(|result| result.map(|addr_info| addr_info.sockaddr))
.collect::<Result<Vec<_>, _>>()?;
Ok(list.into_iter())
})
}
}
pub type Resolver = background::Resolver<System>;
#[cfg(test)]
mod tests {
use std::{
net::{Ipv4Addr, Ipv6Addr, SocketAddrV4, SocketAddrV6},
str::FromStr,
};
use tower_service::Service;
use crate::addr_info_hints::AddressFamily;
use super::*;
#[tokio::test]
async fn test_resolve_ipv4() {
let mut resolver = background::Resolver::new(System {
addr_info_hints: Some(
crate::AddrInfoHints {
address_family: AddressFamily::Inet,
}
.into(),
),
service: None,
});
let addrs: Vec<_> = resolver
.call(Name::from_str("localhost").unwrap())
.await
.unwrap()
.collect();
let localhost = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 0));
assert_eq!(addrs, vec![localhost, localhost]);
}
#[tokio::test]
async fn test_resolve_ipv6() {
let mut resolver = background::Resolver::new(System {
addr_info_hints: Some(
crate::AddrInfoHints {
address_family: AddressFamily::Inet6,
}
.into(),
),
service: None,
});
let addrs: Vec<_> = resolver
.call(Name::from_str("localhost").unwrap())
.await
.unwrap()
.collect();
let localhost = SocketAddr::V6(SocketAddrV6::new(
Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1),
0,
0,
0,
));
assert_eq!(addrs, vec![localhost, localhost]);
}
}