From df3e35c54b7ede8f256eb124939d0784d561d2bb Mon Sep 17 00:00:00 2001 From: Martin Hoffmann Date: Tue, 12 Apr 2016 15:38:11 +0200 Subject: [PATCH] Messages are always of lazy flavor. --- src/bits/flavor.rs | 10 -- src/bits/message.rs | 224 +++++++++++++++++++++++++++++++------------- src/bits/record.rs | 6 +- 3 files changed, 162 insertions(+), 78 deletions(-) diff --git a/src/bits/flavor.rs b/src/bits/flavor.rs index e39f53e8..7aafb045 100644 --- a/src/bits/flavor.rs +++ b/src/bits/flavor.rs @@ -32,8 +32,6 @@ pub trait Flavor: Sized { pub trait FlatFlavor<'a>: Flavor { type FlatNest: nest::FlatNest<'a, Self>; type Parser: parse::ParseFlavor<'a, Self> + Clone; - - fn parser_for_message(bytes: &'a [u8]) -> Self::Parser; } /// The flavor for owned DNS data. @@ -61,10 +59,6 @@ impl<'a> Flavor for Ref<'a> { impl<'a> FlatFlavor<'a> for Ref<'a> { type FlatNest = nest::NestRef<'a>; type Parser = parse::SliceParser<'a>; - - fn parser_for_message(bytes: &'a [u8]) -> Self::Parser { - parse::SliceParser::new(bytes) - } } @@ -83,8 +77,4 @@ impl<'a> Flavor for Lazy<'a> { impl<'a> FlatFlavor<'a> for Lazy<'a> { type FlatNest = nest::LazyNest<'a>; type Parser = parse::ContextParser<'a>; - - fn parser_for_message(bytes: &'a [u8]) -> Self::Parser { - parse::ContextParser::new(bytes, bytes) - } } diff --git a/src/bits/message.rs b/src/bits/message.rs index b7354b3a..3ed6e001 100644 --- a/src/bits/message.rs +++ b/src/bits/message.rs @@ -1,60 +1,147 @@ //! DNS messages. +use std::borrow::Borrow; use std::marker::PhantomData; use std::mem; +use std::ops::Deref; use super::compose::ComposeBytes; -use super::error::{ComposeError, ComposeResult, ParseResult}; -use super::flavor::{self, FlatFlavor}; +use super::error::{ComposeError, ComposeResult, ParseError, ParseResult}; +use super::flavor; use super::header::{Header, HeaderCounts, FullHeader}; -use super::parse::ParseBytes; -use super::question::{ComposeQuestion, Question}; +use super::parse::{ContextParser, ParseBytes}; +use super::question::{ComposeQuestion, LazyQuestion}; use super::rdata::{GenericRecordData, FlatRecordData}; -use super::record::{ComposeRecord, Record}; +use super::record::{ComposeRecord, LazyRecord}; //============ Disecting Existing Messages ================================== //------------ Message ------------------------------------------------------ -/// A DNS message. -#[derive(Clone, Debug)] -pub struct Message<'a, F: FlatFlavor<'a>> { - bytes: &'a [u8], - marker: PhantomData, +/// A bytes slice containing a DNS message. +/// +/// Everything parsed out of a message will be of the lazy flavor. +/// +/// This is an unsized type. +#[derive(Debug)] +pub struct Message { + slice: [u8] } -pub type MessageRef<'a> = Message<'a, flavor::Ref<'a>>; -pub type LazyMessage<'a> = Message<'a, flavor::Lazy<'a>>; - - /// # Creation and Conversion /// -impl<'a, F: FlatFlavor<'a>> Message<'a, F> { +impl Message { /// Creates a message from a bytes slice. - pub fn from_bytes(bytes: &'a [u8]) -> Self { - Message { bytes: bytes, marker: PhantomData } + pub fn from_bytes(slice: &[u8]) -> ParseResult<&Self> { + if slice.len() < mem::size_of::() { + Err(ParseError::UnexpectedEnd) + } + else { + Ok(unsafe { Message::from_bytes_unsafe(slice) }) + } + } + + unsafe fn from_bytes_unsafe(slice: &[u8]) -> &Self { + mem::transmute(slice) + } + + /// Returns an owned copy of this message. + pub fn to_owned(&self) -> MessageBuf { + unsafe { MessageBuf::from_bytes_unsafe(&self.slice) } + } + + /// Returns the underlying bytes slice. + pub fn as_bytes(&self) -> &[u8] { + &self.slice } } /// # Header Access /// -impl<'a, F: FlatFlavor<'a>> Message<'a, F> { +impl Message { /// Returns a reference to the message header. - pub fn header<'b: 'a>(&'b self) -> &'a Header { - unsafe { Header::from_message(self.bytes) } + pub fn header(&self) -> &Header { + unsafe { Header::from_message(&self.slice) } } /// Returns a reference to the header counts of the message. - pub fn counts<'b: 'a>(&'b self) -> &'a HeaderCounts { - unsafe { HeaderCounts::from_message(self.bytes) } + pub fn counts(&self) -> &HeaderCounts { + unsafe { HeaderCounts::from_message(&self.slice) } } /// Returns an iterator over the question section - pub fn question<'b: 'a>(&'b self) -> QuestionSection<'a, F> { - let mut parser = F::parser_for_message(self.bytes); - parser.skip(mem::size_of::()).unwrap(); // XXX Hmm. - QuestionSection::new(parser, (*self.counts()).clone()) + pub fn question(&self) -> QuestionSection { + let mut parser = ContextParser::new(&self.slice, &self.slice); + parser.skip(mem::size_of::()).unwrap(); + QuestionSection::new(parser, self.counts()) + } +} + + +//--- AsRef + +impl AsRef for Message { + fn as_ref(&self) -> &Message { self } +} + + +//--- ToOwned + +impl ToOwned for Message { + type Owned = MessageBuf; + + fn to_owned(&self) -> Self::Owned { self.to_owned() } +} + + +//------------ MessageBuf --------------------------------------------------- + +/// An owned DNS message. +#[derive(Clone, Debug)] +pub struct MessageBuf { + inner: Vec +} + + +/// # Creation and Conversion +/// +impl MessageBuf { + /// Creates a new owned message from a bytes slice. + pub fn from_bytes(slice: &[u8]) -> ParseResult { + let msg = try!(Message::from_bytes(slice)); + Ok(MessageBuf { inner: Vec::from(&msg.slice) }) + } + + unsafe fn from_bytes_unsafe(slice: &[u8]) -> Self { + MessageBuf { inner: Vec::from(slice) } + } + + pub fn as_slice(&self) -> &Message { + self + } +} + + +//--- Deref, Borrow, and AsRef + +impl Deref for MessageBuf { + type Target = Message; + + fn deref(&self) -> &Message { + unsafe { Message::from_bytes_unsafe(&self.inner) } + } +} + +impl Borrow for MessageBuf { + fn borrow(&self) -> &Message { + self.deref() + } +} + +impl AsRef for MessageBuf { + fn as_ref(&self) -> &Message { + self } } @@ -62,14 +149,14 @@ impl<'a, F: FlatFlavor<'a>> Message<'a, F> { //------------ QuestionSection ---------------------------------------------- #[derive(Clone, Debug)] -pub struct QuestionSection<'a, F: FlatFlavor<'a>> { - parser: F::Parser, - counts: HeaderCounts, +pub struct QuestionSection<'a> { + parser: ContextParser<'a>, + counts: &'a HeaderCounts, count: u16 } -impl<'a, F: FlatFlavor<'a>> QuestionSection<'a, F> { - fn new(parser: F::Parser, counts: HeaderCounts) -> Self { +impl<'a> QuestionSection<'a> { + fn new(parser: ContextParser<'a>, counts: &'a HeaderCounts) -> Self { let count = counts.qdcount(); QuestionSection { parser: parser, counts: counts, count: count } } @@ -79,7 +166,7 @@ impl<'a, F: FlatFlavor<'a>> QuestionSection<'a, F> { } /// Continues to the answer section. - pub fn answer(mut self) -> ParseResult> { + pub fn answer(mut self) -> ParseResult> { for question in self.iter() { if let Err(e) = question { return Err(e) @@ -89,12 +176,12 @@ impl<'a, F: FlatFlavor<'a>> QuestionSection<'a, F> { } } -impl<'a, F: FlatFlavor<'a>> Iterator for QuestionSection<'a, F> { - type Item = ParseResult>; +impl<'a> Iterator for QuestionSection<'a> { + type Item = ParseResult>; fn next(&mut self) -> Option { if self.count == 0 { return None } - Some(Question::parse(&mut self.parser) + Some(LazyQuestion::parse(&mut self.parser) .map(|res| { self.count -= 1; res })) } } @@ -104,22 +191,23 @@ impl<'a, F: FlatFlavor<'a>> Iterator for QuestionSection<'a, F> { /// The answer section of a message. #[derive(Clone, Debug)] -pub struct AnswerSection<'a, F: FlatFlavor<'a>> { - parser: F::Parser, - counts: HeaderCounts, +pub struct AnswerSection<'a> { + parser: ContextParser<'a>, + counts: &'a HeaderCounts, } -impl<'a, F: FlatFlavor<'a>> AnswerSection<'a, F> { - fn new(parser: F::Parser, counts: HeaderCounts) -> Self { +impl<'a> AnswerSection<'a> { + fn new(parser: ContextParser<'a>, counts: &'a HeaderCounts) -> Self { AnswerSection { parser: parser, counts: counts } } - pub fn iter>(&self) -> RecordIter<'a, F, D> { + pub fn iter(&self) -> RecordIter<'a, D> + where D: FlatRecordData<'a, flavor::Lazy<'a>> { RecordIter::new(self.parser.clone(), self.counts.ancount()) } - pub fn authority(self) -> ParseResult> { - let mut iter = self.iter::>(); + pub fn authority(self) -> ParseResult> { + let mut iter = self.iter::>>(); try!(iter.exhaust()); Ok(AuthoritySection::new(iter.parser, self.counts)) } @@ -130,22 +218,23 @@ impl<'a, F: FlatFlavor<'a>> AnswerSection<'a, F> { /// The authority section of a message. #[derive(Clone, Debug)] -pub struct AuthoritySection<'a, F: FlatFlavor<'a>> { - parser: F::Parser, - counts: HeaderCounts, +pub struct AuthoritySection<'a> { + parser: ContextParser<'a>, + counts: &'a HeaderCounts, } -impl<'a, F: FlatFlavor<'a>> AuthoritySection<'a, F> { - fn new(parser: F::Parser, counts: HeaderCounts) -> Self { +impl<'a> AuthoritySection<'a> { + fn new(parser: ContextParser<'a>, counts: &'a HeaderCounts) -> Self { AuthoritySection { parser: parser, counts: counts } } - pub fn iter>(&self) -> RecordIter<'a, F, D> { - RecordIter::new(self.parser.clone(), self.counts.nscount()) + pub fn iter(&self) -> RecordIter<'a, D> + where D: FlatRecordData<'a, flavor::Lazy<'a>> { + RecordIter::new(self.parser.clone(), self.counts.ancount()) } - pub fn additional(self) -> ParseResult> { - let mut iter = self.iter::>(); + pub fn additional(self) -> ParseResult> { + let mut iter = self.iter::>>(); try!(iter.exhaust()); Ok(AdditionalSection::new(iter.parser, self.counts)) } @@ -156,17 +245,18 @@ impl<'a, F: FlatFlavor<'a>> AuthoritySection<'a, F> { /// The additional section of a message. #[derive(Clone, Debug)] -pub struct AdditionalSection<'a, F: FlatFlavor<'a>> { - parser: F::Parser, - counts: HeaderCounts, +pub struct AdditionalSection<'a> { + parser: ContextParser<'a>, + counts: &'a HeaderCounts, } -impl<'a, F: FlatFlavor<'a>> AdditionalSection<'a, F> { - fn new(parser: F::Parser, counts: HeaderCounts) -> Self { +impl<'a> AdditionalSection<'a> { + fn new(parser: ContextParser<'a>, counts: &'a HeaderCounts) -> Self { AdditionalSection { parser: parser, counts: counts } } - pub fn iter>(&self) -> RecordIter<'a, F, D> { + pub fn iter(&self) -> RecordIter<'a, D> + where D: FlatRecordData<'a, flavor::Lazy<'a>> { RecordIter::new(self.parser.clone(), self.counts.ancount()) } } @@ -176,14 +266,14 @@ impl<'a, F: FlatFlavor<'a>> AdditionalSection<'a, F> { /// An iterator over the records in one of a record section. #[derive(Clone, Debug)] -pub struct RecordIter<'a, F: FlatFlavor<'a>, D: FlatRecordData<'a, F>> { - parser: F::Parser, +pub struct RecordIter<'a, D: FlatRecordData<'a, flavor::Lazy<'a>>> { + parser: ContextParser<'a>, count: u16, marker: PhantomData } -impl<'a, F: FlatFlavor<'a>, D: FlatRecordData<'a, F>> RecordIter<'a, F, D> { - fn new(parser: F::Parser, count: u16) -> Self { +impl<'a, D: FlatRecordData<'a, flavor::Lazy<'a>>> RecordIter<'a, D> { + fn new(parser: ContextParser<'a>, count: u16) -> Self { RecordIter { parser: parser, count: count, marker: PhantomData } } @@ -198,14 +288,14 @@ impl<'a, F: FlatFlavor<'a>, D: FlatRecordData<'a, F>> RecordIter<'a, F, D> { Ok(()) } - fn step(&mut self) -> ParseResult>> { - Record::parse(&mut self.parser).map(|res| { self.count -= 1; res }) + fn step(&mut self) -> ParseResult>> { + LazyRecord::parse(&mut self.parser).map(|res| { self.count -= 1; res }) } } -impl<'a, F, D> Iterator for RecordIter<'a, F, D> - where F: FlatFlavor<'a>, D: FlatRecordData<'a, F> { - type Item = ParseResult>; +impl<'a, D> Iterator for RecordIter<'a, D> + where D: FlatRecordData<'a, flavor::Lazy<'a>> { + type Item = ParseResult>; fn next(&mut self) -> Option { if self.count == 0 { return None } diff --git a/src/bits/record.rs b/src/bits/record.rs index 3245ee3f..bf697685 100644 --- a/src/bits/record.rs +++ b/src/bits/record.rs @@ -3,7 +3,7 @@ use std::fmt; use super::compose::ComposeBytes; use super::error::{ComposeError, ComposeResult, ParseResult}; -use super::flavor::{FlatFlavor, Flavor}; +use super::flavor::{self, FlatFlavor, Flavor}; use super::iana::{Class, RRType}; use super::parse::ParseFlavor; use super::rdata::{FlatRecordData, RecordData}; @@ -18,6 +18,10 @@ pub struct Record> { rdata: D } +pub type OwnedRecord = Record; +pub type RecordRef<'a, D> = Record, D>; +pub type LazyRecord<'a, D> = Record, D>; + /// # Creation and Conversion ///