1 use std::future::Future;
2 use std::io;
3 use std::net::SocketAddr;
4 use std::pin::Pin;
5 use std::sync::Arc;
6 use std::task::{self, Poll};
7
8 use hyper::client::connect::dns as hyper_dns;
9 use hyper::service::Service;
10 use tokio::sync::Mutex;
11 use trust_dns_resolver::{
12 config::{ResolverConfig, ResolverOpts},
13 lookup_ip::LookupIpIntoIter,
14 system_conf, AsyncResolver, TokioConnection, TokioConnectionProvider, TokioHandle,
15 };
16
17 use crate::error::BoxError;
18
19 type SharedResolver = Arc<AsyncResolver<TokioConnection, TokioConnectionProvider>>;
20
21 lazy_static! {
22 static ref SYSTEM_CONF: io::Result<(ResolverConfig, ResolverOpts)> =
23 system_conf::read_system_conf().map_err(io::Error::from);
24 }
25
26 #[derive(Clone)]
27 pub(crate) struct TrustDnsResolver {
28 state: Arc<Mutex<State>>,
29 }
30
31 pub(crate) struct SocketAddrs {
32 iter: LookupIpIntoIter,
33 }
34
35 enum State {
36 Init,
37 Ready(SharedResolver),
38 }
39
40 impl TrustDnsResolver {
new() -> io::Result<Self>41 pub(crate) fn new() -> io::Result<Self> {
42 SYSTEM_CONF.as_ref().map_err(|e| {
43 io::Error::new(e.kind(), format!("error reading DNS system conf: {}", e))
44 })?;
45
46 // At this stage, we might not have been called in the context of a
47 // Tokio Runtime, so we must delay the actual construction of the
48 // resolver.
49 Ok(TrustDnsResolver {
50 state: Arc::new(Mutex::new(State::Init)),
51 })
52 }
53 }
54
55 impl Service<hyper_dns::Name> for TrustDnsResolver {
56 type Response = SocketAddrs;
57 type Error = BoxError;
58 type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>> + Send>>;
59
poll_ready(&mut self, _: &mut task::Context<'_>) -> Poll<Result<(), Self::Error>>60 fn poll_ready(&mut self, _: &mut task::Context<'_>) -> Poll<Result<(), Self::Error>> {
61 Poll::Ready(Ok(()))
62 }
63
call(&mut self, name: hyper_dns::Name) -> Self::Future64 fn call(&mut self, name: hyper_dns::Name) -> Self::Future {
65 let resolver = self.clone();
66 Box::pin(async move {
67 let mut lock = resolver.state.lock().await;
68
69 let resolver = match &*lock {
70 State::Init => {
71 let resolver = new_resolver().await?;
72 *lock = State::Ready(resolver.clone());
73 resolver
74 }
75 State::Ready(resolver) => resolver.clone(),
76 };
77
78 // Don't keep lock once the resolver is constructed, otherwise
79 // only one lookup could be done at a time.
80 drop(lock);
81
82 let lookup = resolver.lookup_ip(name.as_str()).await?;
83 Ok(SocketAddrs {
84 iter: lookup.into_iter(),
85 })
86 })
87 }
88 }
89
90 impl Iterator for SocketAddrs {
91 type Item = SocketAddr;
92
next(&mut self) -> Option<Self::Item>93 fn next(&mut self) -> Option<Self::Item> {
94 self.iter.next().map(|ip_addr| SocketAddr::new(ip_addr, 0))
95 }
96 }
97
new_resolver() -> Result<SharedResolver, BoxError>98 async fn new_resolver() -> Result<SharedResolver, BoxError> {
99 let (config, opts) = SYSTEM_CONF
100 .as_ref()
101 .expect("can't construct TrustDnsResolver if SYSTEM_CONF is error")
102 .clone();
103 let resolver = AsyncResolver::new(config, opts, TokioHandle)?;
104 Ok(Arc::new(resolver))
105 }
106