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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
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, Clone)]
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>;
impl System {
pub fn resolver(self) -> Resolver {
Resolver::new(self)
}
}
impl From<System> for Resolver {
fn from(system: System) -> Self {
system.resolver()
}
}
#[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!(addrs.len() > 0);
for addr in addrs {
assert_eq!(addr, 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!(addrs.len() > 0);
for addr in addrs {
assert_eq!(addr, localhost);
}
}
}