domain/base/message_builder.rs
1//! Building a new DNS message.
2//!
3//! The types in this module allow building a DNS message consecutively from
4//! its parts. Since messages consist of five parts, a number of types are
5//! involved. The concept is that you start out with a [`MessageBuilder`] and
6//! work your way step by step through the sections by trading the builder in
7//! for on of another type representing the following section. The sequence
8//! is [`MessageBuilder`], [`QuestionBuilder`], [`AnswerBuilder`],
9//! [`AuthorityBuilder`], and finally [`AdditionalBuilder`].
10//!
11//! You can skip forward over unwanted sections. You can also go backwards,
12//! but then you’ll loose anything you built before. The naming of the
13//! methods that do these things is consistent across types: `builder` takes
14//! you to the message builder. The four methods `question`, `answer`,
15//! `additional`, and `authority` progress or return to the respective
16//! section. Finally, `finish` completes building.
17//!
18//! Each of the section builders offers a `push` method to add elements to
19//! the section. For the question section, the method accepts anything that
20//! resembles a [`Question`] while the three record sections except
21//! something that looks like a [`Record`]. Apart from actual values
22//! of these types, tuples of the components also work, such as a pair of a
23//! domain name and a record type for a question or a triple of the owner
24//! name, TTL, and record data for a record.
25//!
26//! The `push` method of the record
27//! section builders is also available via the [`RecordSectionBuilder`]
28//! trait so you can build code that works with all three record sections.
29//!
30//! The [`AdditionalBuilder`] has a special feature that helps building the
31//! OPT record for EDNS. Its [`opt`][AdditionalBuilder::opt] method allows a
32//! closure to build this record on the fly via the [`OptBuilder`] type.
33//!
34//! Building happens atop any [octets builder], so the type of buffer to use
35//! for building can be chosen. The module also provides a few helper types
36//! that provide optional features for building messages. All of these are
37//! wrappers around an octets builder and are octets builders themselves, so
38//! you can mix and match.
39//!
40//! First, the [`StreamTarget`] builds a message for use with streaming
41//! transport protocols, e.g., TCP, where the actual message is preceded by
42//! a 16 bit length counter. The stream target keeps this counter up-to-date
43//! and makes sure the message doesn’t become longer than what the counter
44//! can provide for.
45//!
46//! There is also support for name compression. This is a mechanism to decrease
47//! the size of a DNS message by avoiding repeating domain names: Instead of
48//! including a domain name or suffix of a domain name that has been mentioned
49//! already, a pointer to the position of the original mention is provided.
50//! Since this process is somewhat expensive as you have to remember which names
51//! have already been used, it isn’t enabled by default and is instead provided
52//! by separate octets builders which we call compressors.
53//!
54//! Currently, there are three different compressors. [`TreeCompressor`] stores
55//! all names it encountered in a binary tree. While it can handle any number
56//! of names, it does require an allocator and therefore cannot be used in a
57//! `no_std` environment. [`HashCompressor`] also requires allocation, but uses
58//! a fast and space efficient hash table (via the `hashbrown` crate) instead.
59//! [`StaticCompressor`], meanwhile, has a static table for up to 24 names. It
60//! is ineffective on large messages with lots of different names, but this is
61//! quite rare anyway.
62//!
63//! # Example
64//!
65//! The following example builds a message with both name compression and
66//! the stream length and simply puts two A records into it.
67//!
68#![cfg_attr(feature = "std", doc = "```")]
69#![cfg_attr(not(feature = "std"), doc = "```ignore")]
70//! use std::str::FromStr;
71//! use domain::base::{
72//! Name, MessageBuilder, Rtype, StaticCompressor, StreamTarget
73//! };
74//! use domain::rdata::A;
75//!
76//! // Make a domain name we can use later on.
77//! let name = Name::<Vec<u8>>::from_str("example.com").unwrap();
78//!
79//! // Create a message builder wrapping a compressor wrapping a stream
80//! // target.
81//! let mut msg = MessageBuilder::from_target(
82//! StaticCompressor::new(
83//! StreamTarget::new_vec()
84//! )
85//! ).unwrap();
86//!
87//! // Set the RD bit in the header and proceed to the question section.
88//! msg.header_mut().set_rd(true);
89//! let mut msg = msg.question();
90//!
91//! // Add a question and proceed to the answer section.
92//! msg.push((&name, Rtype::A)).unwrap();
93//! let mut msg = msg.answer();
94//!
95//! // Add two answer and proceed to the additional sections
96//! msg.push((&name, 86400, A::from_octets(192, 0, 2, 1))).unwrap();
97//! msg.push((&name, 86400, A::from_octets(192, 0, 2, 2))).unwrap();
98//! let mut msg = msg.additional();
99//!
100//! // Add an OPT record.
101//! msg.opt(|opt| {
102//! opt.set_udp_payload_size(4096);
103//! Ok(())
104//! }).unwrap();
105//!
106//! // Convert the builder into the actual message.
107//! let target = msg.finish().into_target();
108//!
109//! // A stream target can provide access to the data with or without the
110//! // length counter:
111//! let _ = target.as_stream_slice(); // With length
112//! let _ = target.as_dgram_slice(); // Without length
113//! ```
114//!
115//! [`MessageBuilder`]: struct.MessageBuilder.html
116//! [`QuestionBuilder`]: struct.QuestionBuilder.html
117//! [`AnswerBuilder`]: struct.AnswerBuilder.html
118//! [`AuthorityBuilder`]: struct.AuthorityBuilder.html
119//! [`AdditionalBuilder`]: struct.AdditionalBuilder.html
120//! [`AdditionalBuilder::opt`]: struct.AdditionalBuilder.html#method.opt
121//! [`OptBuilder`]: struct.OptBuilder.html
122//! [`RecordSectionBuilder`]: trait.RecordSectionBuilder.html
123//! [`StaticCompressor`]: struct.StaticCompressor.html
124//! [`StreamTarget`]: struct.StreamTarget.html
125//! [`TreeCompressor`]: struct.TreeCompressor.html
126//! [`Question`]: ../question/struct.Question.html
127//! [`Record`]: ../question/struct.Record.html
128//! [octets builder]: ../octets/trait.OctetsBuilder.html
129
130use super::header::{CountOverflow, Header, HeaderCounts, HeaderSection};
131#[cfg(feature = "rand")]
132use super::iana::Rtype;
133use super::iana::{OptRcode, OptionCode, Rcode};
134use super::message::Message;
135use super::name::{Label, ToName};
136use super::opt::{ComposeOptData, OptHeader, OptRecord};
137use super::question::ComposeQuestion;
138use super::record::ComposeRecord;
139use super::wire::{Compose, Composer};
140#[cfg(feature = "bytes")]
141use bytes::BytesMut;
142use core::ops::{Deref, DerefMut};
143use core::{fmt, mem};
144#[cfg(feature = "std")]
145use hashbrown::HashTable;
146#[cfg(feature = "std")]
147use octseq::array::Array;
148#[cfg(any(feature = "std", feature = "bytes"))]
149use octseq::builder::infallible;
150use octseq::builder::{FreezeBuilder, OctetsBuilder, ShortBuf, Truncate};
151use octseq::octets::Octets;
152#[cfg(feature = "std")]
153use std::collections::{hash_map::RandomState, HashMap};
154#[cfg(feature = "std")]
155use std::hash::BuildHasher;
156#[cfg(feature = "std")]
157use std::vec::Vec;
158
159//------------ MessageBuilder ------------------------------------------------
160
161/// Starts building a DNS message.
162///
163/// This type wraps an [`OctetsBuilder`] and starts the process of building a
164/// message. It allows access to the header section. The message builder can
165/// be traded in for any section builder or the underlying octets builder.
166///
167/// For more details see the [module documentation].
168///
169/// [module documentation]: index.html
170/// [`OctetsBuilder`]: ../../octets/trait.OctetsBuilder.html
171#[derive(Clone, Debug)]
172pub struct MessageBuilder<Target> {
173 target: Target,
174
175 /// An optional maximum message size.
176 ///
177 /// Defaults to usize::MAX.
178 limit: usize,
179}
180
181/// # Creating Message Builders
182///
183impl<Target: OctetsBuilder + Truncate> MessageBuilder<Target> {
184 /// Creates a new message builder using the given target.
185 ///
186 /// The target must be an [`OctetsBuilder`]. It will be truncated to zero
187 /// size before appending the header section. That is, all data that was
188 /// in the builder before will be lost.
189 ///
190 /// The function will result in an error if the builder doesn’t have
191 /// enough space for the header section.
192 pub fn from_target(
193 mut target: Target,
194 ) -> Result<Self, Target::AppendError> {
195 target.truncate(0);
196 target.append_slice(HeaderSection::new().as_slice())?;
197 Ok(MessageBuilder {
198 target,
199 limit: usize::MAX,
200 })
201 }
202}
203
204#[cfg(feature = "std")]
205impl MessageBuilder<Vec<u8>> {
206 /// Creates a new message builder atop a `Vec<u8>`.
207 #[must_use]
208 pub fn new_vec() -> Self {
209 infallible(Self::from_target(Vec::new()))
210 }
211}
212
213#[cfg(feature = "std")]
214impl MessageBuilder<StreamTarget<Vec<u8>>> {
215 /// Creates a new builder for a streamable message atop a `Vec<u8>`.
216 #[must_use]
217 pub fn new_stream_vec() -> Self {
218 Self::from_target(StreamTarget::new_vec()).unwrap()
219 }
220}
221
222#[cfg(feature = "bytes")]
223impl MessageBuilder<BytesMut> {
224 /// Creates a new message builder atop a bytes value.
225 pub fn new_bytes() -> Self {
226 infallible(Self::from_target(BytesMut::new()))
227 }
228}
229
230#[cfg(feature = "bytes")]
231impl MessageBuilder<StreamTarget<BytesMut>> {
232 /// Creates a new streamable message builder atop a bytes value.
233 pub fn new_stream_bytes() -> Self {
234 Self::from_target(StreamTarget::new_bytes()).unwrap()
235 }
236}
237
238impl<Target: Composer> MessageBuilder<Target> {
239 /// Starts creating an answer for the given message.
240 ///
241 /// Specifically, this sets the ID, QR, OPCODE, RD, and RCODE fields
242 /// in the header and attempts to push the message’s questions to the
243 /// builder.
244 ///
245 /// The method converts the message builder into an answer builder ready
246 /// to receive the answer for the question.
247 pub fn start_answer<Octs: Octets + ?Sized>(
248 mut self,
249 msg: &Message<Octs>,
250 rcode: Rcode,
251 ) -> Result<AnswerBuilder<Target>, PushError> {
252 {
253 let header = self.header_mut();
254 header.set_id(msg.header().id());
255 header.set_qr(true);
256 header.set_opcode(msg.header().opcode());
257 header.set_rd(msg.header().rd());
258 header.set_rcode(rcode);
259 }
260 let mut builder = self.question();
261 for item in msg.question().flatten() {
262 builder.push(item)?;
263 }
264 Ok(builder.answer())
265 }
266
267 /// Starts creating an error for the given message.
268 ///
269 /// Like [`start_answer()`][Self::start_answer] but infallible. Questions
270 /// will be pushed if possible.
271 pub fn start_error<Octs: Octets + ?Sized>(
272 mut self,
273 msg: &Message<Octs>,
274 rcode: Rcode,
275 ) -> AnswerBuilder<Target> {
276 {
277 let header = self.header_mut();
278 header.set_id(msg.header().id());
279 header.set_qr(true);
280 header.set_opcode(msg.header().opcode());
281 header.set_rd(msg.header().rd());
282 header.set_rcode(rcode);
283 }
284
285 let mut builder = self.question();
286 for item in msg.question().flatten() {
287 if builder.push(item).is_err() {
288 builder.header_mut().set_rcode(Rcode::SERVFAIL);
289 break;
290 }
291 }
292
293 builder.answer()
294 }
295
296 /// Creates an AXFR request for the given domain.
297 ///
298 /// Sets a random ID, pushes the domain and the AXFR record type into
299 /// the question section, and converts the builder into an answer builder.
300 #[cfg(feature = "rand")]
301 pub fn request_axfr<N: ToName>(
302 mut self,
303 apex: N,
304 ) -> Result<AnswerBuilder<Target>, PushError> {
305 self.header_mut().set_random_id();
306 let mut builder = self.question();
307 builder.push((apex, Rtype::AXFR))?;
308 Ok(builder.answer())
309 }
310}
311
312/// # Limiting message size
313impl<Target: Composer> MessageBuilder<Target> {
314 /// Limit how much of the underlying buffer may be used.
315 ///
316 /// When a limit is set, calling `push()` on a message section (e.g.
317 /// [`AdditionalBuilder::push()`]) will fail if the limit is exceeded just
318 /// as if the actual end of the underlying buffer had been reached.
319 ///
320 /// Note: Calling this function does NOT truncate the underlying buffer.
321 /// If the new limit is lees than the amount of the buffer that has
322 /// already been used, exisitng content beyond the limit will remain
323 /// untouched, the length will remain larger than the limit, and calls to
324 /// `push()` will fail until the buffer is truncated to a size less than
325 /// the limit.
326 pub fn set_push_limit(&mut self, limit: usize) {
327 self.limit = limit;
328 }
329
330 /// Clear the push limit, if set.
331 ///
332 /// Removes any push limit previously set via `[set_push_limit()`].
333 pub fn clear_push_limit(&mut self) {
334 self.limit = usize::MAX;
335 }
336
337 /// Returns the current push limit, if set.
338 pub fn push_limit(&self) -> Option<usize> {
339 if self.limit == usize::MAX {
340 None
341 } else {
342 Some(self.limit)
343 }
344 }
345}
346
347/// # Access to the Message Header
348///
349impl<Target: OctetsBuilder + AsRef<[u8]>> MessageBuilder<Target> {
350 /// Return the current value of the message header.
351 pub fn header(&self) -> Header {
352 *Header::for_message_slice(self.target.as_ref())
353 }
354
355 /// Return the current value of the message header counts.
356 pub fn counts(&self) -> HeaderCounts {
357 *HeaderCounts::for_message_slice(self.target.as_ref())
358 }
359}
360
361impl<Target: OctetsBuilder + AsMut<[u8]>> MessageBuilder<Target> {
362 /// Returns a mutable reference to the message header for manipulations.
363 pub fn header_mut(&mut self) -> &mut Header {
364 Header::for_message_slice_mut(self.target.as_mut())
365 }
366
367 /// Returns a mutable reference to the message header counts.
368 fn counts_mut(&mut self) -> &mut HeaderCounts {
369 HeaderCounts::for_message_slice_mut(self.target.as_mut())
370 }
371}
372
373/// # Conversions
374///
375impl<Target> MessageBuilder<Target> {
376 /// Converts the message builder into a message builder
377 ///
378 /// This is a no-op.
379 pub fn builder(self) -> MessageBuilder<Target> {
380 self
381 }
382}
383
384impl<Target: Composer> MessageBuilder<Target> {
385 /// Converts the message builder into a question builder.
386 pub fn question(self) -> QuestionBuilder<Target> {
387 QuestionBuilder::new(self)
388 }
389
390 /// Converts the message builder into an answer builder.
391 ///
392 /// This will leave the question section empty.
393 pub fn answer(self) -> AnswerBuilder<Target> {
394 self.question().answer()
395 }
396
397 /// Converts the message builder into an authority builder.
398 ///
399 /// This will leave the question and answer sections empty.
400 pub fn authority(self) -> AuthorityBuilder<Target> {
401 self.question().answer().authority()
402 }
403
404 /// Converts the message builder into an additional builder.
405 ///
406 /// This will leave the question, answer, and authority sections empty.
407 pub fn additional(self) -> AdditionalBuilder<Target> {
408 self.question().answer().authority().additional()
409 }
410
411 /// Converts the message into the underlying octets builder.
412 ///
413 /// This will leave the all sections empty.
414 pub fn finish(self) -> Target {
415 self.target
416 }
417}
418
419impl<Target: FreezeBuilder> MessageBuilder<Target> {
420 /// Converts the builder into a message.
421 ///
422 /// The method will return a message atop whatever octets sequence the
423 /// builder’s octets builder converts into.
424 pub fn into_message(self) -> Message<Target::Octets> {
425 unsafe { Message::from_octets_unchecked(self.target.freeze()) }
426 }
427}
428
429impl<Target> MessageBuilder<Target> {
430 /// Returns a reference to the underlying octets builder.
431 pub fn as_target(&self) -> &Target {
432 &self.target
433 }
434
435 /// Returns a mutable reference to the underlying octets builder.
436 ///
437 /// Since one could entirely mess up the message with this reference, the
438 /// method is private.
439 fn as_target_mut(&mut self) -> &mut Target {
440 &mut self.target
441 }
442
443 /// Returns an octets slice of the octets assembled so far.
444 pub fn as_slice(&self) -> &[u8]
445 where
446 Target: AsRef<[u8]>,
447 {
448 self.as_target().as_ref()
449 }
450
451 /// Returns a message atop for the octets assembled so far.
452 ///
453 /// This message is atop the octets slices derived from the builder, so
454 /// it can be created cheaply.
455 pub fn as_message(&self) -> Message<&[u8]>
456 where
457 Target: AsRef<[u8]>,
458 {
459 unsafe { Message::from_octets_unchecked(self.target.as_ref()) }
460 }
461}
462
463impl<Target: Composer> MessageBuilder<Target> {
464 fn push<Push, Inc>(
465 &mut self,
466 push: Push,
467 inc: Inc,
468 ) -> Result<(), PushError>
469 where
470 Push: FnOnce(&mut Target) -> Result<(), ShortBuf>,
471 Inc: FnOnce(&mut HeaderCounts) -> Result<(), CountOverflow>,
472 {
473 let pos = self.target.as_ref().len();
474 if let Err(err) = push(&mut self.target) {
475 self.target.truncate(pos);
476 return Err(From::from(err));
477 }
478
479 let new_pos = self.target.as_ref().len();
480 if new_pos >= self.limit {
481 self.target.truncate(pos);
482 return Err(PushError::ShortBuf);
483 }
484
485 if inc(self.counts_mut()).is_err() {
486 self.target.truncate(pos);
487 return Err(PushError::CountOverflow);
488 }
489 Ok(())
490 }
491}
492
493//--- From
494
495impl<Target> From<QuestionBuilder<Target>> for MessageBuilder<Target>
496where
497 Target: Composer,
498{
499 fn from(src: QuestionBuilder<Target>) -> Self {
500 src.builder()
501 }
502}
503
504impl<Target> From<AnswerBuilder<Target>> for MessageBuilder<Target>
505where
506 Target: Composer,
507{
508 fn from(src: AnswerBuilder<Target>) -> Self {
509 src.builder()
510 }
511}
512
513impl<Target> From<AuthorityBuilder<Target>> for MessageBuilder<Target>
514where
515 Target: Composer,
516{
517 fn from(src: AuthorityBuilder<Target>) -> Self {
518 src.builder()
519 }
520}
521
522impl<Target> From<AdditionalBuilder<Target>> for MessageBuilder<Target>
523where
524 Target: Composer,
525{
526 fn from(src: AdditionalBuilder<Target>) -> Self {
527 src.builder()
528 }
529}
530
531impl<Target> From<MessageBuilder<Target>> for Message<Target::Octets>
532where
533 Target: FreezeBuilder,
534{
535 fn from(src: MessageBuilder<Target>) -> Self {
536 src.into_message()
537 }
538}
539
540//--- AsRef
541//
542// XXX Should we deref down to target?
543
544impl<Target> AsRef<Target> for MessageBuilder<Target> {
545 fn as_ref(&self) -> &Target {
546 self.as_target()
547 }
548}
549
550impl<Target: AsRef<[u8]>> AsRef<[u8]> for MessageBuilder<Target> {
551 fn as_ref(&self) -> &[u8] {
552 self.as_slice()
553 }
554}
555
556//------------ QuestionBuilder -----------------------------------------------
557
558/// Builds the question section of a DNS message.
559///
560/// A value of this type can be acquired by calling the `question` method on
561/// any other builder type. See the [module documentation] for an overview of
562/// how to build a message.
563///
564/// You can push questions to the end of the question section via the
565/// [`push`] method. It accepts various things that represent a question:
566/// question values and references; tuples of a domain name, record type, and
567/// class; and, using the regular class of IN, a pair of just a domain name
568/// and record type.
569///
570/// Once you are finished building the question section, you can progress to
571/// the answer section via the [`answer`] method or finish the message via
572/// [`finish`]. Additionally, conversions to all other builder types are
573/// available as well.
574///
575/// [`answer`]: #method.answer
576/// [`finish`]: #method.finish
577/// [`push`]: #method.push
578/// [module documentation]: index.html
579#[derive(Clone, Debug)]
580pub struct QuestionBuilder<Target> {
581 builder: MessageBuilder<Target>,
582}
583
584impl<Target: OctetsBuilder> QuestionBuilder<Target> {
585 /// Creates a new question builder from a message builder.
586 fn new(builder: MessageBuilder<Target>) -> Self {
587 Self { builder }
588 }
589}
590
591impl<Target: Composer> QuestionBuilder<Target> {
592 /// Appends a question to the question section.
593 ///
594 /// This method accepts anything that implements the [`ComposeQuestion`]
595 /// trait. Apart from an actual [`Question`][super::question::Question]
596 /// or a reference to it, this can also be a tuple of a domain name,
597 /// record type, and class or, if the class is the usual IN, a pair of
598 /// just the name and type.
599 ///
600 /// In other words, the options are:
601 ///
602 #[cfg_attr(feature = "std", doc = "```")]
603 #[cfg_attr(not(feature = "std"), doc = "```ignore")]
604 /// use domain::base::{Name, MessageBuilder, Question, Rtype};
605 /// use domain::base::iana::Class;
606 ///
607 /// let mut msg = MessageBuilder::new_vec().question();
608 /// msg.push(Question::new_in(Name::root_ref(), Rtype::A)).unwrap();
609 /// msg.push(&Question::new_in(Name::root_ref(), Rtype::A)).unwrap();
610 /// msg.push((Name::root_ref(), Rtype::A, Class::IN)).unwrap();
611 /// msg.push((Name::root_ref(), Rtype::A)).unwrap();
612 /// ```
613 pub fn push(
614 &mut self,
615 question: impl ComposeQuestion,
616 ) -> Result<(), PushError> {
617 self.builder.push(
618 |target| question.compose_question(target).map_err(Into::into),
619 |counts| counts.inc_qdcount(),
620 )
621 }
622}
623
624/// # Conversions
625///
626/// Additional conversion are available via the `Deref` implementation.
627impl<Target: Composer> QuestionBuilder<Target> {
628 /// Rewinds to an empty question section.
629 ///
630 /// All previously added questions will be lost.
631 pub fn rewind(&mut self) {
632 self.as_target_mut()
633 .truncate(mem::size_of::<HeaderSection>());
634 self.counts_mut().set_qdcount(0);
635 }
636
637 /// Converts the question builder into a message builder.
638 ///
639 /// All questions will be dropped and the question section will be empty.
640 pub fn builder(mut self) -> MessageBuilder<Target> {
641 self.rewind();
642 self.builder
643 }
644}
645
646impl<Target> QuestionBuilder<Target> {
647 /// Converts the question builder into a question builder.
648 ///
649 /// In other words, doesn’t do anything.
650 pub fn question(self) -> QuestionBuilder<Target> {
651 self
652 }
653}
654
655impl<Target: Composer> QuestionBuilder<Target> {
656 /// Converts the question builder into an answer builder.
657 pub fn answer(self) -> AnswerBuilder<Target> {
658 AnswerBuilder::new(self.builder)
659 }
660
661 /// Converts the question builder into an authority builder.
662 ///
663 /// This will leave the answer section empty.
664 pub fn authority(self) -> AuthorityBuilder<Target> {
665 self.answer().authority()
666 }
667
668 /// Converts the question builder into an additional builder.
669 ///
670 /// This will leave the answer and authority sections empty.
671 pub fn additional(self) -> AdditionalBuilder<Target> {
672 self.answer().authority().additional()
673 }
674
675 /// Converts the question builder into the underlying octets builder.
676 ///
677 /// This will leave the answer, authority, and additional sections empty.
678 pub fn finish(self) -> Target {
679 self.builder.finish()
680 }
681}
682
683impl<Target: FreezeBuilder> QuestionBuilder<Target> {
684 /// Converts the question builder into the final message.
685 ///
686 /// The method will return a message atop whatever octets sequence the
687 /// builder’s octets builder converts into.
688 pub fn into_message(self) -> Message<Target::Octets> {
689 self.builder.into_message()
690 }
691}
692
693impl<Target> QuestionBuilder<Target> {
694 /// Returns a reference to the underlying message builder.
695 pub fn as_builder(&self) -> &MessageBuilder<Target> {
696 &self.builder
697 }
698
699 /// Returns a mutable reference to the underlying message builder.
700 pub fn as_builder_mut(&mut self) -> &mut MessageBuilder<Target> {
701 &mut self.builder
702 }
703}
704
705//--- From
706
707impl<Target> From<MessageBuilder<Target>> for QuestionBuilder<Target>
708where
709 Target: Composer,
710{
711 fn from(src: MessageBuilder<Target>) -> Self {
712 src.question()
713 }
714}
715
716impl<Target> From<AnswerBuilder<Target>> for QuestionBuilder<Target>
717where
718 Target: Composer,
719{
720 fn from(src: AnswerBuilder<Target>) -> Self {
721 src.question()
722 }
723}
724
725impl<Target> From<AuthorityBuilder<Target>> for QuestionBuilder<Target>
726where
727 Target: Composer,
728{
729 fn from(src: AuthorityBuilder<Target>) -> Self {
730 src.question()
731 }
732}
733
734impl<Target> From<AdditionalBuilder<Target>> for QuestionBuilder<Target>
735where
736 Target: Composer,
737{
738 fn from(src: AdditionalBuilder<Target>) -> Self {
739 src.question()
740 }
741}
742
743impl<Target> From<QuestionBuilder<Target>> for Message<Target::Octets>
744where
745 Target: FreezeBuilder,
746{
747 fn from(src: QuestionBuilder<Target>) -> Self {
748 src.into_message()
749 }
750}
751
752//--- Deref, DerefMut, AsRef, and AsMut
753
754impl<Target> Deref for QuestionBuilder<Target> {
755 type Target = MessageBuilder<Target>;
756
757 fn deref(&self) -> &Self::Target {
758 &self.builder
759 }
760}
761
762impl<Target> DerefMut for QuestionBuilder<Target> {
763 fn deref_mut(&mut self) -> &mut Self::Target {
764 &mut self.builder
765 }
766}
767
768impl<Target> AsRef<MessageBuilder<Target>> for QuestionBuilder<Target> {
769 fn as_ref(&self) -> &MessageBuilder<Target> {
770 self.as_builder()
771 }
772}
773
774impl<Target> AsMut<MessageBuilder<Target>> for QuestionBuilder<Target> {
775 fn as_mut(&mut self) -> &mut MessageBuilder<Target> {
776 self.as_builder_mut()
777 }
778}
779
780impl<Target> AsRef<Target> for QuestionBuilder<Target> {
781 fn as_ref(&self) -> &Target {
782 self.as_target()
783 }
784}
785
786impl<Target: AsRef<[u8]>> AsRef<[u8]> for QuestionBuilder<Target> {
787 fn as_ref(&self) -> &[u8] {
788 self.as_slice()
789 }
790}
791
792//------------ AnswerBuilder -------------------------------------------------
793
794/// Builds the answer section of a DNS message.
795///
796/// A value of this type can be acquired by calling the `answer` method on
797/// any other builder type. See the [module documentation] for an overview of
798/// how to build a message.
799///
800/// You can push records to the end of the answer section via the [`push`]
801/// method. It accepts various things that represent resource records: record
802/// values and references, tuples of an owner domain name, a class, TTL, and
803/// record data, as well as tuples of just the owner, TTL, and data, assuming
804/// the class of IN.
805///
806/// Once you are finished building the answer section, you can progress to
807/// the authority section via the [`authority`] method or finish the message
808/// via [`finish`]. Additionally, conversions to all other builder types are
809/// available as well.
810///
811/// [`authority`]: #method.authority
812/// [`finish`]: #method.finish
813/// [`push`]: #method.push
814/// [module documentation]: index.html
815#[derive(Clone, Debug)]
816pub struct AnswerBuilder<Target> {
817 /// The message builder we work on.
818 builder: MessageBuilder<Target>,
819
820 /// The index in the octets builder where the answer section starts.
821 start: usize,
822}
823
824impl<Target: Composer> AnswerBuilder<Target> {
825 /// Creates a new answer builder from an underlying message builder.
826 ///
827 /// Assumes that all three record sections are empty.
828 #[must_use]
829 fn new(builder: MessageBuilder<Target>) -> Self {
830 AnswerBuilder {
831 start: builder.target.as_ref().len(),
832 builder,
833 }
834 }
835}
836
837impl<Target> AnswerBuilder<Target> {
838 #[must_use]
839 pub fn into_target(self) -> Target {
840 self.builder.target
841 }
842}
843
844impl<Target: Composer> AnswerBuilder<Target> {
845 /// Appends a record to the answer section.
846 ///
847 /// This methods accepts anything that implements the [`ComposeRecord`]
848 /// trait. Apart from record values and references, this are tuples of
849 /// the owner domain name, optionally the class (which is taken to be IN
850 /// if missing), the TTL, and record data.
851 ///
852 /// In other words, you can do the following things:
853 ///
854 #[cfg_attr(feature = "std", doc = "```")]
855 #[cfg_attr(not(feature = "std"), doc = "```ignore")]
856 /// use domain::base::{Name, MessageBuilder, Record, Rtype, Ttl};
857 /// use domain::base::iana::Class;
858 /// use domain::rdata::A;
859 ///
860 /// let mut msg = MessageBuilder::new_vec().answer();
861 /// let record = Record::new(
862 /// Name::root_ref(), Class::IN, Ttl::from_secs(86400), A::from_octets(192, 0, 2, 1)
863 /// );
864 /// msg.push(&record).unwrap();
865 /// msg.push(record).unwrap();
866 /// msg.push(
867 /// (Name::root_ref(), Class::IN, 86400, A::from_octets(192, 0, 2, 1))
868 /// ).unwrap();
869 /// msg.push(
870 /// (Name::root_ref(), 86400, A::from_octets(192, 0, 2, 1))
871 /// ).unwrap();
872 /// ```
873 ///
874 pub fn push(
875 &mut self,
876 record: impl ComposeRecord,
877 ) -> Result<(), PushError> {
878 self.builder.push(
879 |target| record.compose_record(target).map_err(Into::into),
880 |counts| counts.inc_ancount(),
881 )
882 }
883
884 /// Appends a record to the answer section without consuming it.
885 ///
886 /// See [`push`][Self::push].
887 pub fn push_ref(
888 &mut self,
889 record: &impl ComposeRecord,
890 ) -> Result<(), PushError> {
891 self.builder.push(
892 |target| record.compose_record(target).map_err(Into::into),
893 |counts| counts.inc_ancount(),
894 )
895 }
896}
897
898/// # Conversions
899///
900/// Additional conversion are available via the `Deref` implementation.
901impl<Target: Composer> AnswerBuilder<Target> {
902 /// Rewinds to an empty answer section.
903 ///
904 /// All previously added answers will be lost.
905 pub fn rewind(&mut self) {
906 self.builder.target.truncate(self.start);
907 self.counts_mut().set_ancount(0);
908 }
909
910 /// Converts the answer builder into a message builder.
911 ///
912 /// All questions and answers will be dropped and all sections will be
913 /// empty.
914 pub fn builder(self) -> MessageBuilder<Target> {
915 self.question().builder()
916 }
917
918 /// Converts the answer builder into a question builder.
919 ///
920 /// All answers will be dropped. All previously added questions will,
921 /// however, remain.
922 pub fn question(mut self) -> QuestionBuilder<Target> {
923 self.rewind();
924 QuestionBuilder::new(self.builder)
925 }
926}
927
928impl<Target: Composer> AnswerBuilder<Target> {
929 /// Converts the answer builder into an answer builder.
930 ///
931 /// This doesn’t do anything, really.
932 pub fn answer(self) -> AnswerBuilder<Target> {
933 self
934 }
935
936 /// Converts the answer builder into an authority builder.
937 pub fn authority(self) -> AuthorityBuilder<Target> {
938 AuthorityBuilder::new(self)
939 }
940
941 /// Converts the answer builder into an additional builder.
942 ///
943 /// This will leave the authority section empty.
944 pub fn additional(self) -> AdditionalBuilder<Target> {
945 self.authority().additional()
946 }
947
948 /// Converts the answer builder into the underlying octets builder.
949 ///
950 /// This will leave the authority and additional sections empty.
951 pub fn finish(self) -> Target {
952 self.builder.finish()
953 }
954}
955
956impl<Target: FreezeBuilder> AnswerBuilder<Target> {
957 /// Converts the answer builder into the final message.
958 ///
959 /// The method will return a message atop whatever octets sequence the
960 /// builder’s octets builder converts into.
961 pub fn into_message(self) -> Message<Target::Octets> {
962 self.builder.into_message()
963 }
964}
965
966impl<Target> AnswerBuilder<Target> {
967 /// Returns a reference to the underlying message builder.
968 pub fn as_builder(&self) -> &MessageBuilder<Target> {
969 &self.builder
970 }
971
972 /// Returns a mutable reference to the underlying message builder.
973 pub fn as_builder_mut(&mut self) -> &mut MessageBuilder<Target> {
974 &mut self.builder
975 }
976}
977
978//--- From
979
980impl<Target> From<MessageBuilder<Target>> for AnswerBuilder<Target>
981where
982 Target: Composer,
983{
984 fn from(src: MessageBuilder<Target>) -> Self {
985 src.answer()
986 }
987}
988
989impl<Target> From<QuestionBuilder<Target>> for AnswerBuilder<Target>
990where
991 Target: Composer,
992{
993 fn from(src: QuestionBuilder<Target>) -> Self {
994 src.answer()
995 }
996}
997
998impl<Target> From<AuthorityBuilder<Target>> for AnswerBuilder<Target>
999where
1000 Target: Composer,
1001{
1002 fn from(src: AuthorityBuilder<Target>) -> Self {
1003 src.answer()
1004 }
1005}
1006
1007impl<Target> From<AdditionalBuilder<Target>> for AnswerBuilder<Target>
1008where
1009 Target: Composer,
1010{
1011 fn from(src: AdditionalBuilder<Target>) -> Self {
1012 src.answer()
1013 }
1014}
1015
1016impl<Target> From<AnswerBuilder<Target>> for Message<Target::Octets>
1017where
1018 Target: FreezeBuilder,
1019{
1020 fn from(src: AnswerBuilder<Target>) -> Self {
1021 src.into_message()
1022 }
1023}
1024
1025//--- Deref, DerefMut, AsRef, and AsMut
1026
1027impl<Target> Deref for AnswerBuilder<Target> {
1028 type Target = MessageBuilder<Target>;
1029
1030 fn deref(&self) -> &Self::Target {
1031 &self.builder
1032 }
1033}
1034
1035impl<Target> DerefMut for AnswerBuilder<Target> {
1036 fn deref_mut(&mut self) -> &mut Self::Target {
1037 &mut self.builder
1038 }
1039}
1040
1041impl<Target> AsRef<MessageBuilder<Target>> for AnswerBuilder<Target> {
1042 fn as_ref(&self) -> &MessageBuilder<Target> {
1043 self.as_builder()
1044 }
1045}
1046
1047impl<Target> AsMut<MessageBuilder<Target>> for AnswerBuilder<Target> {
1048 fn as_mut(&mut self) -> &mut MessageBuilder<Target> {
1049 self.as_builder_mut()
1050 }
1051}
1052
1053impl<Target> AsRef<Target> for AnswerBuilder<Target> {
1054 fn as_ref(&self) -> &Target {
1055 self.as_target()
1056 }
1057}
1058
1059impl<Target: AsRef<[u8]>> AsRef<[u8]> for AnswerBuilder<Target> {
1060 fn as_ref(&self) -> &[u8] {
1061 self.as_slice()
1062 }
1063}
1064
1065//------------ AuthorityBuilder ----------------------------------------------
1066
1067/// Builds the authority section of a DNS message.
1068///
1069/// A value of this type can be acquired by calling the `authority` method on
1070/// any other builder type. See the [module documentation] for an overview of
1071/// how to build a message.
1072///
1073/// You can push records to the end of the authority section via the [`push`]
1074/// method. It accepts various things that represent resource records: record
1075/// values and references, tuples of an owner domain name, a class, TTL, and
1076/// record data, as well as tuples of just the owner, TTL, and data, assuming
1077/// the class of IN.
1078///
1079/// Once you are finished building the authority section, you can progress to
1080/// the additional section via the [`additional`] method or finish the message
1081/// via [`finish`]. Additionally, conversions to all other builder types are
1082/// available as well.
1083///
1084/// [`additional`]: #method.additional
1085/// [`finish`]: #method.finish
1086/// [`push`]: #method.push
1087/// [module documentation]: index.html
1088#[derive(Clone, Debug)]
1089pub struct AuthorityBuilder<Target> {
1090 /// The message builder we work on.
1091 answer: AnswerBuilder<Target>,
1092
1093 /// The index in the octets builder where the authority section starts.
1094 start: usize,
1095}
1096
1097impl<Target: Composer> AuthorityBuilder<Target> {
1098 /// Creates a new authority builder from an answer builder.
1099 ///
1100 /// Assumes that the authority and additional sections are empty.
1101 fn new(answer: AnswerBuilder<Target>) -> Self {
1102 AuthorityBuilder {
1103 start: answer.as_target().as_ref().len(),
1104 answer,
1105 }
1106 }
1107}
1108
1109impl<Target: Composer> AuthorityBuilder<Target> {
1110 /// Appends a record to the authority section.
1111 ///
1112 /// This methods accepts anything that implements the [`ComposeRecord`] trait.
1113 /// Apart from record values and references, this are tuples of the owner
1114 /// domain name, optionally the class (which is taken to be IN if
1115 /// missing), the TTL, and record data.
1116 ///
1117 /// In other words, you can do the following things:
1118 ///
1119 #[cfg_attr(feature = "std", doc = "```")]
1120 #[cfg_attr(not(feature = "std"), doc = "```ignore")]
1121 /// use domain::base::{Name, MessageBuilder, Record, Rtype, Ttl};
1122 /// use domain::base::iana::Class;
1123 /// use domain::rdata::A;
1124 ///
1125 /// let mut msg = MessageBuilder::new_vec().authority();
1126 /// let record = Record::new(
1127 /// Name::root_ref(), Class::IN, Ttl::from_secs(86400),
1128 /// A::from_octets(192, 0, 2, 1)
1129 /// );
1130 /// msg.push(&record).unwrap();
1131 /// msg.push(record).unwrap();
1132 /// msg.push(
1133 /// (Name::root_ref(), Class::IN, 86400, A::from_octets(192, 0, 2, 1))
1134 /// ).unwrap();
1135 /// msg.push(
1136 /// (Name::root_ref(), 86400, A::from_octets(192, 0, 2, 1))
1137 /// ).unwrap();
1138 /// ```
1139 pub fn push(
1140 &mut self,
1141 record: impl ComposeRecord,
1142 ) -> Result<(), PushError> {
1143 self.answer.builder.push(
1144 |target| record.compose_record(target).map_err(Into::into),
1145 |counts| counts.inc_nscount(),
1146 )
1147 }
1148}
1149
1150/// # Conversions
1151///
1152/// Additional conversion methods are available via the `Deref`
1153/// implementation.
1154impl<Target: Composer> AuthorityBuilder<Target> {
1155 /// Rewinds to an empty authority section.
1156 ///
1157 /// All previously added authority records will be lost.
1158 pub fn rewind(&mut self) {
1159 self.answer.as_target_mut().truncate(self.start);
1160 self.counts_mut().set_nscount(0);
1161 }
1162
1163 /// Converts the authority builder into a message builder.
1164 ///
1165 /// All questions, answer and authority records will be dropped and all
1166 /// sections will be empty.
1167 pub fn builder(self) -> MessageBuilder<Target> {
1168 self.question().builder()
1169 }
1170
1171 /// Converts the authority builder into a question builder.
1172 ///
1173 /// All authority and answer records will be dropped. All previously added
1174 /// questions will, however, remain.
1175 pub fn question(self) -> QuestionBuilder<Target> {
1176 self.answer().question()
1177 }
1178
1179 /// Converts the authority builder into an answer builder.
1180 ///
1181 /// All authority records will be dropped. All previously added questions
1182 /// and answer records will, however, remain.
1183 pub fn answer(mut self) -> AnswerBuilder<Target> {
1184 self.rewind();
1185 self.answer
1186 }
1187
1188 /// Converts the authority builder into an authority builder.
1189 ///
1190 /// This is identical to the identity function.
1191 pub fn authority(self) -> AuthorityBuilder<Target> {
1192 self
1193 }
1194
1195 /// Converts the authority builder into an additional builder.
1196 pub fn additional(self) -> AdditionalBuilder<Target> {
1197 AdditionalBuilder::new(self)
1198 }
1199
1200 /// Converts the authority builder into the underlying octets builder.
1201 ///
1202 /// This will leave the additional section empty.
1203 pub fn finish(self) -> Target {
1204 self.answer.finish()
1205 }
1206}
1207
1208impl<Target: FreezeBuilder> AuthorityBuilder<Target> {
1209 /// Converts the authority builder into the final message.
1210 ///
1211 /// The method will return a message atop whatever octets sequence the
1212 /// builder’s octets builder converts into.
1213 pub fn into_message(self) -> Message<Target::Octets> {
1214 self.answer.into_message()
1215 }
1216}
1217
1218impl<Target> AuthorityBuilder<Target> {
1219 /// Returns a reference to the underlying message builder.
1220 pub fn as_builder(&self) -> &MessageBuilder<Target> {
1221 self.answer.as_builder()
1222 }
1223
1224 /// Returns a mutable reference to the underlying message builder.
1225 pub fn as_builder_mut(&mut self) -> &mut MessageBuilder<Target> {
1226 self.answer.as_builder_mut()
1227 }
1228}
1229
1230//--- From
1231
1232impl<Target> From<MessageBuilder<Target>> for AuthorityBuilder<Target>
1233where
1234 Target: Composer,
1235{
1236 fn from(src: MessageBuilder<Target>) -> Self {
1237 src.authority()
1238 }
1239}
1240
1241impl<Target> From<QuestionBuilder<Target>> for AuthorityBuilder<Target>
1242where
1243 Target: Composer,
1244{
1245 fn from(src: QuestionBuilder<Target>) -> Self {
1246 src.authority()
1247 }
1248}
1249
1250impl<Target> From<AnswerBuilder<Target>> for AuthorityBuilder<Target>
1251where
1252 Target: Composer,
1253{
1254 fn from(src: AnswerBuilder<Target>) -> Self {
1255 src.authority()
1256 }
1257}
1258
1259impl<Target> From<AdditionalBuilder<Target>> for AuthorityBuilder<Target>
1260where
1261 Target: Composer,
1262{
1263 fn from(src: AdditionalBuilder<Target>) -> Self {
1264 src.authority()
1265 }
1266}
1267
1268impl<Target> From<AuthorityBuilder<Target>> for Message<Target::Octets>
1269where
1270 Target: FreezeBuilder,
1271{
1272 fn from(src: AuthorityBuilder<Target>) -> Self {
1273 src.into_message()
1274 }
1275}
1276
1277//--- Deref, DerefMut, AsRef, and AsMut
1278
1279impl<Target> Deref for AuthorityBuilder<Target> {
1280 type Target = MessageBuilder<Target>;
1281
1282 fn deref(&self) -> &Self::Target {
1283 self.answer.deref()
1284 }
1285}
1286
1287impl<Target> DerefMut for AuthorityBuilder<Target> {
1288 fn deref_mut(&mut self) -> &mut Self::Target {
1289 self.answer.deref_mut()
1290 }
1291}
1292
1293impl<Target> AsRef<MessageBuilder<Target>> for AuthorityBuilder<Target> {
1294 fn as_ref(&self) -> &MessageBuilder<Target> {
1295 self.as_builder()
1296 }
1297}
1298
1299impl<Target> AsMut<MessageBuilder<Target>> for AuthorityBuilder<Target> {
1300 fn as_mut(&mut self) -> &mut MessageBuilder<Target> {
1301 self.as_builder_mut()
1302 }
1303}
1304
1305impl<Target> AsRef<Target> for AuthorityBuilder<Target> {
1306 fn as_ref(&self) -> &Target {
1307 self.as_target()
1308 }
1309}
1310
1311impl<Target: AsRef<[u8]>> AsRef<[u8]> for AuthorityBuilder<Target> {
1312 fn as_ref(&self) -> &[u8] {
1313 self.as_slice()
1314 }
1315}
1316
1317//------------ AdditionalBuilder ---------------------------------------------
1318
1319/// Builds the additional section of a DNS message.
1320///
1321/// A value of this type can be acquired by calling the `additional` method on
1322/// any other builder type. See the [module documentation] for an overview of
1323/// how to build a message.
1324///
1325/// You can push records to the end of the additional section via the [`push`]
1326/// method. It accepts various things that represent resource records: record
1327/// values and references, tuples of an owner domain name, a class, TTL, and
1328/// record data, as well as tuples of just the owner, TTL, and data, assuming
1329/// the class of IN.
1330///
1331/// A special method exists to make adding an OPT record to the section
1332/// easier. The [`opt`] method creates an [`OptBuilder`] and passes it to a
1333/// closure. This way, you can add and remove OPT records from additional
1334/// builders that are part of another type and cannot be traded in easily.
1335///
1336/// Once you are finished building the additional section, you can finish the
1337/// message via [`finish`]. Additionally, conversions to all other builder
1338/// types are available as well.
1339///
1340/// [`finish`]: #method.finish
1341/// [`opt`]: #method.opt
1342/// [`push`]: #method.push
1343/// [`OptBuilder`]: struct.OptBuilder.html
1344/// [module documentation]: index.html
1345#[derive(Clone, Debug)]
1346pub struct AdditionalBuilder<Target> {
1347 /// The message builder we work on.
1348 authority: AuthorityBuilder<Target>,
1349
1350 /// The index in the octets builder where the additional section starts.
1351 start: usize,
1352}
1353
1354impl<Target: Composer> AdditionalBuilder<Target> {
1355 /// Creates a new additional builder from an authority builder.
1356 ///
1357 /// Assumes that the additional section is currently empty.
1358 fn new(authority: AuthorityBuilder<Target>) -> Self {
1359 AdditionalBuilder {
1360 start: authority.as_target().as_ref().len(),
1361 authority,
1362 }
1363 }
1364}
1365
1366impl<Target: Composer> AdditionalBuilder<Target> {
1367 /// Appends a record to the additional section.
1368 ///
1369 /// This methods accepts anything that implements the
1370 /// [`ComposeRecord`] trait.
1371 /// Apart from record values and references, this are tuples of the owner
1372 /// domain name, optionally the class (which is taken to be IN if
1373 /// missing), the TTL, and record data.
1374 ///
1375 /// In other words, you can do the following things:
1376 ///
1377 #[cfg_attr(feature = "std", doc = "```")]
1378 #[cfg_attr(not(feature = "std"), doc = "```ignore")]
1379 /// use domain::base::{Name, MessageBuilder, Record, Rtype, Ttl};
1380 /// use domain::base::iana::Class;
1381 /// use domain::rdata::A;
1382 ///
1383 /// let mut msg = MessageBuilder::new_vec().additional();
1384 /// let record = Record::new(
1385 /// Name::root_ref(), Class::IN, Ttl::from_secs(86400), A::from_octets(192, 0, 2, 1)
1386 /// );
1387 /// msg.push(&record).unwrap();
1388 /// msg.push(record).unwrap();
1389 /// msg.push(
1390 /// (Name::root_ref(), Class::IN, 86400, A::from_octets(192, 0, 2, 1))
1391 /// ).unwrap();
1392 /// msg.push(
1393 /// (Name::root_ref(), 86400, A::from_octets(192, 0, 2, 1))
1394 /// ).unwrap();
1395 /// ```
1396 pub fn push(
1397 &mut self,
1398 record: impl ComposeRecord,
1399 ) -> Result<(), PushError> {
1400 self.authority.answer.builder.push(
1401 |target| record.compose_record(target).map_err(Into::into),
1402 |counts| counts.inc_arcount(),
1403 )
1404 }
1405}
1406
1407impl<Target: Composer> AdditionalBuilder<Target> {
1408 /// Appends and builds an OPT record.
1409 ///
1410 /// The actual building of the record is handled by a closure that
1411 /// receives an [`OptBuilder`] which can both change the header of the
1412 /// record and add options.
1413 ///
1414 /// The method will return whatever the closure returns. In addition, it
1415 /// will return an error if it failed to add the header of the OPT record.
1416 ///
1417 /// [`OptBuilder`]: struct.OptBuilder.html
1418 pub fn opt<F>(&mut self, op: F) -> Result<(), PushError>
1419 where
1420 F: FnOnce(
1421 &mut OptBuilder<'_, Target>,
1422 ) -> Result<(), Target::AppendError>,
1423 {
1424 self.authority.answer.builder.push(
1425 |target| OptBuilder::new(target)?.build(op),
1426 |counts| counts.inc_arcount(),
1427 )
1428 }
1429}
1430
1431/// # Conversions
1432///
1433/// Additional conversion methods are available via the `Deref`
1434/// implementation.
1435impl<Target: Composer> AdditionalBuilder<Target> {
1436 /// Rewinds to an empty additional section.
1437 ///
1438 /// All previously added additional records will be lost.
1439 pub fn rewind(&mut self) {
1440 self.authority.as_target_mut().truncate(self.start);
1441 self.counts_mut().set_arcount(0);
1442 }
1443
1444 /// Converts the additional builder into a message builder.
1445 ///
1446 /// All questions and records will be dropped and all sections will be
1447 /// empty.
1448 pub fn builder(self) -> MessageBuilder<Target> {
1449 self.question().builder()
1450 }
1451
1452 /// Converts the additional builder into a question builder.
1453 ///
1454 /// All answer, authority, and additional records will be dropped. All
1455 /// previously added questions will, however, remain.
1456 pub fn question(self) -> QuestionBuilder<Target> {
1457 self.answer().question()
1458 }
1459
1460 /// Converts the additional builder into an answer builder.
1461 ///
1462 /// All authority and additional records will be dropped. All questions
1463 /// and answer records will remain.
1464 pub fn answer(self) -> AnswerBuilder<Target> {
1465 self.authority().answer()
1466 }
1467
1468 /// Converts the additional builder into an authority builder.
1469 ///
1470 /// All additional records will be dropped. All questions, answer, and
1471 /// authority records will remain.
1472 pub fn authority(mut self) -> AuthorityBuilder<Target> {
1473 self.rewind();
1474 self.authority
1475 }
1476
1477 /// Converts the additional builder into an additional builder.
1478 ///
1479 /// In other words, does absolutely nothing.
1480 pub fn additional(self) -> AdditionalBuilder<Target> {
1481 self
1482 }
1483
1484 /// Converts the additional builder into the underlying octets builder.
1485 pub fn finish(self) -> Target {
1486 self.authority.finish()
1487 }
1488}
1489
1490impl<Target: FreezeBuilder> AdditionalBuilder<Target> {
1491 /// Converts the additional builder into the final message.
1492 ///
1493 /// The method will return a message atop whatever octets sequence the
1494 /// builder’s octets builder converts into.
1495 pub fn into_message(self) -> Message<Target::Octets> {
1496 self.authority.into_message()
1497 }
1498}
1499
1500impl<Target> AdditionalBuilder<Target> {
1501 /// Returns a reference to the underlying message builder.
1502 pub fn as_builder(&self) -> &MessageBuilder<Target> {
1503 self.authority.as_builder()
1504 }
1505
1506 /// Returns a mutable reference to the underlying message builder.
1507 pub fn as_builder_mut(&mut self) -> &mut MessageBuilder<Target> {
1508 self.authority.as_builder_mut()
1509 }
1510}
1511
1512//--- From
1513
1514impl<Target> From<MessageBuilder<Target>> for AdditionalBuilder<Target>
1515where
1516 Target: Composer,
1517{
1518 fn from(src: MessageBuilder<Target>) -> Self {
1519 src.additional()
1520 }
1521}
1522
1523impl<Target> From<QuestionBuilder<Target>> for AdditionalBuilder<Target>
1524where
1525 Target: Composer,
1526{
1527 fn from(src: QuestionBuilder<Target>) -> Self {
1528 src.additional()
1529 }
1530}
1531
1532impl<Target> From<AnswerBuilder<Target>> for AdditionalBuilder<Target>
1533where
1534 Target: Composer,
1535{
1536 fn from(src: AnswerBuilder<Target>) -> Self {
1537 src.additional()
1538 }
1539}
1540
1541impl<Target> From<AuthorityBuilder<Target>> for AdditionalBuilder<Target>
1542where
1543 Target: Composer,
1544{
1545 fn from(src: AuthorityBuilder<Target>) -> Self {
1546 src.additional()
1547 }
1548}
1549
1550impl<Target> From<AdditionalBuilder<Target>> for Message<Target::Octets>
1551where
1552 Target: FreezeBuilder,
1553{
1554 fn from(src: AdditionalBuilder<Target>) -> Self {
1555 src.into_message()
1556 }
1557}
1558
1559//--- Deref, DerefMut, AsRef, and AsMut
1560
1561impl<Target> Deref for AdditionalBuilder<Target> {
1562 type Target = MessageBuilder<Target>;
1563
1564 fn deref(&self) -> &Self::Target {
1565 self.as_builder()
1566 }
1567}
1568
1569impl<Target> DerefMut for AdditionalBuilder<Target> {
1570 fn deref_mut(&mut self) -> &mut Self::Target {
1571 self.as_builder_mut()
1572 }
1573}
1574
1575impl<Target> AsRef<MessageBuilder<Target>> for AdditionalBuilder<Target> {
1576 fn as_ref(&self) -> &MessageBuilder<Target> {
1577 self.as_builder()
1578 }
1579}
1580
1581impl<Target> AsMut<MessageBuilder<Target>> for AdditionalBuilder<Target> {
1582 fn as_mut(&mut self) -> &mut MessageBuilder<Target> {
1583 self.as_builder_mut()
1584 }
1585}
1586
1587impl<Target> AsRef<Target> for AdditionalBuilder<Target> {
1588 fn as_ref(&self) -> &Target {
1589 self.as_target()
1590 }
1591}
1592
1593impl<Target: AsRef<[u8]>> AsRef<[u8]> for AdditionalBuilder<Target> {
1594 fn as_ref(&self) -> &[u8] {
1595 self.as_slice()
1596 }
1597}
1598
1599//------------ RecordSectionBuilder ------------------------------------------
1600
1601/// A section that can have records pushed to it.
1602///
1603/// This trait exists to make it possible to write code that works for all
1604/// three record sections. It basically just duplicates the `push` method of
1605/// these sections.
1606///
1607/// (This method is available on the sections as a method, too, so you don’t
1608/// need to import the `RecordSectionBuilder` all the time.)
1609pub trait RecordSectionBuilder<Target: Composer> {
1610 /// Appends a record to a record section.
1611 ///
1612 /// The methods accepts anything that implements the [`ComposeRecord`] trait.
1613 /// Apart from record values and references, this are tuples of the owner
1614 /// domain name, optionally the class (which is taken to be IN if
1615 /// missing), the TTL, and record data.
1616 fn push(&mut self, record: impl ComposeRecord) -> Result<(), PushError>;
1617}
1618
1619impl<Target> RecordSectionBuilder<Target> for AnswerBuilder<Target>
1620where
1621 Target: Composer,
1622{
1623 fn push(&mut self, record: impl ComposeRecord) -> Result<(), PushError> {
1624 Self::push(self, record)
1625 }
1626}
1627
1628impl<Target: Composer> RecordSectionBuilder<Target>
1629 for AuthorityBuilder<Target>
1630{
1631 fn push(&mut self, record: impl ComposeRecord) -> Result<(), PushError> {
1632 Self::push(self, record)
1633 }
1634}
1635
1636impl<Target> RecordSectionBuilder<Target> for AdditionalBuilder<Target>
1637where
1638 Target: Composer,
1639{
1640 fn push(&mut self, record: impl ComposeRecord) -> Result<(), PushError> {
1641 Self::push(self, record)
1642 }
1643}
1644
1645//------------ OptBuilder ----------------------------------------------------
1646
1647/// Builds an OPT record.
1648///
1649/// A mutable reference of this type is passed to the closure given to
1650/// [`AdditionalBuilder::opt`] allowing this closure to manipulate both the
1651/// header values of the record and push options to the record data.
1652///
1653/// [`AdditionalBuilder::opt`]: struct.AdditonalBuilder.html#method.opt
1654pub struct OptBuilder<'a, Target: ?Sized> {
1655 start: usize,
1656 target: &'a mut Target,
1657}
1658
1659impl<'a, Target: Composer + ?Sized> OptBuilder<'a, Target> {
1660 /// Creates a new opt builder atop an additional builder.
1661 fn new(target: &'a mut Target) -> Result<Self, ShortBuf> {
1662 let start = target.as_ref().len();
1663 OptHeader::default().compose(target).map_err(Into::into)?;
1664 Ok(OptBuilder { start, target })
1665 }
1666
1667 fn build<F>(&mut self, op: F) -> Result<(), ShortBuf>
1668 where
1669 F: FnOnce(&mut Self) -> Result<(), Target::AppendError>,
1670 {
1671 self.target.append_slice(&[0; 2]).map_err(Into::into)?;
1672 let pos = self.target.as_ref().len();
1673 match op(self) {
1674 Ok(_) => match u16::try_from(self.target.as_ref().len() - pos) {
1675 Ok(len) => {
1676 self.target.as_mut()[pos - 2..pos]
1677 .copy_from_slice(&(len).to_be_bytes());
1678 Ok(())
1679 }
1680 Err(_) => {
1681 self.target.truncate(pos);
1682 Err(ShortBuf)
1683 }
1684 },
1685 Err(_) => {
1686 self.target.truncate(pos);
1687 Err(ShortBuf)
1688 }
1689 }
1690 }
1691
1692 /// Replaces the contents of this [`OptBuilder`] with the given
1693 /// [`OptRecord`]`.
1694 pub fn clone_from<T: AsRef<[u8]>>(
1695 &mut self,
1696 source: &OptRecord<T>,
1697 ) -> Result<(), Target::AppendError> {
1698 self.target.truncate(self.start);
1699 source.as_record().compose(self.target)
1700 }
1701
1702 /// Appends an option to the OPT record.
1703 pub fn push<Opt: ComposeOptData + ?Sized>(
1704 &mut self,
1705 opt: &Opt,
1706 ) -> Result<(), Target::AppendError> {
1707 self.push_raw_option(opt.code(), opt.compose_len(), |target| {
1708 opt.compose_option(target)
1709 })
1710 }
1711
1712 /// Appends a raw option to the OPT record.
1713 ///
1714 /// The method will append an option with the given option code. The data
1715 /// of the option will be written via the closure `op`.
1716 pub fn push_raw_option<F>(
1717 &mut self,
1718 code: OptionCode,
1719 option_len: u16,
1720 op: F,
1721 ) -> Result<(), Target::AppendError>
1722 where
1723 F: FnOnce(&mut Target) -> Result<(), Target::AppendError>,
1724 {
1725 code.compose(self.target)?;
1726 option_len.compose(self.target)?;
1727 op(self.target)
1728 }
1729
1730 /// Returns the current UDP payload size field of the OPT record.
1731 ///
1732 /// This field contains the largest UDP datagram the sender can accept.
1733 /// This is not the path MTU but really what the sender can work with
1734 /// internally.
1735 #[must_use]
1736 pub fn udp_payload_size(&self) -> u16 {
1737 self.opt_header().udp_payload_size()
1738 }
1739
1740 /// Sets the UDP payload size field of the OPT record.
1741 pub fn set_udp_payload_size(&mut self, value: u16) {
1742 self.opt_header_mut().set_udp_payload_size(value)
1743 }
1744
1745 /// Returns the extended rcode of the message.
1746 ///
1747 /// The method assembles the rcode both from the message header and the
1748 /// OPT header.
1749 #[must_use]
1750 pub fn rcode(&self) -> OptRcode {
1751 self.opt_header()
1752 .rcode(*Header::for_message_slice(self.target.as_ref()))
1753 }
1754
1755 /// Sets the extended rcode of the message.
1756 //
1757 /// The method will update both the message header and the OPT header.
1758 pub fn set_rcode(&mut self, rcode: OptRcode) {
1759 Header::for_message_slice_mut(self.target.as_mut())
1760 .set_rcode(rcode.rcode());
1761 self.opt_header_mut().set_rcode(rcode)
1762 }
1763
1764 /// Returns the EDNS version of the OPT header.
1765 ///
1766 /// Only EDNS version 0 is currently defined.
1767 #[must_use]
1768 pub fn version(&self) -> u8 {
1769 self.opt_header().version()
1770 }
1771
1772 /// Sets the EDNS version of the OPT header.
1773 pub fn set_version(&mut self, version: u8) {
1774 self.opt_header_mut().set_version(version)
1775 }
1776
1777 /// Returns the value of the DNSSEC OK (DO) bit.
1778 ///
1779 /// By setting this bit, a resolver indicates that it is interested in
1780 /// also receiving the DNSSEC-related resource records necessary to
1781 /// validate an answer. The bit and the related procedures are defined in
1782 /// [RFC 3225].
1783 ///
1784 /// [RFC 3225]: https://tools.ietf.org/html/rfc3225
1785 #[must_use]
1786 pub fn dnssec_ok(&self) -> bool {
1787 self.opt_header().dnssec_ok()
1788 }
1789
1790 /// Sets the DNSSEC OK (DO) bit to the given value.
1791 pub fn set_dnssec_ok(&mut self, value: bool) {
1792 self.opt_header_mut().set_dnssec_ok(value)
1793 }
1794
1795 /// Returns a reference to the full OPT header.
1796 fn opt_header(&self) -> &OptHeader {
1797 OptHeader::for_record_slice(&self.target.as_ref()[self.start..])
1798 }
1799
1800 /// Returns a mutual reference to the full OPT header.
1801 fn opt_header_mut(&mut self) -> &mut OptHeader {
1802 let start = self.start;
1803 OptHeader::for_record_slice_mut(&mut self.target.as_mut()[start..])
1804 }
1805
1806 /// Returns a reference to the underlying octets builder.
1807 pub fn as_target(&self) -> &Target {
1808 self.target
1809 }
1810}
1811
1812//------------ StreamTarget --------------------------------------------------
1813
1814/// A builder target for sending messages on stream transports.
1815///
1816/// TODO: Rename this type and adjust the doc comments as it is usable both
1817/// for datagram AND stream transports via [`as_dgram_slice`] and
1818/// [`as_stream_slice`].
1819///
1820/// When messages are sent over stream-oriented transports such as TCP, a DNS
1821/// message is preceded by a 16 bit length value in order to determine the end
1822/// of a message. This type transparently adds this length value as the first
1823/// two octets of an octets builder and itself presents an octets builder
1824/// interface for building the actual message. Whenever data is pushed to that
1825/// builder interface, the type will update the length value.
1826///
1827/// Because the length is 16 bits long, the assembled message can be at most
1828/// 65536 octets long, independently of the maximum length the underlying
1829/// builder allows.
1830///
1831/// [`as_dgram_slice`]: Self::as_dgram_slice
1832/// [`as_stream_slice`]: Self::as_stream_slice
1833#[derive(Clone, Debug, Default)]
1834pub struct StreamTarget<Target> {
1835 /// The underlying octets builder.
1836 target: Target,
1837}
1838
1839impl<Target: Composer> StreamTarget<Target> {
1840 /// Creates a new stream target wrapping an octets builder.
1841 ///
1842 /// The function will truncate the builder back to empty and append the
1843 /// length value. Because of the latter, this can fail if the octets
1844 /// builder doesn’t even have space for that.
1845 pub fn new(mut target: Target) -> Result<Self, Target::AppendError> {
1846 target.truncate(0);
1847 0u16.compose(&mut target)?;
1848 Ok(StreamTarget { target })
1849 }
1850}
1851
1852#[cfg(feature = "std")]
1853impl StreamTarget<Vec<u8>> {
1854 /// Creates a stream target atop an empty `Vec<u8>`.
1855 #[must_use]
1856 pub fn new_vec() -> Self {
1857 infallible(Self::new(Vec::new()))
1858 }
1859}
1860
1861#[cfg(feature = "bytes")]
1862impl StreamTarget<BytesMut> {
1863 /// Creates a stream target atop an empty `Vec<u8>`.
1864 pub fn new_bytes() -> Self {
1865 infallible(Self::new(BytesMut::new()))
1866 }
1867}
1868
1869impl<Target> StreamTarget<Target> {
1870 /// Returns a reference to the underlying octets builder.
1871 pub fn as_target(&self) -> &Target {
1872 &self.target
1873 }
1874
1875 /// Converts the stream target into the underlying octets builder.
1876 ///
1877 /// The returned builder will contain the 16 bit length value with the
1878 /// correct content and the assembled message.
1879 pub fn into_target(self) -> Target {
1880 self.target
1881 }
1882}
1883
1884impl<Target: AsRef<[u8]> + AsMut<[u8]>> StreamTarget<Target> {
1885 /// Updates the length value to the current length of the target.
1886 fn update_shim(&mut self) -> Result<(), ShortBuf> {
1887 match u16::try_from(self.target.as_ref().len() - 2) {
1888 Ok(len) => {
1889 self.target.as_mut()[..2].copy_from_slice(&len.to_be_bytes());
1890 Ok(())
1891 }
1892 Err(_) => Err(ShortBuf),
1893 }
1894 }
1895}
1896
1897impl<Target: AsRef<[u8]>> StreamTarget<Target> {
1898 /// Returns an octets slice of the message for stream transports.
1899 ///
1900 /// The slice will start with the length octets and can be send as is
1901 /// through a stream transport such as TCP.
1902 pub fn as_stream_slice(&self) -> &[u8] {
1903 self.target.as_ref()
1904 }
1905
1906 /// Returns an octets slice of the message for datagram transports.
1907 ///
1908 /// The slice will not contain the length octets but only the actual
1909 /// message itself. This slice can be used for sending via datagram
1910 /// transports such as UDP.
1911 pub fn as_dgram_slice(&self) -> &[u8] {
1912 &self.target.as_ref()[2..]
1913 }
1914}
1915
1916//--- AsRef, AsMut
1917
1918impl<Target: AsRef<[u8]>> AsRef<[u8]> for StreamTarget<Target> {
1919 fn as_ref(&self) -> &[u8] {
1920 &self.target.as_ref()[2..]
1921 }
1922}
1923
1924impl<Target: AsMut<[u8]>> AsMut<[u8]> for StreamTarget<Target> {
1925 fn as_mut(&mut self) -> &mut [u8] {
1926 &mut self.target.as_mut()[2..]
1927 }
1928}
1929
1930//--- OctetsBuilder, Truncate, Composer
1931
1932impl<Target> OctetsBuilder for StreamTarget<Target>
1933where
1934 Target: OctetsBuilder + AsRef<[u8]> + AsMut<[u8]>,
1935 Target::AppendError: Into<ShortBuf>,
1936{
1937 type AppendError = ShortBuf;
1938
1939 fn append_slice(
1940 &mut self,
1941 slice: &[u8],
1942 ) -> Result<(), Self::AppendError> {
1943 self.target.append_slice(slice).map_err(Into::into)?;
1944 self.update_shim()
1945 }
1946}
1947
1948impl<Target: Composer> Truncate for StreamTarget<Target> {
1949 fn truncate(&mut self, len: usize) {
1950 self.target
1951 .truncate(len.checked_add(2).expect("long truncate"));
1952 self.update_shim().expect("truncate grew buffer???")
1953 }
1954}
1955
1956impl<Target> Composer for StreamTarget<Target>
1957where
1958 Target: Composer,
1959 Target::AppendError: Into<ShortBuf>,
1960{
1961 fn append_compressed_name<N: ToName + ?Sized>(
1962 &mut self,
1963 name: &N,
1964 ) -> Result<(), Self::AppendError> {
1965 self.target
1966 .append_compressed_name(name)
1967 .map_err(Into::into)?;
1968 self.update_shim()
1969 }
1970}
1971
1972//------------ StaticCompressor ----------------------------------------------
1973
1974/// A domain name compressor that doesn’t require an allocator.
1975///
1976/// This type wraps around an octets builder and implements domain name
1977/// compression. It does not require an allocator but because of that it
1978/// can only remember the position of up to 24 domain names. This should be
1979/// sufficient for most messages.
1980///
1981/// The position of a domain name is calculated relative to the beginning of
1982/// the underlying octets builder. This means that this builder must represent
1983/// the message only. This means that if you are using the [`StreamTarget`],
1984/// you need to place it inside this type, _not_ the other way around.
1985///
1986/// [`StreamTarget`]: struct.StreamTarget.html
1987#[derive(Clone, Debug)]
1988pub struct StaticCompressor<Target> {
1989 /// The underlying octets builder.
1990 target: Target,
1991
1992 /// The domain names we have encountered so far.
1993 ///
1994 /// The value is the position of the domain name within the message.
1995 entries: [u16; 24],
1996
1997 /// The number of entries in `entries`.
1998 len: usize,
1999}
2000
2001impl<Target> StaticCompressor<Target> {
2002 /// Creates a static compressor from an octets builder.
2003 pub fn new(target: Target) -> Self {
2004 StaticCompressor {
2005 target,
2006 entries: Default::default(),
2007 len: 0,
2008 }
2009 }
2010
2011 /// Returns a reference to the underlying octets builder.
2012 pub fn as_target(&self) -> &Target {
2013 &self.target
2014 }
2015
2016 /// Converts the static compressor into the underlying octets builder.
2017 pub fn into_target(self) -> Target {
2018 self.target
2019 }
2020
2021 /// Returns a reference to the octets slice of the content.
2022 pub fn as_slice(&self) -> &[u8]
2023 where
2024 Target: AsRef<[u8]>,
2025 {
2026 self.target.as_ref()
2027 }
2028
2029 /// Returns a reference to the octets slice of the content.
2030 pub fn as_slice_mut(&mut self) -> &mut [u8]
2031 where
2032 Target: AsMut<[u8]>,
2033 {
2034 self.target.as_mut()
2035 }
2036
2037 /// Returns a known position of a domain name if there is one.
2038 fn get<'a, N: Iterator<Item = &'a Label> + Clone>(
2039 &self,
2040 name: N,
2041 ) -> Option<u16>
2042 where
2043 Target: AsRef<[u8]>,
2044 {
2045 self.entries[..self.len].iter().find_map(|&pos| {
2046 if name
2047 .clone()
2048 .eq(Label::iter_slice(self.target.as_ref(), pos as usize))
2049 {
2050 Some(pos)
2051 } else {
2052 None
2053 }
2054 })
2055 }
2056
2057 /// Inserts the position of a new domain name if possible.
2058 fn insert(&mut self, pos: usize) -> bool {
2059 if pos < 0xc000 && self.len < self.entries.len() {
2060 self.entries[self.len] = pos as u16;
2061 self.len += 1;
2062 true
2063 } else {
2064 false
2065 }
2066 }
2067}
2068
2069//--- AsRef and AsMut
2070
2071impl<Target: AsRef<[u8]>> AsRef<[u8]> for StaticCompressor<Target> {
2072 fn as_ref(&self) -> &[u8] {
2073 self.as_slice()
2074 }
2075}
2076
2077impl<Target: AsMut<[u8]>> AsMut<[u8]> for StaticCompressor<Target> {
2078 fn as_mut(&mut self) -> &mut [u8] {
2079 self.as_slice_mut()
2080 }
2081}
2082
2083//--- OctetsBuilder
2084
2085impl<Target: OctetsBuilder> OctetsBuilder for StaticCompressor<Target> {
2086 type AppendError = Target::AppendError;
2087
2088 fn append_slice(
2089 &mut self,
2090 slice: &[u8],
2091 ) -> Result<(), Self::AppendError> {
2092 self.target.append_slice(slice)
2093 }
2094}
2095
2096impl<Target: Composer> Composer for StaticCompressor<Target> {
2097 fn append_compressed_name<N: ToName + ?Sized>(
2098 &mut self,
2099 name: &N,
2100 ) -> Result<(), Self::AppendError> {
2101 let mut name = name.iter_labels().peekable();
2102
2103 loop {
2104 // If the parent is root, just write that and return.
2105 // Because we do that, there will always be a label left here.
2106 if let Some(label) = name.peek() {
2107 if label.is_root() {
2108 label.compose(self)?;
2109 return Ok(());
2110 }
2111 }
2112
2113 // If we already know this name, append it as a compressed label.
2114 if let Some(pos) = self.get(name.clone()) {
2115 return (pos | 0xC000).compose(self);
2116 }
2117
2118 // So we don’t know the name. Try inserting it into the
2119 // compressor. If we can’t insert anymore, just write out what’s
2120 // left and return.
2121 if !self.insert(self.target.as_ref().len()) {
2122 for label in &mut name {
2123 label.compose(self)?;
2124 }
2125 return Ok(());
2126 }
2127
2128 // Advance to the parent.
2129 let label = name.next().unwrap();
2130 label.compose(self)?;
2131 }
2132 }
2133
2134 fn can_compress(&self) -> bool {
2135 true
2136 }
2137}
2138
2139impl<Target: Truncate> Truncate for StaticCompressor<Target> {
2140 fn truncate(&mut self, len: usize) {
2141 self.target.truncate(len);
2142 if len < 0xC000 {
2143 let len = len as u16;
2144 for i in 0..self.len {
2145 if self.entries[i] >= len {
2146 self.len = i;
2147 break;
2148 }
2149 }
2150 }
2151 }
2152}
2153
2154impl<Target: FreezeBuilder> FreezeBuilder for StaticCompressor<Target> {
2155 type Octets = Target::Octets;
2156
2157 fn freeze(self) -> Self::Octets {
2158 self.target.freeze()
2159 }
2160}
2161
2162//------------ TreeCompressor ------------------------------------------------
2163
2164/// A domain name compressor that uses a tree.
2165///
2166/// This type wraps around an octets builder and implements domain name
2167/// compression for it. It stores the position of any domain name it has seen
2168/// in a binary tree.
2169///
2170/// The position of a domain name is calculated relative to the beginning of
2171/// the underlying octets builder. This means that this builder must represent
2172/// the message only. This means that if you are using the [`StreamTarget`],
2173/// you need to place it inside this type, _not_ the other way around.
2174///
2175/// [`StreamTarget`]: struct.StreamTarget.html
2176#[cfg(feature = "std")]
2177#[derive(Clone, Debug)]
2178pub struct TreeCompressor<Target> {
2179 /// The underlying octetsbuilder.
2180 target: Target,
2181
2182 /// The topmost node of our tree.
2183 start: Node,
2184}
2185
2186/// A node in our tree.
2187///
2188/// The tree is a bit odd. It follows the labels of the domain names from the
2189/// root towards the left. The root node is for the root label. It contains a
2190/// map that maps all the labels encountered to the immediate left of the
2191/// name traced by this path through the tree to a node for the name resulting
2192/// by adding this label to the name constructed so far.
2193///
2194/// Each node also contains the position of that name in the message.
2195#[cfg(feature = "std")]
2196#[derive(Clone, Debug, Default)]
2197struct Node {
2198 /// The labels immediately to the left of this name and their nodes.
2199 parents: HashMap<Array<64>, Self>,
2200
2201 /// The position of this name in the message.
2202 value: Option<u16>,
2203}
2204
2205#[cfg(feature = "std")]
2206impl Node {
2207 fn drop_above(&mut self, len: u16) {
2208 self.value = match self.value {
2209 Some(value) if value < len => Some(value),
2210 _ => None,
2211 };
2212 self.parents
2213 .values_mut()
2214 .for_each(|node| node.drop_above(len))
2215 }
2216}
2217
2218#[cfg(feature = "std")]
2219impl<Target> TreeCompressor<Target> {
2220 /// Creates a new compressor from an underlying octets builder.
2221 pub fn new(target: Target) -> Self {
2222 TreeCompressor {
2223 target,
2224 start: Default::default(),
2225 }
2226 }
2227
2228 /// Returns a reference to the underlying octets builder.
2229 pub fn as_target(&self) -> &Target {
2230 &self.target
2231 }
2232
2233 /// Converts the compressor into the underlying octets builder.
2234 pub fn into_target(self) -> Target {
2235 self.target
2236 }
2237
2238 /// Returns an octets slice of the data.
2239 pub fn as_slice(&self) -> &[u8]
2240 where
2241 Target: AsRef<[u8]>,
2242 {
2243 self.target.as_ref()
2244 }
2245
2246 /// Returns an mutable octets slice of the data.
2247 pub fn as_slice_mut(&mut self) -> &mut [u8]
2248 where
2249 Target: AsMut<[u8]>,
2250 {
2251 self.target.as_mut()
2252 }
2253
2254 fn get<'a, N: Iterator<Item = &'a Label> + Clone>(
2255 &self,
2256 name: N,
2257 ) -> Option<u16> {
2258 let mut node = &self.start;
2259 for label in name {
2260 if label.is_root() {
2261 return node.value;
2262 }
2263 node = node.parents.get(label.as_ref())?;
2264 }
2265 None
2266 }
2267
2268 fn insert<'a, N: Iterator<Item = &'a Label> + Clone>(
2269 &mut self,
2270 name: N,
2271 pos: usize,
2272 ) -> bool {
2273 if pos >= 0xC000 {
2274 return false;
2275 }
2276 let pos = pos as u16;
2277 let mut node = &mut self.start;
2278 for label in name {
2279 if label.is_root() {
2280 node.value = Some(pos);
2281 break;
2282 }
2283 node = node
2284 .parents
2285 .entry(label.as_ref().try_into().unwrap())
2286 .or_default();
2287 }
2288 true
2289 }
2290}
2291
2292//--- AsRef, AsMut, and OctetsBuilder
2293
2294#[cfg(feature = "std")]
2295impl<Target: AsRef<[u8]>> AsRef<[u8]> for TreeCompressor<Target> {
2296 fn as_ref(&self) -> &[u8] {
2297 self.as_slice()
2298 }
2299}
2300
2301#[cfg(feature = "std")]
2302impl<Target: AsMut<[u8]>> AsMut<[u8]> for TreeCompressor<Target> {
2303 fn as_mut(&mut self) -> &mut [u8] {
2304 self.as_slice_mut()
2305 }
2306}
2307
2308#[cfg(feature = "std")]
2309impl<Target: OctetsBuilder> OctetsBuilder for TreeCompressor<Target> {
2310 type AppendError = Target::AppendError;
2311
2312 fn append_slice(
2313 &mut self,
2314 slice: &[u8],
2315 ) -> Result<(), Self::AppendError> {
2316 self.target.append_slice(slice)
2317 }
2318}
2319
2320#[cfg(feature = "std")]
2321impl<Target: Composer> Composer for TreeCompressor<Target> {
2322 fn append_compressed_name<N: ToName + ?Sized>(
2323 &mut self,
2324 name: &N,
2325 ) -> Result<(), Self::AppendError> {
2326 let mut name = name.iter_labels().peekable();
2327
2328 loop {
2329 // If the parent is root, just write that and return.
2330 // Because we do that, there will always be a label left here.
2331 if let Some(label) = name.peek() {
2332 if label.is_root() {
2333 label.compose(self)?;
2334 return Ok(());
2335 }
2336 }
2337
2338 // If we already know this name, append it as a compressed label.
2339 if let Some(pos) = self.get(name.clone()) {
2340 return (pos | 0xC000).compose(self);
2341 }
2342
2343 // So we don’t know the name. Try inserting it into the
2344 // compressor. If we can’t insert anymore, just write out what’s
2345 // left and return.
2346 if !self.insert(name.clone(), self.target.as_ref().len()) {
2347 for label in &mut name {
2348 label.compose(self)?;
2349 }
2350 return Ok(());
2351 }
2352
2353 // Advance to the parent. If the parent is root, just write that
2354 // and return. Because we do that, there will always be a label
2355 // left here.
2356 let label = name.next().unwrap();
2357 label.compose(self)?;
2358 }
2359 }
2360
2361 fn can_compress(&self) -> bool {
2362 true
2363 }
2364}
2365
2366#[cfg(feature = "std")]
2367impl<Target: Composer> Truncate for TreeCompressor<Target> {
2368 fn truncate(&mut self, len: usize) {
2369 self.target.truncate(len);
2370 if len < 0xC000 {
2371 self.start.drop_above(len as u16)
2372 }
2373 }
2374}
2375
2376//------------ HashCompressor ------------------------------------------------
2377
2378/// A domain name compressor that uses a hash table.
2379///
2380/// This type wraps around an octets builder and implements domain name
2381/// compression for it. It stores the position of any domain name it has seen
2382/// in a hash table.
2383///
2384/// The position of a domain name is calculated relative to the beginning of
2385/// the underlying octets builder. This means that this builder must represent
2386/// the message only. This means that if you are using the [`StreamTarget`],
2387/// you need to place it inside this type, _not_ the other way around.
2388///
2389/// [`StreamTarget`]: struct.StreamTarget.html
2390#[cfg(feature = "std")]
2391#[derive(Clone, Debug)]
2392pub struct HashCompressor<Target> {
2393 /// The underlying octetsbuilder.
2394 target: Target,
2395
2396 /// The names inserted into the message.
2397 ///
2398 /// Consider a set of names, where the "parent" (i.e. tail) of each name is
2399 /// another name in the set. For example, a set might contain `.`, `org.`,
2400 /// `example.org.`, and `www.example.org.`. Each of these names (except the
2401 /// root, which is handled specially) is stored as a separate entry in this
2402 /// hash table. A name `<head>.<tail>` is stored as the index of `<head>`
2403 /// and the index of `<tail>` in the built message. Its hash is built from
2404 /// `<head>` (the bytes in the label, not the index into the message) and
2405 /// the index of `<tail>`.
2406 ///
2407 /// Lookups are performed by iterating backward through the labels in a name
2408 /// (to go from the root outward). At each step, the canonical position of
2409 /// `<tail>` is already known; it is hashed together with the next label and
2410 /// searched for in the hash table. An entry with a matching `<head>` (i.e.
2411 /// where the referenced content in the message matches the searched label)
2412 /// and a matching `<tail>` position represents the same name.
2413 ///
2414 /// The root is handled specially. It is never inserted in the hash table,
2415 /// and instead has a fixed fake position in the message of 0xFFFF. That is
2416 /// the initial value that lookups start with.
2417 ///
2418 /// As an example, consider a message `org. example.org. www.example.org.`.
2419 /// In the hash table, the first two entries will look like:
2420 ///
2421 /// ```text
2422 /// - head=0 ("org") tail=0xFFFF
2423 /// - head=5 ("example") tail=0
2424 /// ```
2425 ///
2426 /// Now, to insert `www.example.org.`, the lookup begins from the end. We
2427 /// search for a label "org" with tail 0xFFFF, and find head=0. We set this
2428 /// as the next tail, and search for label "example" to find head=5. Since
2429 /// a label "www" with tail=5 is not already in the hash table, it will be
2430 /// inserted with head=18.
2431 ///
2432 /// This has a space overhead of 4-5 bytes for each entry, accounting for
2433 /// the load factor (which appears to be 87.5%). Technically, storing the
2434 /// labels indirectly means that comparisons are more expensive; but most
2435 /// labels are relatively short and storing them inline as 64-byte arrays
2436 /// would be quite wasteful.
2437 names: HashTable<HashEntry>,
2438
2439 /// How names in the table are hashed.
2440 hasher: RandomState,
2441}
2442
2443#[cfg(feature = "std")]
2444#[derive(Copy, Clone, Debug)]
2445struct HashEntry {
2446 /// The position of the head label in the name.
2447 head: u16,
2448
2449 /// The position of the tail name.
2450 tail: u16,
2451}
2452
2453#[cfg(feature = "std")]
2454impl HashEntry {
2455 /// Try constructing a [`HashEntry`].
2456 fn new(head: usize, tail: usize) -> Option<Self> {
2457 if head < 0xC000 {
2458 Some(Self {
2459 head: head as u16,
2460 tail: tail as u16,
2461 })
2462 } else {
2463 None
2464 }
2465 }
2466
2467 /// Get the head label for this entry.
2468 fn head<'m>(&self, message: &'m [u8]) -> &'m Label {
2469 Label::split_from(&message[self.head as usize..])
2470 .expect("the message contains valid labels")
2471 .0
2472 }
2473
2474 /// Compute the hash of this entry.
2475 fn hash(&self, message: &[u8], hasher: &RandomState) -> u64 {
2476 hasher.hash_one((self.head(message), self.tail))
2477 }
2478
2479 /// Compare this entry to a label.
2480 fn eq(&self, message: &[u8], query: (&Label, u16)) -> bool {
2481 (self.head(message), self.tail) == query
2482 }
2483}
2484
2485#[cfg(feature = "std")]
2486impl<Target> HashCompressor<Target> {
2487 /// Creates a new compressor from an underlying octets builder.
2488 pub fn new(target: Target) -> Self {
2489 HashCompressor {
2490 target,
2491 names: Default::default(),
2492 hasher: Default::default(),
2493 }
2494 }
2495
2496 /// Returns a reference to the underlying octets builder.
2497 pub fn as_target(&self) -> &Target {
2498 &self.target
2499 }
2500
2501 /// Converts the compressor into the underlying octets builder.
2502 pub fn into_target(self) -> Target {
2503 self.target
2504 }
2505
2506 /// Returns an octets slice of the data.
2507 pub fn as_slice(&self) -> &[u8]
2508 where
2509 Target: AsRef<[u8]>,
2510 {
2511 self.target.as_ref()
2512 }
2513
2514 /// Returns an mutable octets slice of the data.
2515 pub fn as_slice_mut(&mut self) -> &mut [u8]
2516 where
2517 Target: AsMut<[u8]>,
2518 {
2519 self.target.as_mut()
2520 }
2521}
2522
2523//--- AsRef, AsMut, and OctetsBuilder
2524
2525#[cfg(feature = "std")]
2526impl<Target: AsRef<[u8]>> AsRef<[u8]> for HashCompressor<Target> {
2527 fn as_ref(&self) -> &[u8] {
2528 self.as_slice()
2529 }
2530}
2531
2532#[cfg(feature = "std")]
2533impl<Target: AsMut<[u8]>> AsMut<[u8]> for HashCompressor<Target> {
2534 fn as_mut(&mut self) -> &mut [u8] {
2535 self.as_slice_mut()
2536 }
2537}
2538
2539#[cfg(feature = "std")]
2540impl<Target: OctetsBuilder> OctetsBuilder for HashCompressor<Target> {
2541 type AppendError = Target::AppendError;
2542
2543 fn append_slice(
2544 &mut self,
2545 slice: &[u8],
2546 ) -> Result<(), Self::AppendError> {
2547 self.target.append_slice(slice)
2548 }
2549}
2550
2551#[cfg(feature = "std")]
2552impl<Target: Composer> Composer for HashCompressor<Target> {
2553 fn append_compressed_name<N: ToName + ?Sized>(
2554 &mut self,
2555 name: &N,
2556 ) -> Result<(), Self::AppendError> {
2557 let mut name = name.iter_labels();
2558 let message = self.target.as_ref();
2559
2560 // Remove the root label -- we know it's there.
2561 assert!(
2562 name.next_back().is_some_and(|l| l.is_root()),
2563 "absolute names must end with a root label"
2564 );
2565
2566 // The position of the consumed labels from the end of the name.
2567 let mut position = 0xFFFF;
2568
2569 // The last label that must be inserted, if any.
2570 let mut last_label = None;
2571
2572 // Look up each label in reverse order.
2573 while let Some(label) = name.next_back() {
2574 // Look up the labels seen thus far in the hash table.
2575 let query = (label, position);
2576 let hash = self.hasher.hash_one(query);
2577
2578 let entry =
2579 self.names.find(hash, |&name| name.eq(message, query));
2580 if let Some(entry) = entry {
2581 // We found a match, so update the position.
2582 position = entry.head;
2583 } else {
2584 // We will have to write this label.
2585 last_label = Some(label);
2586 break;
2587 }
2588 }
2589
2590 // Write out the remaining labels in the name in regular order.
2591 let mut labels = name.chain(last_label).peekable();
2592 while let Some(label) = labels.next() {
2593 let head = self.target.as_ref().len();
2594 let tail = head + label.compose_len() as usize;
2595
2596 label.compose(self)?;
2597
2598 // Remember this label for future compression, if possible.
2599 //
2600 // If some labels in this name pass the 0xC000 boundary point, then
2601 // none of its remembered labels can be used (since they are looked
2602 // up from right to left, and the rightmost ones will fail first).
2603 // We could check more thoroughly for this, but it's not worth it.
2604 if let Some(mut entry) = HashEntry::new(head, tail) {
2605 // If there is no following label, use the remaining position.
2606 if labels.peek().is_none() {
2607 entry.tail = position;
2608 }
2609
2610 let message = self.target.as_ref();
2611 let hasher = &self.hasher;
2612 let hash = entry.hash(message, hasher);
2613 self.names.insert_unique(hash, entry, |&name| {
2614 name.hash(message, hasher)
2615 });
2616 }
2617 }
2618
2619 // Write the compressed pointer or the root label.
2620 if position != 0xFFFF {
2621 (position | 0xC000).compose(self)
2622 } else {
2623 Label::root().compose(self)
2624 }
2625 }
2626
2627 fn can_compress(&self) -> bool {
2628 true
2629 }
2630}
2631
2632#[cfg(feature = "std")]
2633impl<Target: Composer> Truncate for HashCompressor<Target> {
2634 fn truncate(&mut self, len: usize) {
2635 self.target.truncate(len);
2636 if len < 0xC000 {
2637 self.names.retain(|name| name.head < len as u16);
2638 }
2639 }
2640}
2641
2642//============ Errors ========================================================
2643
2644#[derive(Clone, Copy, Debug)]
2645pub enum PushError {
2646 CountOverflow,
2647 ShortBuf,
2648}
2649
2650impl<T: Into<ShortBuf>> From<T> for PushError {
2651 fn from(_: T) -> Self {
2652 Self::ShortBuf
2653 }
2654}
2655
2656impl fmt::Display for PushError {
2657 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2658 match *self {
2659 PushError::CountOverflow => f.write_str("counter overflow"),
2660 PushError::ShortBuf => ShortBuf.fmt(f),
2661 }
2662 }
2663}
2664
2665#[cfg(feature = "std")]
2666impl std::error::Error for PushError {}
2667
2668//============ Testing =======================================================
2669
2670#[cfg(test)]
2671#[cfg(feature = "std")]
2672mod test {
2673 use super::*;
2674 use crate::base::opt;
2675 use crate::base::{Name, Serial, Ttl};
2676 use crate::rdata::{Ns, Soa, A};
2677 use core::str::FromStr;
2678
2679 #[test]
2680 fn message_builder() {
2681 // Make a domain name we can use later on.
2682 let name = Name::<Vec<u8>>::from_str("example.com").unwrap();
2683
2684 // Create a message builder wrapping a compressor wrapping a stream
2685 // target.
2686 let mut msg = MessageBuilder::from_target(StaticCompressor::new(
2687 StreamTarget::new_vec(),
2688 ))
2689 .unwrap();
2690
2691 // Set the RD bit in the header and proceed to the question section.
2692 msg.header_mut().set_rd(true);
2693 let mut msg = msg.question();
2694
2695 // Add a question and proceed to the answer section.
2696 msg.push((&name, Rtype::A)).unwrap();
2697 let mut msg = msg.answer();
2698
2699 // Add two answer and proceed to the additional sections
2700 msg.push((&name, 86400, A::from_octets(192, 0, 2, 1)))
2701 .unwrap();
2702 msg.push((&name, 86400, A::from_octets(192, 0, 2, 2)))
2703 .unwrap();
2704
2705 // Add an authority
2706 let mut msg = msg.authority();
2707 msg.push((&name, 0, Ns::from(name.clone()))).unwrap();
2708
2709 // Add additional
2710 let mut msg = msg.additional();
2711 msg.push((&name, 86400, A::from_octets(192, 0, 2, 1)))
2712 .unwrap();
2713
2714 // Convert the builder into the actual message.
2715 let target = msg.finish().into_target();
2716
2717 // Reparse message and check contents
2718 let msg = Message::from_octets(target.as_dgram_slice()).unwrap();
2719 let q = msg.first_question().unwrap();
2720 assert_eq!(q.qname(), &name);
2721 assert_eq!(q.qtype(), Rtype::A);
2722
2723 let section = msg.answer().unwrap();
2724 let mut records = section.limit_to::<A>();
2725 assert_eq!(
2726 records.next().unwrap().unwrap().data(),
2727 &A::from_octets(192, 0, 2, 1)
2728 );
2729 assert_eq!(
2730 records.next().unwrap().unwrap().data(),
2731 &A::from_octets(192, 0, 2, 2)
2732 );
2733
2734 let section = msg.authority().unwrap();
2735 let mut records = section.limit_to::<Ns<_>>();
2736 let rr = records.next().unwrap().unwrap();
2737 assert_eq!(rr.owner(), &name);
2738 assert_eq!(rr.data().nsdname(), &name);
2739
2740 let section = msg.additional().unwrap();
2741 let mut records = section.limit_to::<A>();
2742 let rr = records.next().unwrap().unwrap();
2743 assert_eq!(rr.owner(), &name);
2744 assert_eq!(rr.data(), &A::from_octets(192, 0, 2, 1));
2745 }
2746
2747 #[cfg(feature = "heapless")]
2748 #[test]
2749 fn exceed_limits() {
2750 // Create a limited message builder.
2751 let buf = heapless::Vec::<u8, 100>::new();
2752
2753 // Initialize it with a message header (12 bytes)
2754 let mut msg = MessageBuilder::from_target(buf).unwrap();
2755 let hdr_len = msg.as_slice().len();
2756
2757 // Add some bytes.
2758 msg.push(|t| t.append_slice(&[0u8; 50]), |_| Ok(()))
2759 .unwrap();
2760 assert_eq!(msg.as_slice().len(), hdr_len + 50);
2761
2762 // Set a push limit below the current length.
2763 msg.set_push_limit(25);
2764
2765 // Verify that push fails.
2766 assert!(msg.push(|t| t.append_slice(&[0u8; 1]), |_| Ok(())).is_err());
2767 assert_eq!(msg.as_slice().len(), hdr_len + 50);
2768
2769 // Remove the limit.
2770 msg.clear_push_limit();
2771
2772 // Verify that push up until capacity succeeds.
2773 for _ in (hdr_len + 50)..100 {
2774 msg.push(|t| t.append_slice(&[0u8; 1]), |_| Ok(())).unwrap();
2775 }
2776 assert_eq!(msg.as_slice().len(), 100);
2777
2778 // Verify that exceeding the underlying capacity limit fails.
2779 assert!(msg.push(|t| t.append_slice(&[0u8; 1]), |_| Ok(())).is_err());
2780 assert_eq!(msg.as_slice().len(), 100);
2781 }
2782
2783 #[test]
2784 fn opt_builder() {
2785 let mut msg = MessageBuilder::new_vec().additional();
2786
2787 // Add an OPT record.
2788 let nsid = opt::nsid::Nsid::from_octets(&b"example"[..]).unwrap();
2789 msg.opt(|o| {
2790 o.set_udp_payload_size(4096);
2791 o.push(&nsid)?;
2792 Ok(())
2793 })
2794 .unwrap();
2795
2796 let msg = msg.finish();
2797 println!("{:?}", msg);
2798 let msg = Message::from_octets(msg).unwrap();
2799 let opt = msg.opt().unwrap();
2800
2801 // Check options
2802 assert_eq!(opt.udp_payload_size(), 4096);
2803 let mut opts = opt.opt().iter::<opt::nsid::Nsid<_>>();
2804 assert_eq!(opts.next(), Some(Ok(nsid)));
2805 }
2806
2807 fn create_compressed<T: Composer>(target: T) -> T
2808 where
2809 T::AppendError: fmt::Debug,
2810 {
2811 let mut msg = MessageBuilder::from_target(target).unwrap().question();
2812 msg.header_mut().set_rcode(Rcode::NXDOMAIN);
2813 msg.header_mut().set_rd(true);
2814 msg.header_mut().set_ra(true);
2815 msg.header_mut().set_qr(true);
2816
2817 msg.push((&"example".parse::<Name<Vec<u8>>>().unwrap(), Rtype::NS))
2818 .unwrap();
2819 let mut msg = msg.authority();
2820
2821 let mname: Name<Vec<u8>> = "a.root-servers.net".parse().unwrap();
2822 let rname = "nstld.verisign-grs.com".parse().unwrap();
2823 msg.push((
2824 Name::root_slice(),
2825 86390,
2826 Soa::new(
2827 mname,
2828 rname,
2829 Serial(2020081701),
2830 Ttl::from_secs(1800),
2831 Ttl::from_secs(900),
2832 Ttl::from_secs(604800),
2833 Ttl::from_secs(86400),
2834 ),
2835 ))
2836 .unwrap();
2837 msg.finish()
2838 }
2839
2840 #[test]
2841 fn compressor() {
2842 // An example negative response to `example. NS` with an SOA to test
2843 // various compressed name situations.
2844 let expect = &[
2845 0x00, 0x00, 0x81, 0x83, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00,
2846 0x00, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x00, 0x00,
2847 0x02, 0x00, 0x01, 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, 0x01, 0x51,
2848 0x76, 0x00, 0x40, 0x01, 0x61, 0x0c, 0x72, 0x6f, 0x6f, 0x74, 0x2d,
2849 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x03, 0x6e, 0x65, 0x74,
2850 0x00, 0x05, 0x6e, 0x73, 0x74, 0x6c, 0x64, 0x0c, 0x76, 0x65, 0x72,
2851 0x69, 0x73, 0x69, 0x67, 0x6e, 0x2d, 0x67, 0x72, 0x73, 0x03, 0x63,
2852 0x6f, 0x6d, 0x00, 0x78, 0x68, 0x00, 0x25, 0x00, 0x00, 0x07, 0x08,
2853 0x00, 0x00, 0x03, 0x84, 0x00, 0x09, 0x3a, 0x80, 0x00, 0x01, 0x51,
2854 0x80,
2855 ];
2856
2857 let msg = create_compressed(StaticCompressor::new(Vec::new()));
2858 assert_eq!(&expect[..], msg.as_ref());
2859
2860 let msg = create_compressed(TreeCompressor::new(Vec::new()));
2861 assert_eq!(&expect[..], msg.as_ref());
2862 }
2863
2864 #[test]
2865 fn compress_positive_response() {
2866 // An example positive response to `A example.com.` that is compressed
2867 //
2868 // ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 0
2869 // ;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
2870 //
2871 // ;; QUESTION SECTION:
2872 // ;example.com. IN A
2873 //
2874 // ;; ANSWER SECTION:
2875 // example.com. 3600 IN A 203.0.113.1
2876 //
2877 // ;; MSG SIZE rcvd: 45
2878 let expect = &[
2879 0x00, 0x00, 0x81, 0xa0, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
2880 0x00, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x03, 0x63,
2881 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01, 0xc0, 0x0c, 0x00, 0x01,
2882 0x00, 0x01, 0x00, 0x00, 0x0e, 0x10, 0x00, 0x04, 0xcb, 0x00, 0x71,
2883 0x01,
2884 ];
2885
2886 let name = "example.com.".parse::<Name<Vec<u8>>>().unwrap();
2887 let mut msg =
2888 MessageBuilder::from_target(StaticCompressor::new(Vec::new()))
2889 .unwrap()
2890 .question();
2891 msg.header_mut().set_rcode(Rcode::NOERROR);
2892 msg.header_mut().set_rd(true);
2893 msg.header_mut().set_ra(true);
2894 msg.header_mut().set_qr(true);
2895 msg.header_mut().set_ad(true);
2896
2897 // Question
2898 msg.push((name.clone(), Rtype::A)).unwrap();
2899
2900 // Answer
2901 let mut msg = msg.answer();
2902 msg.push((name.clone(), 3600, A::from_octets(203, 0, 113, 1)))
2903 .unwrap();
2904
2905 let actual = msg.finish().into_target();
2906 assert_eq!(45, actual.len(), "unexpected response size");
2907 assert_eq!(expect[..], actual, "unexpected response data");
2908 }
2909
2910 #[cfg(feature = "std")]
2911 #[test]
2912 fn hash_compress_positive_response() {
2913 // An example positive response to `A example.com.` that is compressed
2914 //
2915 // ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 0
2916 // ;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
2917 //
2918 // ;; QUESTION SECTION:
2919 // ;example.com. IN A
2920 //
2921 // ;; ANSWER SECTION:
2922 // example.com. 3600 IN A 203.0.113.1
2923 //
2924 // ;; MSG SIZE rcvd: 45
2925 let expect = &[
2926 0x00, 0x00, 0x81, 0xa0, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
2927 0x00, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x03, 0x63,
2928 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01, 0xc0, 0x0c, 0x00, 0x01,
2929 0x00, 0x01, 0x00, 0x00, 0x0e, 0x10, 0x00, 0x04, 0xcb, 0x00, 0x71,
2930 0x01,
2931 ];
2932
2933 let name = "example.com.".parse::<Name<Vec<u8>>>().unwrap();
2934 let mut msg =
2935 MessageBuilder::from_target(HashCompressor::new(Vec::new()))
2936 .unwrap()
2937 .question();
2938 msg.header_mut().set_rcode(Rcode::NOERROR);
2939 msg.header_mut().set_rd(true);
2940 msg.header_mut().set_ra(true);
2941 msg.header_mut().set_qr(true);
2942 msg.header_mut().set_ad(true);
2943
2944 // Question
2945 msg.push((name.clone(), Rtype::A)).unwrap();
2946
2947 // Answer
2948 let mut msg = msg.answer();
2949 msg.push((name.clone(), 3600, A::from_octets(203, 0, 113, 1)))
2950 .unwrap();
2951
2952 let actual = msg.finish().into_target();
2953 assert_eq!(45, actual.len(), "unexpected response size");
2954 assert_eq!(expect[..], actual, "unexpected response data");
2955 }
2956}