use std::net::{IpAddr, Ipv4Addr};
use std::time::{Duration, Instant};
use hickory_resolver::config::{ResolverConfig, ResolverOpts};
use hickory_resolver::{TokioAsyncResolver, system_conf};
const LOOKUP_TIMEOUT: Duration = Duration::from_secs(2);
pub fn build() -> TokioAsyncResolver {
let (config, mut opts) = system_conf::read_system_conf()
.unwrap_or_else(|_| (ResolverConfig::cloudflare(), ResolverOpts::default()));
opts.timeout = LOOKUP_TIMEOUT;
opts.attempts = 1; opts.cache_size = 0; TokioAsyncResolver::tokio(config, opts)
}
pub fn configured_servers() -> Vec<IpAddr> {
let Ok((config, _)) = system_conf::read_system_conf() else {
return Vec::new();
};
let mut seen = Vec::new();
for ns in config.name_servers() {
let ip = ns.socket_addr.ip();
if !seen.contains(&ip) {
seen.push(ip);
}
}
seen
}
pub async fn resolve_timed(
resolver: &TokioAsyncResolver,
host: String,
) -> (String, Option<Ipv4Addr>, u128) {
let start = Instant::now();
let ip = match resolver.ipv4_lookup(format!("{host}.")).await {
Ok(lookup) => lookup.iter().next().map(|a| a.0),
Err(_) => None,
};
(host, ip, start.elapsed().as_millis())
}