domain_core/bits/message.rs
1//! Accessing exisiting DNS messages.
2//!
3//! This module defines a number of types for disecting the content of a
4//! DNS message in wire format. Because many of the components of the message
5//! are of varying length, this can only be done iteratively. You start out
6//! with a value of type [`Message`] that wraps the data of a complete
7//! message and progressively trade it in for values of other types
8//! representing other sections of the message.
9//!
10//! For all details, see the [`Message`] type.
11//!
12//! [`Message`]: struct.Message.html
13
14
15use std::{mem, ops};
16use std::marker::PhantomData;
17use bytes::Bytes;
18use ::iana::{Rcode, Rtype};
19use ::rdata::Cname;
20use super::message_builder::{MessageBuilder, AdditionalBuilder, RecordSectionBuilder};
21use super::header::{Header, HeaderCounts, HeaderSection};
22use super::name::{ParsedDname, ParsedDnameError, ToDname};
23use super::parse::{Parse, Parser, ShortBuf};
24use super::question::Question;
25use super::rdata::{ParseRecordData, RecordData};
26use super::record::{ParsedRecord, Record, RecordParseError};
27
28
29//------------ Message -------------------------------------------------------
30
31/// A DNS message.
32///
33/// This type wraps a bytes value with the wire-format content of a DNS
34/// message and allows parsing the content for further processing.
35///
36/// Typically, you create a message by passing a bytes value with data you
37/// received from the network to the [`from_bytes`] function. This function
38/// does a quick sanity check if the data can be a DNS message at all
39/// before returning a message value. All further parsing happens lazily when
40/// you access more of the message.
41///
42/// Section 4 of [RFC 1035] defines DNS messages as being divded into five
43/// sections named header, question, answer, authority, and additional.
44///
45/// The header section is of a fixed sized and can be accessed at any time
46/// through the methods given under [Header Section]. Most likely, you will
47/// be interested in the first part of the header for which references
48/// are returned by the [`header`] method. The second part of the header
49/// section contains the number of entries in the following four sections
50/// and is of less interest as there are more sophisticated ways of accessing
51/// these sections. If you do care, you can get a reference through
52/// [`counts`].
53///
54/// The question section contains what was asked of the DNS by a request.
55/// These questions consist of a domain name, a record type, and class. With
56/// normal queries, a requests asks for all records of the given record type
57/// that are owned by the domain name within the class. There will normally
58/// be exactly one question for normal queries. With other query operations,
59/// the questions may refer to different things.
60///
61/// You can get access to the question section through the [`question`]
62/// method. It returns a [`QuestionSection`] value that is an iterator over
63/// questions. Since a single question is a very common case, there is a
64/// convenience method [`first_question`] that simple returns the first
65/// question if there is any.
66///
67/// The following three section all contain DNS resource records. In normal
68/// queries, they are empty in a request and may or may not contain records
69/// in a response. The *answer* section contains all the records that answer
70/// the given question. The *authority* section contains records declaring
71/// which name server provided authoritative information for the question,
72/// and the *additional* section can contain records that the name server
73/// thought might be useful for processing the question. For instance, if you
74/// trying to find out the mail server of a domain by asking for MX records,
75/// you likely also want the IP addresses for the server, so the name server
76/// may include these right away and free of charge.
77///
78/// There are functions to access all three sections directly: [`answer`],
79/// [`authority`], and [`additional`]. However, since there are no
80/// pointers to where the later sections start, accessing them directly
81/// means iterating over the previous sections. This is why it is more
82/// efficitent to call [`next_section`] on the returned value and process
83/// them in order. Alternatively, you can use the [`sections`] function
84/// that gives you all four sections at once with the minimal amount of
85/// iterating necessary.
86///
87/// Each record in the record sections is of a specific type. Each type has
88/// its specific record data. Because there are so many types, we decided
89/// against having only one giant enum. Instead, invidual types can either
90/// implement the record data for one single record type or there can be
91/// compound types covering multiple record types. An example of the latter
92/// is [`AllRecordData`] from the [rdata] module that does indeed provide
93/// this one giant enum if you insist on using it.
94///
95/// Consequently, the typ representing a record section of a message,
96/// somewhat obviously named [`RecordSection`], iterates over a stand-in type,
97/// [`ParseRecord`], that gives you access to all information of the record
98/// except for its data.
99///
100/// There are two ways to convert that value into a [`Record`] with actual
101/// data. [`ParseRecord::into_record`] takes a record data type as a type
102/// argument—turbo-fish style—and tries to reparse the record as a record
103/// with that data. Alternatively, you can switch the entire record section
104/// to inly iterate over such records via the [`limit_to`] method.
105///
106/// So, if you want to iterate over the MX records in the answer section, you
107/// would do something like this:
108///
109/// ```
110/// # use domain_core::bits::message::Message;
111/// use domain_core::rdata::parsed::Mx;
112///
113/// # let bytes = vec![0; 12].into();
114/// let msg = Message::from_bytes(bytes).unwrap();
115/// for record in msg.answer().unwrap().limit_to::<Mx>() {
116/// if let Ok(record) = record {
117/// // Do something with the record ...
118/// }
119/// }
120/// ```
121///
122/// The code inside the for loop deals with the fact that iterator actually
123/// returns a `Result<T, E>`. An error signals that something went wrong while
124/// parsing. If only the record data is broken, the message remains useful and
125/// parsing can continue with the next record. If the message is fully
126/// broken, the next iteration will return `None` to signal that.
127///
128/// [`additional`]: #method.additional
129/// [`answer`]: #method.answer
130/// [`authority`]: #method.authority
131/// [`counts`]: #method.counts
132/// [`first_question`]: #method.first_question
133/// [`from_bytes`]: #method.from_bytes
134/// [`header`]: #method.header
135/// [`limit_to`]: ../struct.RecordSection.html#method.limit_to
136/// [`next_section`]: ../struct.RecordSection.html#method.next_section
137/// [`question`]: #method.question
138/// [`sections`]: #method.sections
139/// [`AllRecordData`]: ../../rdata/enum.AllRecordData.html
140/// [`QuestionSection`]: struct.QuestionSection.html
141/// [`ParseRecord`]: ../record/struct.ParseRecord.html
142/// [`ParseRecord::into_record`]: ../record/struct.ParseRecord.html#method.into_record
143/// [`RecordSection`]: struct.RecordSection.html
144/// [Header Section]: #header-section
145/// [rdata]: ../../rdata/index.html
146/// [RFC 1035]: https://tools.ietf.org/html/rfc1035
147#[derive(Clone, Debug)]
148pub struct Message {
149 bytes:Bytes,
150}
151
152/// # Creation and Conversion
153///
154impl Message {
155 /// Creates a message from a bytes value.
156 ///
157 /// This fails if the slice is too short to even contain a complete
158 /// header section. No further checks are done, though, so if this
159 /// function returns `Ok`, the message may still be broken with other
160 /// methods returning `Err(_)`.
161 pub fn from_bytes(bytes: Bytes) -> Result<Self, ShortBuf> {
162 if bytes.len() < mem::size_of::<HeaderSection>() {
163 Err(ShortBuf)
164 }
165 else {
166 Ok(Message { bytes })
167 }
168 }
169
170 /// Creates a message from a bytes value without checking.
171 pub(super) unsafe fn from_bytes_unchecked(bytes: Bytes) -> Self {
172 Message { bytes }
173 }
174
175 /// Returns a reference to the underlying bytes value.
176 pub fn as_bytes(&self) -> &Bytes {
177 &self.bytes
178 }
179
180 /// Returns a reference to the underlying byte slice.
181 pub fn as_slice(&self) -> &[u8] {
182 self.bytes.as_ref()
183 }
184}
185
186
187/// # Header Section
188///
189impl Message {
190 /// Returns a reference to the message header.
191 pub fn header(&self) -> &Header {
192 Header::for_message_slice(self.as_slice())
193 }
194
195 /// Returns a refernce the header counts of the message.
196 pub fn header_counts(&self) -> &HeaderCounts {
197 HeaderCounts::for_message_slice(self.as_slice())
198 }
199
200 /// Returns whether the rcode is NoError.
201 pub fn no_error(&self) -> bool {
202 self.header().rcode() == Rcode::NoError
203 }
204
205 /// Returns whether the rcode is one of the error values.
206 pub fn is_error(&self) -> bool {
207 self.header().rcode() != Rcode::NoError
208 }
209}
210
211
212/// # Sections
213///
214impl Message {
215 /// Returns the question section.
216 pub fn question(&self) -> QuestionSection {
217 QuestionSection::new(self.bytes.clone())
218 }
219
220 /// Returns the zone section of an UPDATE message.
221 ///
222 /// This is identical to `self.question()`.
223 pub fn zone(&self) -> QuestionSection { self.question() }
224
225 /// Returns the answer section.
226 pub fn answer(&self) -> Result<RecordSection, ParsedDnameError> {
227 Ok(self.question().next_section()?)
228 }
229
230 /// Returns the prerequisite section of an UPDATE message.
231 ///
232 /// This is identical to `self.answer()`.
233 pub fn prerequisite(&self) -> Result<RecordSection, ParsedDnameError> {
234 self.answer()
235 }
236
237 /// Returns the authority section.
238 pub fn authority(&self) -> Result<RecordSection, ParsedDnameError> {
239 Ok(self.answer()?.next_section()?.unwrap())
240 }
241
242 /// Returns the update section of an UPDATE message.
243 ///
244 /// This is identical to `self.authority()`.
245 pub fn update(&self) -> Result<RecordSection, ParsedDnameError> {
246 self.authority()
247 }
248
249 /// Returns the additional section.
250 pub fn additional(&self) -> Result<RecordSection, ParsedDnameError> {
251 Ok(self.authority()?.next_section()?.unwrap())
252 }
253
254 /// Returns all four sections in one fell swoop.
255 pub fn sections(&self) -> Result<(QuestionSection, RecordSection,
256 RecordSection, RecordSection),
257 ParsedDnameError> {
258 let question = self.question();
259 let answer = question.clone().next_section()?;
260 let authority = answer.clone().next_section()?.unwrap();
261 let additional = authority.clone().next_section()?.unwrap();
262 Ok((question, answer, authority, additional))
263 }
264
265 /// Returns record iterator for all sections
266 pub fn iter(&self) -> MessageIterator {
267 match self.answer() {
268 Ok(section) => MessageIterator { inner: Some(section) },
269 Err(_) => MessageIterator { inner: None },
270 }
271 }
272
273 /// Copy records from message into the target message builder.
274 ///
275 /// The method uses `op` to process records from all packet sections before inserting,
276 /// caller can use this closure to filter or manipulate records before inserting.
277 pub fn copy_records<N, D, R, F>(&self, target: MessageBuilder, op: F) -> Result<AdditionalBuilder, ParsedDnameError>
278 where N: ToDname, D: RecordData, R: Into<Record<N, D>>, F: FnMut(Result<ParsedRecord, ParsedDnameError>) -> Option<R> + Copy
279 {
280 // Copy answer, authority, and additional records.
281 let mut target = target.answer();
282 self.answer()?.filter_map(op).for_each(|rr| target.push(rr).unwrap());
283
284 let mut target = target.authority();
285 self.authority()?.filter_map(op).for_each(|rr| target.push(rr).unwrap());
286
287 let mut target = target.additional();
288 self.additional()?.filter_map(op).for_each(|rr| target.push(rr).unwrap());
289
290 Ok(target)
291 }
292}
293
294
295/// # Helpers for Common Tasks
296///
297impl Message {
298 /// Returns whether this is the answer to some other message.
299 ///
300 /// The method checks whether the ID fields of the headers are the same,
301 /// whether the QR flag is set in this message, and whether the questions
302 /// are the same.
303 pub fn is_answer(&self, query: &Message) -> bool {
304 if !self.header().qr()
305 || self.header().id() != query.header().id()
306 || self.header_counts().qdcount()
307 != query.header_counts().qdcount() {
308 false
309 }
310 else { self.question().eq(query.question()) }
311 }
312
313 /// Returns the first question, if there is any.
314 ///
315 /// The method will return `None` both if there are no questions or if
316 /// parsing fails.
317 pub fn first_question(&self) -> Option<Question<ParsedDname>> {
318 match self.question().next() {
319 None | Some(Err(..)) => None,
320 Some(Ok(question)) => Some(question)
321 }
322 }
323
324 /// Returns the query type of the first question, if any.
325 pub fn qtype(&self) -> Option<Rtype> {
326 self.first_question().map(|x| x.qtype())
327 }
328
329 /// Returns whether the message contains answers of a given type.
330 pub fn contains_answer<D: ParseRecordData>(&self) -> bool {
331 let answer = match self.answer() {
332 Ok(answer) => answer,
333 Err(..) => return false
334 };
335 answer.limit_to::<D>().next().is_some()
336 }
337
338 /// Resolves the canonical name of the answer.
339 ///
340 /// Returns `None` if either the message doesn’t have a question or there
341 /// was a parse error. Otherwise starts with the question’s name,
342 /// follows any CNAME trail and returns the name answers should be for.
343 pub fn canonical_name(&self) -> Option<ParsedDname> {
344 let question = match self.first_question() {
345 None => return None,
346 Some(question) => question
347 };
348 let mut name = question.qname().clone();
349 let answer = match self.answer() {
350 Ok(answer) => answer.limit_to::<Cname<ParsedDname>>(),
351 Err(_) => return None,
352 };
353
354 loop {
355 let mut found = false;
356 for record in answer.clone() {
357 let record = match record {
358 Ok(record) => record,
359 Err(_) => continue,
360 };
361 if *record.owner() == name {
362 name = record.data().cname().clone();
363 found = true;
364 break;
365 }
366 }
367 if !found {
368 break
369 }
370 }
371
372 Some(name)
373 }
374}
375
376
377//--- Deref and AsRef
378
379impl ops::Deref for Message {
380 type Target = Bytes;
381
382 fn deref(&self) -> &Self::Target {
383 self.as_bytes()
384 }
385}
386
387impl AsRef<Message> for Message {
388 fn as_ref(&self) -> &Message {
389 self
390 }
391}
392
393impl AsRef<Bytes> for Message {
394 fn as_ref(&self) -> &Bytes {
395 self.as_bytes()
396 }
397}
398
399impl AsRef<[u8]> for Message {
400 fn as_ref(&self) -> &[u8] {
401 self.as_slice()
402 }
403}
404
405//--- Iterator
406
407pub struct MessageIterator {
408 inner: Option<RecordSection>,
409}
410
411impl Iterator for MessageIterator {
412 type Item = (Result<ParsedRecord, ParsedDnameError>, Section);
413
414 fn next(&mut self) -> Option<Self::Item> {
415 // Try to get next record from current section
416 match self.inner {
417 Some(ref mut inner) => {
418 let item = inner.next();
419 if let Some(item) = item {
420 return Some((item, inner.section));
421 }
422 },
423 None => return None,
424 }
425
426 // Advance to next section if possible, and retry
427 self.inner = match self.inner.clone().unwrap().next_section() {
428 Ok(section) => section,
429 Err(_) => None,
430 };
431
432 self.next()
433 }
434}
435
436//------------ QuestionSection ----------------------------------------------
437
438/// An iterator over the question section of a DNS message.
439///
440/// The iterator’s item is the result of trying to parse the questions. In
441/// case of a parse error, `next()` will return an error once and
442/// `None` after that.
443///
444/// You can create a value of this type through the [`Message::section`]
445/// method. Use the [`answer`] or [`next_section`] methods to proceed
446/// to an iterator over the answer section.
447///
448/// [`Message::section`]: struct.Message.html#method.section
449/// [`answer`]: #method.answer
450/// [`next_section`]: #method.next_section
451#[derive(Clone, Debug)]
452pub struct QuestionSection {
453 /// The parser for generating the questions.
454 parser: Parser,
455
456 /// The remaining number of questions.
457 ///
458 /// The `Result` is here to monitor an error during iteration.
459 /// It is used to fuse the iterator after an error and is also returned
460 /// by `answer()` should that be called after an error.
461 count: Result<u16, ParsedDnameError>
462}
463
464impl QuestionSection {
465 /// Creates a new question section from a bytes value.
466 fn new(bytes: Bytes) -> Self {
467 let mut parser = Parser::from_bytes(bytes);
468 parser.advance(mem::size_of::<HeaderSection>()).unwrap();
469 QuestionSection {
470 count: Ok(HeaderCounts::for_message_slice(
471 parser.as_slice()).qdcount()
472 ),
473 parser,
474 }
475 }
476
477 /// Proceeds to the answer section.
478 ///
479 /// Skips over any remaining questions and then converts itself into
480 /// the first [`RecordSection`].
481 ///
482 /// [`RecordSection`]: struct.RecordSection.html
483 pub fn answer(mut self) -> Result<RecordSection, ParsedDnameError> {
484 // XXX Use Parser::skip here.
485 for question in &mut self {
486 let _ = question?;
487 }
488 match self.count {
489 Ok(..) => Ok(RecordSection::new(self.parser, Section::first())),
490 Err(err) => Err(err)
491 }
492 }
493
494 /// Proceeds to the answer section.
495 ///
496 /// This is an alias for the [`answer`] method.
497 ///
498 /// [`answer`]: #method.answer
499 pub fn next_section(self) -> Result<RecordSection, ParsedDnameError> {
500 self.answer()
501 }
502}
503
504
505//--- Iterator
506
507impl Iterator for QuestionSection {
508 type Item = Result<Question<ParsedDname>, ParsedDnameError>;
509
510 fn next(&mut self) -> Option<Self::Item> {
511 match self.count {
512 Ok(count) if count > 0 => {
513 match Question::parse(&mut self.parser) {
514 Ok(question) => {
515 self.count = Ok(count - 1);
516 Some(Ok(question))
517 }
518 Err(err) => {
519 self.count = Err(err);
520 Some(Err(err))
521 }
522 }
523 }
524 _ => None
525 }
526 }
527}
528
529
530//------------ Section -------------------------------------------------------
531
532/// A helper type enumerating which section a `RecordSection` is currently in.
533#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd)]
534pub enum Section {
535 Answer,
536 Authority,
537 Additional
538}
539
540
541impl Section {
542 /// Returns the first section.
543 pub fn first() -> Self { Section::Answer }
544
545 /// Returns the correct record count for this section.
546 fn count(self, counts: HeaderCounts) -> u16 {
547 match self {
548 Section::Answer => counts.ancount(),
549 Section::Authority => counts.nscount(),
550 Section::Additional => counts.arcount()
551 }
552 }
553
554 /// Returns the value for the following section or `None` if this is last.
555 fn next_section(self) -> Option<Self> {
556 match self {
557 Section::Answer => Some(Section::Authority),
558 Section::Authority => Some(Section::Additional),
559 Section::Additional => None
560 }
561 }
562}
563
564
565//------------ RecordSection -----------------------------------------------
566
567/// An iterator over one of the three record sections of a DNS message.
568///
569/// The iterator’s item is the result of parsing a raw record represented by
570/// [`ParsedRecord`]. This type will allow access to a record’s header
571/// only. It can, however, be converted into a concrete [`Record`] via its
572/// [`into_record`] method. If parsing the raw record fails, the iterator
573/// will return an error once and `None` after that.
574///
575/// Alternatively, you can trade in a value of this type into a
576/// [`RecordIter`] that iterates over [`Record`]s of a specific type by
577/// calling the [`limit_to`] method. In particular, you can use this together
578/// with [`AllRecordData`] to acquire an iterator that parses all known
579/// record types. If you are only interested in a subset of records, it may
580/// be more efficient to create a similar enum with only the types you need.
581///
582/// `RecordSection` values cannot be created directly. You can get one either
583/// by calling the method for the section in question of a [`Message`] value
584/// or by proceeding from another section via its `next_section` method.
585///
586/// [`limit_to`]: #method.limit_to
587/// [`AllRecordData`]: ../../rdata/enum.AllRecordData.html
588/// [`Message`]: struct.Message.html
589/// [`ParseRecord`]: ../record/struct.ParsedRecord.html
590/// [`Record`]: ../record/struct.Record.html
591/// [`RecordIter`]: struct.RecordIter.html
592/// [`into_record`]: ../record/struct.ParsedRecord.html#method.into_record
593#[derive(Clone, Debug)]
594pub struct RecordSection {
595 /// The parser for generating the records.
596 parser: Parser,
597
598 /// Which section are we, really?
599 section: Section,
600
601 /// The remaining number of records.
602 ///
603 /// The `Result` is here to monitor an error during iteration.
604 /// It is used to fuse the iterator after an error and is also returned
605 /// by `answer()` should that be called after an error.
606 count: Result<u16, ParsedDnameError>
607}
608
609
610impl RecordSection {
611 /// Creates a new section from a parser.
612 ///
613 /// The parser must only wrap the bytes of the message and it must be
614 /// positioned at the beginning of the section.
615 fn new(parser: Parser, section: Section) -> Self {
616 RecordSection {
617 count: Ok(section.count(
618 *HeaderCounts::for_message_slice(parser.as_slice())
619 )),
620 section,
621 parser,
622 }
623 }
624
625 /// Trades `self` in for an iterator limited to a concrete record type.
626 ///
627 /// The record type is given through its record data type. Since the data
628 /// is being parsed, this type must implement [`ParseRecordData`]. For
629 /// record data types that are generic over domain name types, this is
630 /// normally achieved by giving them a [`ParsedDname`]. As a convenience,
631 /// type aliases for all the fundamental record data types exist in the
632 /// [domain::rdata::parsed] module.
633 ///
634 /// The returned limited iterator will continue at the current position
635 /// of `self`. It will *not* start from the beginning of the section.
636 ///
637 /// [`ParseRecordData`]: ../rdata/trait.ParseRecordData.html
638 /// [`ParsedDname`]: ../name/struct.ParsedDname.html
639 /// [domain::rdata::parsed]: ../../rdata/parsed/index.html
640 pub fn limit_to<D: ParseRecordData>(self) -> RecordIter<D> {
641 RecordIter::new(self)
642 }
643
644 /// Proceeds to the next section if there is one.
645 ///
646 /// Returns an error if parsing has failed and the message is unsable
647 /// now.
648 pub fn next_section(mut self)
649 -> Result<Option<Self>, ParsedDnameError> {
650 let section = match self.section.next_section() {
651 Some(section) => section,
652 None => return Ok(None)
653 };
654 // XXX Use Parser::skip here.
655 for record in &mut self {
656 let _ = try!(record);
657 }
658 match self.count {
659 Ok(..) => Ok(Some(RecordSection::new(self.parser, section))),
660 Err(err) => Err(err)
661 }
662 }
663}
664
665
666//--- Iterator
667
668impl Iterator for RecordSection {
669 type Item = Result<ParsedRecord, ParsedDnameError>;
670
671 fn next(&mut self) -> Option<Self::Item> {
672 match self.count {
673 Ok(count) if count > 0 => {
674 match ParsedRecord::parse(&mut self.parser) {
675 Ok(record) => {
676 self.count = Ok(count - 1);
677 Some(Ok(record))
678 }
679 Err(err) => {
680 self.count = Err(err);
681 Some(Err(err))
682 }
683 }
684 }
685 _ => None
686 }
687 }
688}
689
690
691//------------ RecordIter ----------------------------------------------------
692
693/// An iterator over specific records of a record section of a DNS message.
694///
695/// The iterator’s item type is the result of trying to parse a record.
696/// It silently skips over all records that `D` cannot or does not want to
697/// parse. If parsing the record data fails, the iterator will return an
698/// error but can continue with the next record. If parsing the entire record
699/// fails (and the message thus becoming unusable) or if the end of the
700/// section is reached, the iterator produces `None`. The latter case can be
701/// distinguished by [`next_section`] returning an error.
702///
703/// You can create a value of this type through the
704/// [`RecordSection::limit_to`] method.
705///
706/// [`next_section`]: #method.next_section
707/// [`RecordSection::limit_to`]: struct.RecordSection.html#method.limit_to
708#[derive(Clone, Debug)]
709pub struct RecordIter<D: ParseRecordData> {
710 section: RecordSection,
711 marker: PhantomData<D>
712}
713
714impl<D: ParseRecordData> RecordIter<D> {
715 /// Creates a new limited record iterator from the given section.
716 fn new(section: RecordSection) -> Self {
717 RecordIter { section, marker: PhantomData }
718 }
719
720 /// Trades in the limited iterator for the complete iterator.
721 ///
722 /// The complete iterator will continue right after the last record
723 /// returned by `self`. It will *not* restart from the beginning of the
724 /// section.
725 pub fn unwrap(self) -> RecordSection {
726 self.section
727 }
728
729 /// Proceeds to the next section if there is one.
730 ///
731 /// Returns an error if parsing has failed and the message is unusable
732 /// now.
733 pub fn next_section(self)
734 -> Result<Option<RecordSection>, ParsedDnameError> {
735 self.section.next_section()
736 }
737}
738
739
740//--- Iterator
741
742impl<D: ParseRecordData> Iterator for RecordIter<D> {
743 type Item = Result<Record<ParsedDname, D>,
744 RecordParseError<ParsedDnameError, D::Err>>;
745
746 fn next(&mut self) -> Option<Self::Item> {
747 loop {
748 let record = match self.section.next() {
749 Some(Ok(record)) => record,
750 Some(Err(err)) => {
751 return Some(Err(RecordParseError::Name(err)))
752 }
753 None => return None,
754 };
755 match record.into_record() {
756 Ok(Some(record)) => return Some(Ok(record)),
757 Err(err) => return Some(Err(err)),
758 Ok(None) => { }
759 }
760 }
761 }
762}
763
764
765//============ Testing ======================================================
766
767#[cfg(test)]
768mod test {
769 use std::str::FromStr;
770 use super::*;
771 use bits::name::*;
772 use bits::message_builder::*;
773 use rdata::Ns;
774 use bits::rdata::UnknownRecordData;
775
776 // Helper for test cases
777 fn get_test_message() -> Message {
778 let msg = MessageBuilder::with_capacity(512);
779 let mut msg = msg.answer();
780 msg.push((Dname::from_str("foo.example.com.").unwrap(), 86000,
781 Cname::new(Dname::from_str("baz.example.com.")
782 .unwrap()))).unwrap();
783 let mut msg = msg.authority();
784 msg.push((Dname::from_str("bar.example.com.").unwrap(), 86000,
785 Ns::new(Dname::from_str("baz.example.com.")
786 .unwrap()))).unwrap();
787
788 Message::from_bytes(msg.finish().into()).unwrap()
789 }
790
791 #[test]
792 fn short_message() {
793 assert!(Message::from_bytes(Bytes::from_static(&[0u8; 11])).is_err());
794 assert!(Message::from_bytes(Bytes::from_static(&[0u8; 12])).is_ok());
795 }
796
797 /*
798 use std::str::FromStr;
799 use bits::message_builder::MessageBuilder;
800 use bits::name::Dname;
801 use bits::question::Question;
802 use iana::Rtype;
803 use rdata::Cname;
804
805 #[test]
806 fn canonical_name() {
807 // Message without CNAMEs.
808 let mut msg = MessageBuilder::new_udp();
809 msg.push(&Question::new_in(Dname::from_str("example.com.").unwrap(),
810 Rtype::A)).unwrap();
811 let msg = Message::from_bytes(msg.freeze()).unwrap();
812 println!("{:?}", msg);
813 assert_eq!(Dname::from_str("example.com.").unwrap(),
814 msg.canonical_name().unwrap());
815 // Message with CNAMEs.
816 let mut msg = MessageBuilder::new(ComposeMode::Unlimited,
817 true).unwrap();
818 msg.push((DNameBuf::from_str("example.com.").unwrap(),
819 Rtype::A)).unwrap();
820 let mut answer = msg.answer();
821 answer.push((DNameBuf::from_str("bar.example.com.").unwrap(), 86000,
822 Cname::new(DNameBuf::from_str("baz.example.com.")
823 .unwrap())))
824 .unwrap();
825 answer.push((DNameBuf::from_str("example.com.").unwrap(), 86000,
826 Cname::new(DNameBuf::from_str("foo.example.com.")
827 .unwrap())))
828 .unwrap();
829 answer.push((DNameBuf::from_str("foo.example.com.").unwrap(), 86000,
830 Cname::new(DNameBuf::from_str("bar.example.com.")
831 .unwrap())))
832 .unwrap();
833 let msg = MessageBuf::from_vec(answer.finish()).unwrap();
834 assert_eq!(DNameBuf::from_str("baz.example.com.").unwrap(),
835 msg.canonical_name().unwrap());
836 }
837 */
838
839 #[test]
840 fn message_iterator() {
841 let msg = get_test_message();
842
843 // Check that it returns a record from first section
844 let mut iter = msg.iter();
845 let mut value = iter.next();
846 assert_eq!(true, value.is_some());
847 let (rr, section) = value.unwrap();
848 assert_eq!(Section::Answer, section);
849 assert!(rr.is_ok());
850
851 // Check that it advances to next section
852 value = iter.next();
853 assert_eq!(true, value.is_some());
854 let (rr, section) = value.unwrap();
855 assert_eq!(Section::Authority, section);
856 assert!(rr.is_ok());
857 }
858
859 #[test]
860 fn copy_records() {
861 let msg = get_test_message();
862 let target = MessageBuilder::with_capacity(512);
863 let res = msg.copy_records(target, |rec| {
864 if let Ok(rr) = rec {
865 if let Ok(Some(rr)) = rr.into_record::<UnknownRecordData>() {
866 if rr.rtype() == Rtype::Cname {
867 return Some(rr);
868 }
869 }
870 }
871 return None;
872 });
873
874 assert!(res.is_ok());
875 if let Ok(target) = res {
876 let msg = target.freeze();
877 assert_eq!(1, msg.header_counts().ancount());
878 assert_eq!(0, msg.header_counts().arcount());
879 }
880 }
881}