use moka::future::Cache; use std::net::SocketAddr; use std::sync::Arc; use std::time::Duration; use tokio::task::JoinHandle; use tracing::{error, info}; use crate::config::Config; use crate::packet::question::DnsQuestion; use crate::packet::{Result, Packet}; use super::binding::Binding; use super::resolver::Resolver; pub struct Server { addr: SocketAddr, config: Arc, cache: Cache, } impl Server { pub async fn new(config: Config) -> Result { let addr = format!("[::]:{}", config.get_port()).parse::()?; let cache = Cache::builder() .time_to_live(Duration::from_secs(60 * 60)) .max_capacity(1_000) .build(); Ok(Self { addr, config: Arc::new(config), cache, }) } pub async fn run(&self) -> Result<()> { let tcp = Binding::tcp(self.addr).await?; let tcp_handle = self.listen(tcp); let udp = Binding::udp(self.addr).await?; let udp_handle = self.listen(udp); info!("Fallback DNS Server is set to: {:?}", self.config.get_fallback_ns()); info!("Listening for TCP and UDP traffic on [::]:{}", self.config.get_port()); tokio::join!(tcp_handle) .0 .expect("Failed to join tcp thread"); tokio::join!(udp_handle) .0 .expect("Failed to join udp thread"); Ok(()) } fn listen(&self, mut binding: Binding) -> JoinHandle<()> { let config = self.config.clone(); let cache = self.cache.clone(); tokio::spawn(async move { let mut id = 0; loop { let Ok(connection) = binding.connect().await else { continue }; info!("Received request on {}", binding.name()); let resolver = Resolver::new(id, connection, config.clone(), cache.clone()); if let Err(err) = resolver.handle_query().await { error!("{} request {} failed: {:?}", binding.name(), id, err); }; id += 1; } }) } }