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