reth_dns_discovery/
resolver.rs
1use hickory_resolver::name_server::ConnectionProvider;
4pub use hickory_resolver::{ResolveError, TokioResolver};
5use parking_lot::RwLock;
6use std::{collections::HashMap, future::Future};
7use tracing::trace;
8
9pub trait Resolver: Send + Sync + Unpin + 'static {
11 fn lookup_txt(&self, query: &str) -> impl Future<Output = Option<String>> + Send;
13}
14
15impl<P: ConnectionProvider> Resolver for hickory_resolver::Resolver<P> {
16 async fn lookup_txt(&self, query: &str) -> Option<String> {
17 let fqn = if query.ends_with('.') { query.to_string() } else { format!("{query}.") };
20 match self.txt_lookup(fqn).await {
21 Err(err) => {
22 trace!(target: "disc::dns", %err, ?query, "dns lookup failed");
23 None
24 }
25 Ok(lookup) => {
26 let txt = lookup.into_iter().next()?;
27 let entry = txt.iter().next()?;
28 String::from_utf8(entry.to_vec()).ok()
29 }
30 }
31 }
32}
33
34#[derive(Clone, Debug)]
49pub struct DnsResolver(TokioResolver);
50
51impl DnsResolver {
54 pub const fn new(resolver: TokioResolver) -> Self {
56 Self(resolver)
57 }
58
59 pub fn from_system_conf() -> Result<Self, ResolveError> {
63 TokioResolver::builder_tokio().map(|builder| Self::new(builder.build()))
64 }
65}
66
67impl Resolver for DnsResolver {
68 async fn lookup_txt(&self, query: &str) -> Option<String> {
69 Resolver::lookup_txt(&self.0, query).await
70 }
71}
72
73#[derive(Debug, Default)]
75pub struct MapResolver(RwLock<HashMap<String, String>>);
76
77impl MapResolver {
80 pub fn insert(&self, k: String, v: String) -> Option<String> {
82 self.0.write().insert(k, v)
83 }
84
85 pub fn get(&self, k: &str) -> Option<String> {
87 self.0.read().get(k).cloned()
88 }
89
90 pub fn remove(&self, k: &str) -> Option<String> {
93 self.0.write().remove(k)
94 }
95}
96
97impl Resolver for MapResolver {
98 async fn lookup_txt(&self, query: &str) -> Option<String> {
99 self.get(query)
100 }
101}
102
103#[cfg(test)]
105pub(crate) struct TimeoutResolver(pub(crate) std::time::Duration);
106
107#[cfg(test)]
108impl Resolver for TimeoutResolver {
109 async fn lookup_txt(&self, _query: &str) -> Option<String> {
110 tokio::time::sleep(self.0).await;
111 None
112 }
113}