use crate::message::header::{Header, HeaderInternal, Section};
use crate::message::name::Name;
use crate::message::question::Question;
use crate::message::resource::{Resource, ResourceBody, ResourceHeader, unpack_resource_body};
use crate::message::{DnsClass, DnsType};
use shared::error::*;
#[derive(Default)]
pub(crate) struct Parser<'a> {
pub(crate) msg: &'a [u8],
pub(crate) header: HeaderInternal,
pub(crate) section: Section,
pub(crate) off: usize,
pub(crate) index: usize,
pub(crate) res_header_valid: bool,
pub(crate) res_header: ResourceHeader,
}
impl<'a> Parser<'a> {
pub(crate) fn start(&mut self, msg: &'a [u8]) -> Result<Header> {
*self = Parser {
msg,
..Default::default()
};
self.off = self.header.unpack(msg, 0)?;
self.section = Section::Questions;
Ok(self.header.header())
}
fn check_advance(&mut self, sec: Section) -> Result<()> {
if self.section < sec {
return Err(Error::ErrNotStarted);
}
if self.section > sec {
return Err(Error::ErrSectionDone);
}
self.res_header_valid = false;
if self.index == self.header.count(sec) as usize {
self.index = 0;
self.section = Section::from(1 + self.section as u8);
return Err(Error::ErrSectionDone);
}
Ok(())
}
fn resource(&mut self, sec: Section) -> Result<Resource> {
let header = self.resource_header(sec)?;
self.res_header_valid = false;
let (body, off) =
unpack_resource_body(header.typ, self.msg, self.off, header.length as usize)?;
self.off = off;
self.index += 1;
Ok(Resource {
header,
body: Some(body),
})
}
fn resource_header(&mut self, sec: Section) -> Result<ResourceHeader> {
if self.res_header_valid {
return Ok(self.res_header.clone());
}
self.check_advance(sec)?;
let mut hdr = ResourceHeader::default();
let off = hdr.unpack(self.msg, self.off, 0)?;
self.res_header_valid = true;
self.res_header = hdr.clone();
self.off = off;
Ok(hdr)
}
fn skip_resource(&mut self, sec: Section) -> Result<()> {
if self.res_header_valid {
let new_off = self.off + self.res_header.length as usize;
if new_off > self.msg.len() {
return Err(Error::ErrResourceLen);
}
self.off = new_off;
self.res_header_valid = false;
self.index += 1;
return Ok(());
}
self.check_advance(sec)?;
self.off = Resource::skip(self.msg, self.off)?;
self.index += 1;
Ok(())
}
pub(crate) fn question(&mut self) -> Result<Question> {
self.check_advance(Section::Questions)?;
let mut name = Name::new("")?;
let mut off = name.unpack(self.msg, self.off)?;
let mut typ = DnsType::Unsupported;
off = typ.unpack(self.msg, off)?;
let mut class = DnsClass::default();
off = class.unpack(self.msg, off)?;
self.off = off;
self.index += 1;
Ok(Question { name, typ, class })
}
pub(crate) fn all_questions(&mut self) -> Result<Vec<Question>> {
let mut qs = vec![];
loop {
match self.question() {
Err(err) => {
if Error::ErrSectionDone == err {
return Ok(qs);
} else {
return Err(err);
}
}
Ok(q) => qs.push(q),
}
}
}
pub(crate) fn skip_question(&mut self) -> Result<()> {
self.check_advance(Section::Questions)?;
let mut off = Name::skip(self.msg, self.off)?;
off = DnsType::skip(self.msg, off)?;
off = DnsClass::skip(self.msg, off)?;
self.off = off;
self.index += 1;
Ok(())
}
pub(crate) fn skip_all_questions(&mut self) -> Result<()> {
loop {
if let Err(err) = self.skip_question() {
if Error::ErrSectionDone == err {
return Ok(());
} else {
return Err(err);
}
}
}
}
pub(crate) fn answer_header(&mut self) -> Result<ResourceHeader> {
self.resource_header(Section::Answers)
}
pub(crate) fn answer(&mut self) -> Result<Resource> {
self.resource(Section::Answers)
}
pub(crate) fn all_answers(&mut self) -> Result<Vec<Resource>> {
let mut n = self.header.answers as usize;
if n > 20 {
n = 20
}
let mut a = Vec::with_capacity(n);
loop {
match self.answer() {
Err(err) => {
if Error::ErrSectionDone == err {
return Ok(a);
} else {
return Err(err);
}
}
Ok(r) => a.push(r),
}
}
}
pub(crate) fn skip_answer(&mut self) -> Result<()> {
self.skip_resource(Section::Answers)
}
pub(crate) fn skip_all_answers(&mut self) -> Result<()> {
loop {
if let Err(err) = self.skip_answer() {
if Error::ErrSectionDone == err {
return Ok(());
} else {
return Err(err);
}
}
}
}
pub(crate) fn authority_header(&mut self) -> Result<ResourceHeader> {
self.resource_header(Section::Authorities)
}
pub(crate) fn authority(&mut self) -> Result<Resource> {
self.resource(Section::Authorities)
}
pub(crate) fn all_authorities(&mut self) -> Result<Vec<Resource>> {
let mut n = self.header.authorities as usize;
if n > 10 {
n = 10;
}
let mut a = Vec::with_capacity(n);
loop {
match self.authority() {
Err(err) => {
if Error::ErrSectionDone == err {
return Ok(a);
} else {
return Err(err);
}
}
Ok(r) => a.push(r),
}
}
}
pub(crate) fn skip_authority(&mut self) -> Result<()> {
self.skip_resource(Section::Authorities)
}
pub(crate) fn skip_all_authorities(&mut self) -> Result<()> {
loop {
if let Err(err) = self.skip_authority() {
if Error::ErrSectionDone == err {
return Ok(());
} else {
return Err(err);
}
}
}
}
pub(crate) fn additional_header(&mut self) -> Result<ResourceHeader> {
self.resource_header(Section::Additionals)
}
pub(crate) fn additional(&mut self) -> Result<Resource> {
self.resource(Section::Additionals)
}
pub(crate) fn all_additionals(&mut self) -> Result<Vec<Resource>> {
let mut n = self.header.additionals as usize;
if n > 10 {
n = 10;
}
let mut a = Vec::with_capacity(n);
loop {
match self.additional() {
Err(err) => {
if Error::ErrSectionDone == err {
return Ok(a);
} else {
return Err(err);
}
}
Ok(r) => a.push(r),
}
}
}
pub(crate) fn skip_additional(&mut self) -> Result<()> {
self.skip_resource(Section::Additionals)
}
pub(crate) fn skip_all_additionals(&mut self) -> Result<()> {
loop {
if let Err(err) = self.skip_additional() {
if Error::ErrSectionDone == err {
return Ok(());
} else {
return Err(err);
}
}
}
}
pub(crate) fn resource_body(&mut self) -> Result<Box<dyn ResourceBody>> {
if !self.res_header_valid {
return Err(Error::ErrNotStarted);
}
let (rb, _off) = unpack_resource_body(
self.res_header.typ,
self.msg,
self.off,
self.res_header.length as usize,
)?;
self.off += self.res_header.length as usize;
self.res_header_valid = false;
self.index += 1;
Ok(rb)
}
}