use super::context::Error;
use crate::base::iana::Class;
use crate::base::name::{Chain, Name, ToName};
use crate::base::{Record, RelativeName};
use crate::rdata::ZoneRecordData;
use crate::zonefile::inplace::{Entry, Zonefile};
use bytes::Bytes;
use std::fmt::Debug;
use std::io::Read;
use std::slice::Iter;
use std::sync::Arc;
use std::vec::Vec;
#[derive(Clone, Debug)]
pub(crate) struct TrustAnchor {
rrs: Vec<RrType>,
owner: Name<Bytes>,
label_count: usize,
}
type RrType = Record<
Chain<RelativeName<Bytes>, Name<Bytes>>,
ZoneRecordData<Bytes, Chain<RelativeName<Bytes>, Name<Bytes>>>,
>;
impl TrustAnchor {
fn new(rr: RrType) -> Self {
let owner = rr.owner().to_name::<Bytes>();
let label_count = owner.label_count();
Self {
rrs: vec![rr],
owner,
label_count,
}
}
fn add(&mut self, rr: &RrType) -> Result<(), ()> {
if self.rrs[0].owner().name_eq(rr.owner()) {
self.rrs.push(rr.clone());
return Ok(());
}
Err(())
}
pub fn owner(&self) -> Name<Bytes> {
self.owner.clone()
}
pub fn iter(&mut self) -> Iter<'_, RrType> {
self.rrs.iter()
}
}
pub struct TrustAnchors(Vec<TrustAnchor>);
impl TrustAnchors {
pub fn empty() -> Self {
Self(Vec::new())
}
pub fn from_reader<R>(mut reader: R) -> Result<Self, Error>
where
R: Read,
{
let mut new_self = Self(Vec::new());
let mut buf = Vec::new();
match reader.read_to_end(&mut buf) {
Ok(_) => (), Err(error) => return Err(Error::ReadError(Arc::new(error))),
}
let mut zonefile = Zonefile::new();
zonefile.extend_from_slice(&buf);
for e in zonefile {
let e = e?;
match e {
Entry::Record(r) => {
new_self.add(r);
}
Entry::Include { path: _, origin: _ } => continue, }
}
Ok(new_self)
}
pub fn from_u8(str: &[u8]) -> Result<Self, Error> {
let mut new_self = Self(Vec::new());
let mut zonefile = Zonefile::new();
zonefile.set_default_class(Class::IN);
zonefile.extend_from_slice(str);
zonefile.extend_from_slice(b"\n");
for e in zonefile {
let e = e?;
match e {
Entry::Record(r) => {
new_self.add(r);
}
Entry::Include { path: _, origin: _ } => continue, }
}
Ok(new_self)
}
pub fn add_u8(&mut self, str: &[u8]) -> Result<(), Error> {
let mut zonefile = Zonefile::new();
zonefile.set_default_class(Class::IN);
zonefile.extend_from_slice(str);
zonefile.extend_from_slice("\n".as_bytes());
for e in zonefile {
let e = e?;
match e {
Entry::Record(r) => {
self.add(r);
}
Entry::Include { path: _, origin: _ } => continue, }
}
Ok(())
}
fn add(&mut self, rr: RrType) {
if self.0.is_empty() {
self.0.push(TrustAnchor::new(rr));
return;
}
for a in &mut self.0 {
let res = a.add(&rr);
if res.is_ok() {
return;
}
}
self.0.push(TrustAnchor::new(rr));
}
pub(crate) fn find<TDN: Debug + ToName>(
&self,
name: TDN,
) -> Option<&TrustAnchor> {
self.0
.iter()
.filter(|ta| name.ends_with(ta.rrs[0].owner()))
.max_by_key(|ta| ta.label_count)
}
}