polyresolver 0.1.1

DNS resolver for client-side split horizon resolution over multiple domain arenas
Documentation
use crate::resolver::Resolver;
use async_trait::async_trait;
use trust_dns_resolver::{
    lookup,
    proto::rr::{Record, RecordType},
};
use trust_dns_server::{
    authority::{Authority, LookupError, LookupObject},
    client::rr::LowerName,
};

#[derive(Clone)]
pub struct Forwarder {
    pub resolver: Resolver,
    pub domain_name: LowerName,
}

#[async_trait]
impl Authority for Forwarder {
    type Lookup = ForwardLookup;

    fn zone_type(&self) -> trust_dns_server::authority::ZoneType {
        trust_dns_server::authority::ZoneType::Forward
    }

    fn is_axfr_allowed(&self) -> bool {
        false
    }

    async fn update(
        &self,
        _update: &trust_dns_server::authority::MessageRequest,
    ) -> trust_dns_server::authority::UpdateResult<bool> {
        Ok(false)
    }

    fn origin(&self) -> &trust_dns_server::client::rr::LowerName {
        &self.domain_name
    }

    async fn lookup(
        &self,
        name: &trust_dns_server::client::rr::LowerName,
        rtype: RecordType,
        _lookup_options: trust_dns_server::authority::LookupOptions,
    ) -> Result<Self::Lookup, LookupError> {
        let lookup = self.resolver.lookup(name, rtype).await;

        lookup.map(ForwardLookup).map_err(LookupError::from)
    }

    async fn search(
        &self,
        request_info: trust_dns_server::server::RequestInfo<'_>,
        lookup_options: trust_dns_server::authority::LookupOptions,
    ) -> Result<Self::Lookup, LookupError> {
        self.lookup(
            request_info.query.name(),
            request_info.query.query_type(),
            lookup_options,
        )
        .await
    }

    async fn get_nsec_records(
        &self,
        _name: &trust_dns_server::client::rr::LowerName,
        _lookup_options: trust_dns_server::authority::LookupOptions,
    ) -> Result<Self::Lookup, LookupError> {
        Err(LookupError::from(std::io::Error::new(
            std::io::ErrorKind::Other,
            "this kind of lookup is not supported",
        )))
    }
}

pub struct ForwardLookup(lookup::Lookup);

impl LookupObject for ForwardLookup {
    fn is_empty(&self) -> bool {
        self.0.is_empty()
    }

    fn iter<'a>(&'a self) -> Box<dyn Iterator<Item = &'a Record> + Send + 'a> {
        Box::new(self.0.record_iter())
    }

    fn take_additionals(&mut self) -> Option<Box<dyn LookupObject>> {
        None
    }
}