Skip to main content

Module cache

Module cache 

Source
Expand description

DNS cache traits and the per-call Parameters wrapper.

The crate does not ship a cache implementation. Applications supply one by implementing ResolverCache for their cache type and DnsCache for a type that groups one cache per record type. The cache is then passed to a verifier through Parameters::with_cache. Keys are fully qualified, lowercased domain names (see ToFqdn), or IP addresses for PTR records.

§Example

use mail_auth::{
    AuthenticatedMessage, DnsCache, MessageAuthenticator, Mx, Negative, Parameters, RecordSet,
    ResolverCache, TxtRecord,
};
use std::{
    borrow::Borrow,
    collections::HashMap,
    hash::Hash,
    net::{IpAddr, Ipv4Addr, Ipv6Addr},
    sync::Mutex,
    time::Instant,
};

struct MapCache<K, V>(Mutex<HashMap<K, (V, Instant)>>);

impl<K: Hash + Eq, V: Clone> ResolverCache<K, V> for MapCache<K, V> {
    fn get<Q>(&self, name: &Q) -> Option<V>
    where
        K: Borrow<Q>,
        Q: Hash + Eq + ?Sized,
    {
        let map = self.0.lock().unwrap();
        let (value, expires) = map.get(name)?;
        (*expires > Instant::now()).then(|| value.clone())
    }

    fn remove<Q>(&self, name: &Q) -> Option<V>
    where
        K: Borrow<Q>,
        Q: Hash + Eq + ?Sized,
    {
        self.0.lock().unwrap().remove(name).map(|(value, _)| value)
    }

    fn insert(&self, key: K, value: V, valid_until: Instant) {
        self.0.lock().unwrap().insert(key, (value, valid_until));
    }
}

type Answer<T> = Result<RecordSet<T>, Negative>;

struct Caches {
    txt: MapCache<Box<str>, TxtRecord>,
    mx: MapCache<Box<str>, Answer<Mx>>,
    ipv4: MapCache<Box<str>, Answer<Ipv4Addr>>,
    ipv6: MapCache<Box<str>, Answer<Ipv6Addr>>,
    ptr: MapCache<IpAddr, Answer<Box<str>>>,
}

impl DnsCache for Caches {
    type Txt = MapCache<Box<str>, TxtRecord>;
    type Mx = MapCache<Box<str>, Answer<Mx>>;
    type Ipv4 = MapCache<Box<str>, Answer<Ipv4Addr>>;
    type Ipv6 = MapCache<Box<str>, Answer<Ipv6Addr>>;
    type Ptr = MapCache<IpAddr, Answer<Box<str>>>;

    fn txt(&self) -> Option<&Self::Txt> { Some(&self.txt) }
    fn mx(&self) -> Option<&Self::Mx> { Some(&self.mx) }
    fn ipv4(&self) -> Option<&Self::Ipv4> { Some(&self.ipv4) }
    fn ipv6(&self) -> Option<&Self::Ipv6> { Some(&self.ipv6) }
    fn ptr(&self) -> Option<&Self::Ptr> { Some(&self.ptr) }
}

let message = AuthenticatedMessage::parse(raw).unwrap();
let results = authenticator
    .verify_dkim(Parameters::new(&message).with_cache(caches))
    .await;

Structs§

NoCache
A cache that stores nothing.
Parameters
The input of a verifier, optionally paired with a DNS cache.

Traits§

DnsCache
A set of DNS caches, one per record type, passed to verifiers through Parameters::with_cache.
ResolverCache
A cache for one DNS record type, keyed by K and holding values of type V.