aws_smithy_dns/
hickory.rs1use std::{io::Error as IoError, net::IpAddr, time::Duration};
7
8use aws_smithy_runtime_api::client::dns::{DnsFuture, ResolveDns, ResolveDnsError};
9use hickory_resolver::{
10 config::{NameServerConfigGroup, ResolverConfig},
11 name_server::TokioConnectionProvider,
12 Resolver,
13};
14
15#[non_exhaustive]
19#[derive(Debug, Clone)]
20pub struct HickoryDnsResolver {
21 resolver: Resolver<TokioConnectionProvider>,
22}
23
24impl Default for HickoryDnsResolver {
25 fn default() -> Self {
28 Self {
29 resolver: Resolver::builder_tokio().expect("In tokio runtime").build(),
30 }
31 }
32}
33
34impl HickoryDnsResolver {
35 pub fn builder() -> HickoryDnsResolverBuilder {
37 HickoryDnsResolverBuilder {
38 nameservers: None,
39 timeout: None,
40 attempts: None,
41 cache_size: None,
42 num_concurrent_reqs: None,
43 }
44 }
45
46 pub fn clear_cache(&self) {
48 self.resolver.clear_cache();
49 }
50}
51
52impl ResolveDns for HickoryDnsResolver {
53 fn resolve_dns<'a>(&'a self, name: &'a str) -> DnsFuture<'a> {
54 DnsFuture::new(async move {
55 let result = self.resolver.lookup_ip(name).await;
56
57 match result {
58 Ok(ips) => Ok(ips.into_iter().collect()),
59 Err(failure) => Err(ResolveDnsError::new(IoError::other(failure))),
60 }
61 })
62 }
63}
64
65pub struct HickoryDnsResolverBuilder {
67 nameservers: Option<Nameservers>,
68 timeout: Option<Duration>,
69 attempts: Option<usize>,
70 cache_size: Option<usize>,
71 num_concurrent_reqs: Option<usize>,
72}
73
74struct Nameservers {
75 ips: Vec<IpAddr>,
76 port: u16,
77}
78
79impl HickoryDnsResolverBuilder {
80 pub fn nameservers(mut self, ips: &[IpAddr], port: u16) -> Self {
83 self.nameservers = Some(Nameservers {
84 ips: ips.to_vec(),
85 port,
86 });
87 self
88 }
89
90 pub fn timeout(mut self, timeout: Duration) -> Self {
92 self.timeout = Some(timeout);
93 self
94 }
95
96 pub fn attempts(mut self, attempts: usize) -> Self {
98 self.attempts = Some(attempts);
99 self
100 }
101
102 pub fn cache_size(mut self, cache_size: usize) -> Self {
104 self.cache_size = Some(cache_size);
105 self
106 }
107
108 pub fn num_concurrent_reqs(mut self, num_concurrent_reqs: usize) -> Self {
114 self.num_concurrent_reqs = Some(num_concurrent_reqs);
115 self
116 }
117
118 pub fn build(self) -> HickoryDnsResolver {
120 let mut builder = if let Some(nameservers) = self.nameservers {
121 let nameserver_config =
122 NameServerConfigGroup::from_ips_clear(&nameservers.ips, nameservers.port, true);
123 let resolver_config = ResolverConfig::from_parts(None, vec![], nameserver_config);
124
125 Resolver::builder_with_config(resolver_config, TokioConnectionProvider::default())
126 } else {
127 Resolver::builder_tokio().expect("Successfully read system config")
128 };
129
130 let opts = builder.options_mut();
131
132 if let Some(timeout) = self.timeout {
133 opts.timeout = timeout;
134 }
135
136 if let Some(attempts) = self.attempts {
137 opts.attempts = attempts;
138 }
139
140 if let Some(cache_size) = self.cache_size {
141 opts.cache_size = cache_size;
142 }
143
144 if let Some(num_concurrent_reqs) = self.num_concurrent_reqs {
145 opts.num_concurrent_reqs = num_concurrent_reqs;
146 }
147
148 HickoryDnsResolver {
149 resolver: builder.build(),
150 }
151 }
152}