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(&mut OptBuilder<Target>) -> Result<(), Target::AppendError>,
1421 {
1422 self.authority.answer.builder.push(
1423 |target| OptBuilder::new(target)?.build(op),
1424 |counts| counts.inc_arcount(),
1425 )
1426 }
1427}
1428
1429/// # Conversions
1430///
1431/// Additional conversion methods are available via the `Deref`
1432/// implementation.
1433impl<Target: Composer> AdditionalBuilder<Target> {
1434 /// Rewinds to an empty additional section.
1435 ///
1436 /// All previously added additional records will be lost.
1437 pub fn rewind(&mut self) {
1438 self.authority.as_target_mut().truncate(self.start);
1439 self.counts_mut().set_arcount(0);
1440 }
1441
1442 /// Converts the additional builder into a message builder.
1443 ///
1444 /// All questions and records will be dropped and all sections will be
1445 /// empty.
1446 pub fn builder(self) -> MessageBuilder<Target> {
1447 self.question().builder()
1448 }
1449
1450 /// Converts the additional builder into a question builder.
1451 ///
1452 /// All answer, authority, and additional records will be dropped. All
1453 /// previously added questions will, however, remain.
1454 pub fn question(self) -> QuestionBuilder<Target> {
1455 self.answer().question()
1456 }
1457
1458 /// Converts the additional builder into an answer builder.
1459 ///
1460 /// All authority and additional records will be dropped. All questions
1461 /// and answer records will remain.
1462 pub fn answer(self) -> AnswerBuilder<Target> {
1463 self.authority().answer()
1464 }
1465
1466 /// Converts the additional builder into an authority builder.
1467 ///
1468 /// All additional records will be dropped. All questions, answer, and
1469 /// authority records will remain.
1470 pub fn authority(mut self) -> AuthorityBuilder<Target> {
1471 self.rewind();
1472 self.authority
1473 }
1474
1475 /// Converts the additional builder into an additional builder.
1476 ///
1477 /// In other words, does absolutely nothing.
1478 pub fn additional(self) -> AdditionalBuilder<Target> {
1479 self
1480 }
1481
1482 /// Converts the additional builder into the underlying octets builder.
1483 pub fn finish(self) -> Target {
1484 self.authority.finish()
1485 }
1486}
1487
1488impl<Target: FreezeBuilder> AdditionalBuilder<Target> {
1489 /// Converts the additional builder into the final message.
1490 ///
1491 /// The method will return a message atop whatever octets sequence the
1492 /// builder’s octets builder converts into.
1493 pub fn into_message(self) -> Message<Target::Octets> {
1494 self.authority.into_message()
1495 }
1496}
1497
1498impl<Target> AdditionalBuilder<Target> {
1499 /// Returns a reference to the underlying message builder.
1500 pub fn as_builder(&self) -> &MessageBuilder<Target> {
1501 self.authority.as_builder()
1502 }
1503
1504 /// Returns a mutable reference to the underlying message builder.
1505 pub fn as_builder_mut(&mut self) -> &mut MessageBuilder<Target> {
1506 self.authority.as_builder_mut()
1507 }
1508}
1509
1510//--- From
1511
1512impl<Target> From<MessageBuilder<Target>> for AdditionalBuilder<Target>
1513where
1514 Target: Composer,
1515{
1516 fn from(src: MessageBuilder<Target>) -> Self {
1517 src.additional()
1518 }
1519}
1520
1521impl<Target> From<QuestionBuilder<Target>> for AdditionalBuilder<Target>
1522where
1523 Target: Composer,
1524{
1525 fn from(src: QuestionBuilder<Target>) -> Self {
1526 src.additional()
1527 }
1528}
1529
1530impl<Target> From<AnswerBuilder<Target>> for AdditionalBuilder<Target>
1531where
1532 Target: Composer,
1533{
1534 fn from(src: AnswerBuilder<Target>) -> Self {
1535 src.additional()
1536 }
1537}
1538
1539impl<Target> From<AuthorityBuilder<Target>> for AdditionalBuilder<Target>
1540where
1541 Target: Composer,
1542{
1543 fn from(src: AuthorityBuilder<Target>) -> Self {
1544 src.additional()
1545 }
1546}
1547
1548impl<Target> From<AdditionalBuilder<Target>> for Message<Target::Octets>
1549where
1550 Target: FreezeBuilder,
1551{
1552 fn from(src: AdditionalBuilder<Target>) -> Self {
1553 src.into_message()
1554 }
1555}
1556
1557//--- Deref, DerefMut, AsRef, and AsMut
1558
1559impl<Target> Deref for AdditionalBuilder<Target> {
1560 type Target = MessageBuilder<Target>;
1561
1562 fn deref(&self) -> &Self::Target {
1563 self.as_builder()
1564 }
1565}
1566
1567impl<Target> DerefMut for AdditionalBuilder<Target> {
1568 fn deref_mut(&mut self) -> &mut Self::Target {
1569 self.as_builder_mut()
1570 }
1571}
1572
1573impl<Target> AsRef<MessageBuilder<Target>> for AdditionalBuilder<Target> {
1574 fn as_ref(&self) -> &MessageBuilder<Target> {
1575 self.as_builder()
1576 }
1577}
1578
1579impl<Target> AsMut<MessageBuilder<Target>> for AdditionalBuilder<Target> {
1580 fn as_mut(&mut self) -> &mut MessageBuilder<Target> {
1581 self.as_builder_mut()
1582 }
1583}
1584
1585impl<Target> AsRef<Target> for AdditionalBuilder<Target> {
1586 fn as_ref(&self) -> &Target {
1587 self.as_target()
1588 }
1589}
1590
1591impl<Target: AsRef<[u8]>> AsRef<[u8]> for AdditionalBuilder<Target> {
1592 fn as_ref(&self) -> &[u8] {
1593 self.as_slice()
1594 }
1595}
1596
1597//------------ RecordSectionBuilder ------------------------------------------
1598
1599/// A section that can have records pushed to it.
1600///
1601/// This trait exists to make it possible to write code that works for all
1602/// three record sections. It basically just duplicates the `push` method of
1603/// these sections.
1604///
1605/// (This method is available on the sections as a method, too, so you don’t
1606/// need to import the `RecordSectionBuilder` all the time.)
1607pub trait RecordSectionBuilder<Target: Composer> {
1608 /// Appends a record to a record section.
1609 ///
1610 /// The methods accepts anything that implements the [`ComposeRecord`] trait.
1611 /// Apart from record values and references, this are tuples of the owner
1612 /// domain name, optionally the class (which is taken to be IN if
1613 /// missing), the TTL, and record data.
1614 fn push(&mut self, record: impl ComposeRecord) -> Result<(), PushError>;
1615}
1616
1617impl<Target> RecordSectionBuilder<Target> for AnswerBuilder<Target>
1618where
1619 Target: Composer,
1620{
1621 fn push(&mut self, record: impl ComposeRecord) -> Result<(), PushError> {
1622 Self::push(self, record)
1623 }
1624}
1625
1626impl<Target: Composer> RecordSectionBuilder<Target>
1627 for AuthorityBuilder<Target>
1628{
1629 fn push(&mut self, record: impl ComposeRecord) -> Result<(), PushError> {
1630 Self::push(self, record)
1631 }
1632}
1633
1634impl<Target> RecordSectionBuilder<Target> for AdditionalBuilder<Target>
1635where
1636 Target: Composer,
1637{
1638 fn push(&mut self, record: impl ComposeRecord) -> Result<(), PushError> {
1639 Self::push(self, record)
1640 }
1641}
1642
1643//------------ OptBuilder ----------------------------------------------------
1644
1645/// Builds an OPT record.
1646///
1647/// A mutable reference of this type is passed to the closure given to
1648/// [`AdditionalBuilder::opt`] allowing this closure to manipulate both the
1649/// header values of the record and push options to the record data.
1650///
1651/// [`AdditionalBuilder::opt`]: struct.AdditonalBuilder.html#method.opt
1652pub struct OptBuilder<'a, Target: ?Sized> {
1653 start: usize,
1654 target: &'a mut Target,
1655}
1656
1657impl<'a, Target: Composer + ?Sized> OptBuilder<'a, Target> {
1658 /// Creates a new opt builder atop an additional builder.
1659 fn new(target: &'a mut Target) -> Result<Self, ShortBuf> {
1660 let start = target.as_ref().len();
1661 OptHeader::default().compose(target).map_err(Into::into)?;
1662 Ok(OptBuilder { start, target })
1663 }
1664
1665 fn build<F>(&mut self, op: F) -> Result<(), ShortBuf>
1666 where
1667 F: FnOnce(&mut Self) -> Result<(), Target::AppendError>,
1668 {
1669 self.target.append_slice(&[0; 2]).map_err(Into::into)?;
1670 let pos = self.target.as_ref().len();
1671 match op(self) {
1672 Ok(_) => match u16::try_from(self.target.as_ref().len() - pos) {
1673 Ok(len) => {
1674 self.target.as_mut()[pos - 2..pos]
1675 .copy_from_slice(&(len).to_be_bytes());
1676 Ok(())
1677 }
1678 Err(_) => {
1679 self.target.truncate(pos);
1680 Err(ShortBuf)
1681 }
1682 },
1683 Err(_) => {
1684 self.target.truncate(pos);
1685 Err(ShortBuf)
1686 }
1687 }
1688 }
1689
1690 /// Replaces the contents of this [`OptBuilder`] with the given
1691 /// [`OptRecord`]`.
1692 pub fn clone_from<T: AsRef<[u8]>>(
1693 &mut self,
1694 source: &OptRecord<T>,
1695 ) -> Result<(), Target::AppendError> {
1696 self.target.truncate(self.start);
1697 source.as_record().compose(self.target)
1698 }
1699
1700 /// Appends an option to the OPT record.
1701 pub fn push<Opt: ComposeOptData + ?Sized>(
1702 &mut self,
1703 opt: &Opt,
1704 ) -> Result<(), Target::AppendError> {
1705 self.push_raw_option(opt.code(), opt.compose_len(), |target| {
1706 opt.compose_option(target)
1707 })
1708 }
1709
1710 /// Appends a raw option to the OPT record.
1711 ///
1712 /// The method will append an option with the given option code. The data
1713 /// of the option will be written via the closure `op`.
1714 pub fn push_raw_option<F>(
1715 &mut self,
1716 code: OptionCode,
1717 option_len: u16,
1718 op: F,
1719 ) -> Result<(), Target::AppendError>
1720 where
1721 F: FnOnce(&mut Target) -> Result<(), Target::AppendError>,
1722 {
1723 code.compose(self.target)?;
1724 option_len.compose(self.target)?;
1725 op(self.target)
1726 }
1727
1728 /// Returns the current UDP payload size field of the OPT record.
1729 ///
1730 /// This field contains the largest UDP datagram the sender can accept.
1731 /// This is not the path MTU but really what the sender can work with
1732 /// internally.
1733 #[must_use]
1734 pub fn udp_payload_size(&self) -> u16 {
1735 self.opt_header().udp_payload_size()
1736 }
1737
1738 /// Sets the UDP payload size field of the OPT record.
1739 pub fn set_udp_payload_size(&mut self, value: u16) {
1740 self.opt_header_mut().set_udp_payload_size(value)
1741 }
1742
1743 /// Returns the extended rcode of the message.
1744 ///
1745 /// The method assembles the rcode both from the message header and the
1746 /// OPT header.
1747 #[must_use]
1748 pub fn rcode(&self) -> OptRcode {
1749 self.opt_header()
1750 .rcode(*Header::for_message_slice(self.target.as_ref()))
1751 }
1752
1753 /// Sets the extended rcode of the message.
1754 //
1755 /// The method will update both the message header and the OPT header.
1756 pub fn set_rcode(&mut self, rcode: OptRcode) {
1757 Header::for_message_slice_mut(self.target.as_mut())
1758 .set_rcode(rcode.rcode());
1759 self.opt_header_mut().set_rcode(rcode)
1760 }
1761
1762 /// Returns the EDNS version of the OPT header.
1763 ///
1764 /// Only EDNS version 0 is currently defined.
1765 #[must_use]
1766 pub fn version(&self) -> u8 {
1767 self.opt_header().version()
1768 }
1769
1770 /// Sets the EDNS version of the OPT header.
1771 pub fn set_version(&mut self, version: u8) {
1772 self.opt_header_mut().set_version(version)
1773 }
1774
1775 /// Returns the value of the DNSSEC OK (DO) bit.
1776 ///
1777 /// By setting this bit, a resolver indicates that it is interested in
1778 /// also receiving the DNSSEC-related resource records necessary to
1779 /// validate an answer. The bit and the related procedures are defined in
1780 /// [RFC 3225].
1781 ///
1782 /// [RFC 3225]: https://tools.ietf.org/html/rfc3225
1783 #[must_use]
1784 pub fn dnssec_ok(&self) -> bool {
1785 self.opt_header().dnssec_ok()
1786 }
1787
1788 /// Sets the DNSSEC OK (DO) bit to the given value.
1789 pub fn set_dnssec_ok(&mut self, value: bool) {
1790 self.opt_header_mut().set_dnssec_ok(value)
1791 }
1792
1793 /// Returns a reference to the full OPT header.
1794 fn opt_header(&self) -> &OptHeader {
1795 OptHeader::for_record_slice(&self.target.as_ref()[self.start..])
1796 }
1797
1798 /// Returns a mutual reference to the full OPT header.
1799 fn opt_header_mut(&mut self) -> &mut OptHeader {
1800 let start = self.start;
1801 OptHeader::for_record_slice_mut(&mut self.target.as_mut()[start..])
1802 }
1803
1804 /// Returns a reference to the underlying octets builder.
1805 pub fn as_target(&self) -> &Target {
1806 self.target
1807 }
1808}
1809
1810//------------ StreamTarget --------------------------------------------------
1811
1812/// A builder target for sending messages on stream transports.
1813///
1814/// TODO: Rename this type and adjust the doc comments as it is usable both
1815/// for datagram AND stream transports via [`as_dgram_slice`] and
1816/// [`as_stream_slice`].
1817///
1818/// When messages are sent over stream-oriented transports such as TCP, a DNS
1819/// message is preceded by a 16 bit length value in order to determine the end
1820/// of a message. This type transparently adds this length value as the first
1821/// two octets of an octets builder and itself presents an octets builder
1822/// interface for building the actual message. Whenever data is pushed to that
1823/// builder interface, the type will update the length value.
1824///
1825/// Because the length is 16 bits long, the assembled message can be at most
1826/// 65536 octets long, independently of the maximum length the underlying
1827/// builder allows.
1828///
1829/// [`as_dgram_slice`]: Self::as_dgram_slice
1830/// [`as_stream_slice`]: Self::as_stream_slice
1831#[derive(Clone, Debug, Default)]
1832pub struct StreamTarget<Target> {
1833 /// The underlying octets builder.
1834 target: Target,
1835}
1836
1837impl<Target: Composer> StreamTarget<Target> {
1838 /// Creates a new stream target wrapping an octets builder.
1839 ///
1840 /// The function will truncate the builder back to empty and append the
1841 /// length value. Because of the latter, this can fail if the octets
1842 /// builder doesn’t even have space for that.
1843 pub fn new(mut target: Target) -> Result<Self, Target::AppendError> {
1844 target.truncate(0);
1845 0u16.compose(&mut target)?;
1846 Ok(StreamTarget { target })
1847 }
1848}
1849
1850#[cfg(feature = "std")]
1851impl StreamTarget<Vec<u8>> {
1852 /// Creates a stream target atop an empty `Vec<u8>`.
1853 #[must_use]
1854 pub fn new_vec() -> Self {
1855 infallible(Self::new(Vec::new()))
1856 }
1857}
1858
1859#[cfg(feature = "bytes")]
1860impl StreamTarget<BytesMut> {
1861 /// Creates a stream target atop an empty `Vec<u8>`.
1862 pub fn new_bytes() -> Self {
1863 infallible(Self::new(BytesMut::new()))
1864 }
1865}
1866
1867impl<Target> StreamTarget<Target> {
1868 /// Returns a reference to the underlying octets builder.
1869 pub fn as_target(&self) -> &Target {
1870 &self.target
1871 }
1872
1873 /// Converts the stream target into the underlying octets builder.
1874 ///
1875 /// The returned builder will contain the 16 bit length value with the
1876 /// correct content and the assembled message.
1877 pub fn into_target(self) -> Target {
1878 self.target
1879 }
1880}
1881
1882impl<Target: AsRef<[u8]> + AsMut<[u8]>> StreamTarget<Target> {
1883 /// Updates the length value to the current length of the target.
1884 fn update_shim(&mut self) -> Result<(), ShortBuf> {
1885 match u16::try_from(self.target.as_ref().len() - 2) {
1886 Ok(len) => {
1887 self.target.as_mut()[..2].copy_from_slice(&len.to_be_bytes());
1888 Ok(())
1889 }
1890 Err(_) => Err(ShortBuf),
1891 }
1892 }
1893}
1894
1895impl<Target: AsRef<[u8]>> StreamTarget<Target> {
1896 /// Returns an octets slice of the message for stream transports.
1897 ///
1898 /// The slice will start with the length octets and can be send as is
1899 /// through a stream transport such as TCP.
1900 pub fn as_stream_slice(&self) -> &[u8] {
1901 self.target.as_ref()
1902 }
1903
1904 /// Returns an octets slice of the message for datagram transports.
1905 ///
1906 /// The slice will not contain the length octets but only the actual
1907 /// message itself. This slice can be used for sending via datagram
1908 /// transports such as UDP.
1909 pub fn as_dgram_slice(&self) -> &[u8] {
1910 &self.target.as_ref()[2..]
1911 }
1912}
1913
1914//--- AsRef, AsMut
1915
1916impl<Target: AsRef<[u8]>> AsRef<[u8]> for StreamTarget<Target> {
1917 fn as_ref(&self) -> &[u8] {
1918 &self.target.as_ref()[2..]
1919 }
1920}
1921
1922impl<Target: AsMut<[u8]>> AsMut<[u8]> for StreamTarget<Target> {
1923 fn as_mut(&mut self) -> &mut [u8] {
1924 &mut self.target.as_mut()[2..]
1925 }
1926}
1927
1928//--- OctetsBuilder, Truncate, Composer
1929
1930impl<Target> OctetsBuilder for StreamTarget<Target>
1931where
1932 Target: OctetsBuilder + AsRef<[u8]> + AsMut<[u8]>,
1933 Target::AppendError: Into<ShortBuf>,
1934{
1935 type AppendError = ShortBuf;
1936
1937 fn append_slice(
1938 &mut self,
1939 slice: &[u8],
1940 ) -> Result<(), Self::AppendError> {
1941 self.target.append_slice(slice).map_err(Into::into)?;
1942 self.update_shim()
1943 }
1944}
1945
1946impl<Target: Composer> Truncate for StreamTarget<Target> {
1947 fn truncate(&mut self, len: usize) {
1948 self.target
1949 .truncate(len.checked_add(2).expect("long truncate"));
1950 self.update_shim().expect("truncate grew buffer???")
1951 }
1952}
1953
1954impl<Target> Composer for StreamTarget<Target>
1955where
1956 Target: Composer,
1957 Target::AppendError: Into<ShortBuf>,
1958{
1959 fn append_compressed_name<N: ToName + ?Sized>(
1960 &mut self,
1961 name: &N,
1962 ) -> Result<(), Self::AppendError> {
1963 self.target
1964 .append_compressed_name(name)
1965 .map_err(Into::into)?;
1966 self.update_shim()
1967 }
1968}
1969
1970//------------ StaticCompressor ----------------------------------------------
1971
1972/// A domain name compressor that doesn’t require an allocator.
1973///
1974/// This type wraps around an octets builder and implements domain name
1975/// compression. It does not require an allocator but because of that it
1976/// can only remember the position of up to 24 domain names. This should be
1977/// sufficient for most messages.
1978///
1979/// The position of a domain name is calculated relative to the beginning of
1980/// the underlying octets builder. This means that this builder must represent
1981/// the message only. This means that if you are using the [`StreamTarget`],
1982/// you need to place it inside this type, _not_ the other way around.
1983///
1984/// [`StreamTarget`]: struct.StreamTarget.html
1985#[derive(Clone, Debug)]
1986pub struct StaticCompressor<Target> {
1987 /// The underlying octets builder.
1988 target: Target,
1989
1990 /// The domain names we have encountered so far.
1991 ///
1992 /// The value is the position of the domain name within the message.
1993 entries: [u16; 24],
1994
1995 /// The number of entries in `entries`.
1996 len: usize,
1997}
1998
1999impl<Target> StaticCompressor<Target> {
2000 /// Creates a static compressor from an octets builder.
2001 pub fn new(target: Target) -> Self {
2002 StaticCompressor {
2003 target,
2004 entries: Default::default(),
2005 len: 0,
2006 }
2007 }
2008
2009 /// Returns a reference to the underlying octets builder.
2010 pub fn as_target(&self) -> &Target {
2011 &self.target
2012 }
2013
2014 /// Converts the static compressor into the underlying octets builder.
2015 pub fn into_target(self) -> Target {
2016 self.target
2017 }
2018
2019 /// Returns a reference to the octets slice of the content.
2020 pub fn as_slice(&self) -> &[u8]
2021 where
2022 Target: AsRef<[u8]>,
2023 {
2024 self.target.as_ref()
2025 }
2026
2027 /// Returns a reference to the octets slice of the content.
2028 pub fn as_slice_mut(&mut self) -> &mut [u8]
2029 where
2030 Target: AsMut<[u8]>,
2031 {
2032 self.target.as_mut()
2033 }
2034
2035 /// Returns a known position of a domain name if there is one.
2036 fn get<'a, N: Iterator<Item = &'a Label> + Clone>(
2037 &self,
2038 name: N,
2039 ) -> Option<u16>
2040 where
2041 Target: AsRef<[u8]>,
2042 {
2043 self.entries[..self.len].iter().find_map(|&pos| {
2044 if name
2045 .clone()
2046 .eq(Label::iter_slice(self.target.as_ref(), pos as usize))
2047 {
2048 Some(pos)
2049 } else {
2050 None
2051 }
2052 })
2053 }
2054
2055 /// Inserts the position of a new domain name if possible.
2056 fn insert(&mut self, pos: usize) -> bool {
2057 if pos < 0xc000 && self.len < self.entries.len() {
2058 self.entries[self.len] = pos as u16;
2059 self.len += 1;
2060 true
2061 } else {
2062 false
2063 }
2064 }
2065}
2066
2067//--- AsRef and AsMut
2068
2069impl<Target: AsRef<[u8]>> AsRef<[u8]> for StaticCompressor<Target> {
2070 fn as_ref(&self) -> &[u8] {
2071 self.as_slice()
2072 }
2073}
2074
2075impl<Target: AsMut<[u8]>> AsMut<[u8]> for StaticCompressor<Target> {
2076 fn as_mut(&mut self) -> &mut [u8] {
2077 self.as_slice_mut()
2078 }
2079}
2080
2081//--- OctetsBuilder
2082
2083impl<Target: OctetsBuilder> OctetsBuilder for StaticCompressor<Target> {
2084 type AppendError = Target::AppendError;
2085
2086 fn append_slice(
2087 &mut self,
2088 slice: &[u8],
2089 ) -> Result<(), Self::AppendError> {
2090 self.target.append_slice(slice)
2091 }
2092}
2093
2094impl<Target: Composer> Composer for StaticCompressor<Target> {
2095 fn append_compressed_name<N: ToName + ?Sized>(
2096 &mut self,
2097 name: &N,
2098 ) -> Result<(), Self::AppendError> {
2099 let mut name = name.iter_labels().peekable();
2100
2101 loop {
2102 // If the parent is root, just write that and return.
2103 // Because we do that, there will always be a label left here.
2104 if let Some(label) = name.peek() {
2105 if label.is_root() {
2106 label.compose(self)?;
2107 return Ok(());
2108 }
2109 }
2110
2111 // If we already know this name, append it as a compressed label.
2112 if let Some(pos) = self.get(name.clone()) {
2113 return (pos | 0xC000).compose(self);
2114 }
2115
2116 // So we don’t know the name. Try inserting it into the
2117 // compressor. If we can’t insert anymore, just write out what’s
2118 // left and return.
2119 if !self.insert(self.target.as_ref().len()) {
2120 for label in &mut name {
2121 label.compose(self)?;
2122 }
2123 return Ok(());
2124 }
2125
2126 // Advance to the parent.
2127 let label = name.next().unwrap();
2128 label.compose(self)?;
2129 }
2130 }
2131
2132 fn can_compress(&self) -> bool {
2133 true
2134 }
2135}
2136
2137impl<Target: Truncate> Truncate for StaticCompressor<Target> {
2138 fn truncate(&mut self, len: usize) {
2139 self.target.truncate(len);
2140 if len < 0xC000 {
2141 let len = len as u16;
2142 for i in 0..self.len {
2143 if self.entries[i] >= len {
2144 self.len = i;
2145 break;
2146 }
2147 }
2148 }
2149 }
2150}
2151
2152impl<Target: FreezeBuilder> FreezeBuilder for StaticCompressor<Target> {
2153 type Octets = Target::Octets;
2154
2155 fn freeze(self) -> Self::Octets {
2156 self.target.freeze()
2157 }
2158}
2159
2160//------------ TreeCompressor ------------------------------------------------
2161
2162/// A domain name compressor that uses a tree.
2163///
2164/// This type wraps around an octets builder and implements domain name
2165/// compression for it. It stores the position of any domain name it has seen
2166/// in a binary tree.
2167///
2168/// The position of a domain name is calculated relative to the beginning of
2169/// the underlying octets builder. This means that this builder must represent
2170/// the message only. This means that if you are using the [`StreamTarget`],
2171/// you need to place it inside this type, _not_ the other way around.
2172///
2173/// [`StreamTarget`]: struct.StreamTarget.html
2174#[cfg(feature = "std")]
2175#[derive(Clone, Debug)]
2176pub struct TreeCompressor<Target> {
2177 /// The underlying octetsbuilder.
2178 target: Target,
2179
2180 /// The topmost node of our tree.
2181 start: Node,
2182}
2183
2184/// A node in our tree.
2185///
2186/// The tree is a bit odd. It follows the labels of the domain names from the
2187/// root towards the left. The root node is for the root label. It contains a
2188/// map that maps all the labels encountered to the immediate left of the
2189/// name traced by this path through the tree to a node for the name resulting
2190/// by adding this label to the name constructed so far.
2191///
2192/// Each node also contains the position of that name in the message.
2193#[cfg(feature = "std")]
2194#[derive(Clone, Debug, Default)]
2195struct Node {
2196 /// The labels immediately to the left of this name and their nodes.
2197 parents: HashMap<Array<64>, Self>,
2198
2199 /// The position of this name in the message.
2200 value: Option<u16>,
2201}
2202
2203#[cfg(feature = "std")]
2204impl Node {
2205 fn drop_above(&mut self, len: u16) {
2206 self.value = match self.value {
2207 Some(value) if value < len => Some(value),
2208 _ => None,
2209 };
2210 self.parents
2211 .values_mut()
2212 .for_each(|node| node.drop_above(len))
2213 }
2214}
2215
2216#[cfg(feature = "std")]
2217impl<Target> TreeCompressor<Target> {
2218 /// Creates a new compressor from an underlying octets builder.
2219 pub fn new(target: Target) -> Self {
2220 TreeCompressor {
2221 target,
2222 start: Default::default(),
2223 }
2224 }
2225
2226 /// Returns a reference to the underlying octets builder.
2227 pub fn as_target(&self) -> &Target {
2228 &self.target
2229 }
2230
2231 /// Converts the compressor into the underlying octets builder.
2232 pub fn into_target(self) -> Target {
2233 self.target
2234 }
2235
2236 /// Returns an octets slice of the data.
2237 pub fn as_slice(&self) -> &[u8]
2238 where
2239 Target: AsRef<[u8]>,
2240 {
2241 self.target.as_ref()
2242 }
2243
2244 /// Returns an mutable octets slice of the data.
2245 pub fn as_slice_mut(&mut self) -> &mut [u8]
2246 where
2247 Target: AsMut<[u8]>,
2248 {
2249 self.target.as_mut()
2250 }
2251
2252 fn get<'a, N: Iterator<Item = &'a Label> + Clone>(
2253 &self,
2254 name: N,
2255 ) -> Option<u16> {
2256 let mut node = &self.start;
2257 for label in name {
2258 if label.is_root() {
2259 return node.value;
2260 }
2261 node = node.parents.get(label.as_ref())?;
2262 }
2263 None
2264 }
2265
2266 fn insert<'a, N: Iterator<Item = &'a Label> + Clone>(
2267 &mut self,
2268 name: N,
2269 pos: usize,
2270 ) -> bool {
2271 if pos >= 0xC000 {
2272 return false;
2273 }
2274 let pos = pos as u16;
2275 let mut node = &mut self.start;
2276 for label in name {
2277 if label.is_root() {
2278 node.value = Some(pos);
2279 break;
2280 }
2281 node = node
2282 .parents
2283 .entry(label.as_ref().try_into().unwrap())
2284 .or_default();
2285 }
2286 true
2287 }
2288}
2289
2290//--- AsRef, AsMut, and OctetsBuilder
2291
2292#[cfg(feature = "std")]
2293impl<Target: AsRef<[u8]>> AsRef<[u8]> for TreeCompressor<Target> {
2294 fn as_ref(&self) -> &[u8] {
2295 self.as_slice()
2296 }
2297}
2298
2299#[cfg(feature = "std")]
2300impl<Target: AsMut<[u8]>> AsMut<[u8]> for TreeCompressor<Target> {
2301 fn as_mut(&mut self) -> &mut [u8] {
2302 self.as_slice_mut()
2303 }
2304}
2305
2306#[cfg(feature = "std")]
2307impl<Target: OctetsBuilder> OctetsBuilder for TreeCompressor<Target> {
2308 type AppendError = Target::AppendError;
2309
2310 fn append_slice(
2311 &mut self,
2312 slice: &[u8],
2313 ) -> Result<(), Self::AppendError> {
2314 self.target.append_slice(slice)
2315 }
2316}
2317
2318#[cfg(feature = "std")]
2319impl<Target: Composer> Composer for TreeCompressor<Target> {
2320 fn append_compressed_name<N: ToName + ?Sized>(
2321 &mut self,
2322 name: &N,
2323 ) -> Result<(), Self::AppendError> {
2324 let mut name = name.iter_labels().peekable();
2325
2326 loop {
2327 // If the parent is root, just write that and return.
2328 // Because we do that, there will always be a label left here.
2329 if let Some(label) = name.peek() {
2330 if label.is_root() {
2331 label.compose(self)?;
2332 return Ok(());
2333 }
2334 }
2335
2336 // If we already know this name, append it as a compressed label.
2337 if let Some(pos) = self.get(name.clone()) {
2338 return (pos | 0xC000).compose(self);
2339 }
2340
2341 // So we don’t know the name. Try inserting it into the
2342 // compressor. If we can’t insert anymore, just write out what’s
2343 // left and return.
2344 if !self.insert(name.clone(), self.target.as_ref().len()) {
2345 for label in &mut name {
2346 label.compose(self)?;
2347 }
2348 return Ok(());
2349 }
2350
2351 // Advance to the parent. If the parent is root, just write that
2352 // and return. Because we do that, there will always be a label
2353 // left here.
2354 let label = name.next().unwrap();
2355 label.compose(self)?;
2356 }
2357 }
2358
2359 fn can_compress(&self) -> bool {
2360 true
2361 }
2362}
2363
2364#[cfg(feature = "std")]
2365impl<Target: Composer> Truncate for TreeCompressor<Target> {
2366 fn truncate(&mut self, len: usize) {
2367 self.target.truncate(len);
2368 if len < 0xC000 {
2369 self.start.drop_above(len as u16)
2370 }
2371 }
2372}
2373
2374//------------ HashCompressor ------------------------------------------------
2375
2376/// A domain name compressor that uses a hash table.
2377///
2378/// This type wraps around an octets builder and implements domain name
2379/// compression for it. It stores the position of any domain name it has seen
2380/// in a hash table.
2381///
2382/// The position of a domain name is calculated relative to the beginning of
2383/// the underlying octets builder. This means that this builder must represent
2384/// the message only. This means that if you are using the [`StreamTarget`],
2385/// you need to place it inside this type, _not_ the other way around.
2386///
2387/// [`StreamTarget`]: struct.StreamTarget.html
2388#[cfg(feature = "std")]
2389#[derive(Clone, Debug)]
2390pub struct HashCompressor<Target> {
2391 /// The underlying octetsbuilder.
2392 target: Target,
2393
2394 /// The names inserted into the message.
2395 ///
2396 /// Consider a set of names, where the "parent" (i.e. tail) of each name is
2397 /// another name in the set. For example, a set might contain `.`, `org.`,
2398 /// `example.org.`, and `www.example.org.`. Each of these names (except the
2399 /// root, which is handled specially) is stored as a separate entry in this
2400 /// hash table. A name `<head>.<tail>` is stored as the index of `<head>`
2401 /// and the index of `<tail>` in the built message. Its hash is built from
2402 /// `<head>` (the bytes in the label, not the index into the message) and
2403 /// the index of `<tail>`.
2404 ///
2405 /// Lookups are performed by iterating backward through the labels in a name
2406 /// (to go from the root outward). At each step, the canonical position of
2407 /// `<tail>` is already known; it is hashed together with the next label and
2408 /// searched for in the hash table. An entry with a matching `<head>` (i.e.
2409 /// where the referenced content in the message matches the searched label)
2410 /// and a matching `<tail>` position represents the same name.
2411 ///
2412 /// The root is handled specially. It is never inserted in the hash table,
2413 /// and instead has a fixed fake position in the message of 0xFFFF. That is
2414 /// the initial value that lookups start with.
2415 ///
2416 /// As an example, consider a message `org. example.org. www.example.org.`.
2417 /// In the hash table, the first two entries will look like:
2418 ///
2419 /// ```text
2420 /// - head=0 ("org") tail=0xFFFF
2421 /// - head=5 ("example") tail=0
2422 /// ```
2423 ///
2424 /// Now, to insert `www.example.org.`, the lookup begins from the end. We
2425 /// search for a label "org" with tail 0xFFFF, and find head=0. We set this
2426 /// as the next tail, and search for label "example" to find head=5. Since
2427 /// a label "www" with tail=5 is not already in the hash table, it will be
2428 /// inserted with head=18.
2429 ///
2430 /// This has a space overhead of 4-5 bytes for each entry, accounting for
2431 /// the load factor (which appears to be 87.5%). Technically, storing the
2432 /// labels indirectly means that comparisons are more expensive; but most
2433 /// labels are relatively short and storing them inline as 64-byte arrays
2434 /// would be quite wasteful.
2435 names: HashTable<HashEntry>,
2436
2437 /// How names in the table are hashed.
2438 hasher: RandomState,
2439}
2440
2441#[cfg(feature = "std")]
2442#[derive(Copy, Clone, Debug)]
2443struct HashEntry {
2444 /// The position of the head label in the name.
2445 head: u16,
2446
2447 /// The position of the tail name.
2448 tail: u16,
2449}
2450
2451#[cfg(feature = "std")]
2452impl HashEntry {
2453 /// Try constructing a [`HashEntry`].
2454 fn new(head: usize, tail: usize) -> Option<Self> {
2455 if head < 0xC000 {
2456 Some(Self {
2457 head: head as u16,
2458 tail: tail as u16,
2459 })
2460 } else {
2461 None
2462 }
2463 }
2464
2465 /// Get the head label for this entry.
2466 fn head<'m>(&self, message: &'m [u8]) -> &'m Label {
2467 Label::split_from(&message[self.head as usize..])
2468 .expect("the message contains valid labels")
2469 .0
2470 }
2471
2472 /// Compute the hash of this entry.
2473 fn hash(&self, message: &[u8], hasher: &RandomState) -> u64 {
2474 hasher.hash_one((self.head(message), self.tail))
2475 }
2476
2477 /// Compare this entry to a label.
2478 fn eq(&self, message: &[u8], query: (&Label, u16)) -> bool {
2479 (self.head(message), self.tail) == query
2480 }
2481}
2482
2483#[cfg(feature = "std")]
2484impl<Target> HashCompressor<Target> {
2485 /// Creates a new compressor from an underlying octets builder.
2486 pub fn new(target: Target) -> Self {
2487 HashCompressor {
2488 target,
2489 names: Default::default(),
2490 hasher: Default::default(),
2491 }
2492 }
2493
2494 /// Returns a reference to the underlying octets builder.
2495 pub fn as_target(&self) -> &Target {
2496 &self.target
2497 }
2498
2499 /// Converts the compressor into the underlying octets builder.
2500 pub fn into_target(self) -> Target {
2501 self.target
2502 }
2503
2504 /// Returns an octets slice of the data.
2505 pub fn as_slice(&self) -> &[u8]
2506 where
2507 Target: AsRef<[u8]>,
2508 {
2509 self.target.as_ref()
2510 }
2511
2512 /// Returns an mutable octets slice of the data.
2513 pub fn as_slice_mut(&mut self) -> &mut [u8]
2514 where
2515 Target: AsMut<[u8]>,
2516 {
2517 self.target.as_mut()
2518 }
2519}
2520
2521//--- AsRef, AsMut, and OctetsBuilder
2522
2523#[cfg(feature = "std")]
2524impl<Target: AsRef<[u8]>> AsRef<[u8]> for HashCompressor<Target> {
2525 fn as_ref(&self) -> &[u8] {
2526 self.as_slice()
2527 }
2528}
2529
2530#[cfg(feature = "std")]
2531impl<Target: AsMut<[u8]>> AsMut<[u8]> for HashCompressor<Target> {
2532 fn as_mut(&mut self) -> &mut [u8] {
2533 self.as_slice_mut()
2534 }
2535}
2536
2537#[cfg(feature = "std")]
2538impl<Target: OctetsBuilder> OctetsBuilder for HashCompressor<Target> {
2539 type AppendError = Target::AppendError;
2540
2541 fn append_slice(
2542 &mut self,
2543 slice: &[u8],
2544 ) -> Result<(), Self::AppendError> {
2545 self.target.append_slice(slice)
2546 }
2547}
2548
2549#[cfg(feature = "std")]
2550impl<Target: Composer> Composer for HashCompressor<Target> {
2551 fn append_compressed_name<N: ToName + ?Sized>(
2552 &mut self,
2553 name: &N,
2554 ) -> Result<(), Self::AppendError> {
2555 let mut name = name.iter_labels();
2556 let message = self.target.as_ref();
2557
2558 // Remove the root label -- we know it's there.
2559 assert!(
2560 name.next_back().is_some_and(|l| l.is_root()),
2561 "absolute names must end with a root label"
2562 );
2563
2564 // The position of the consumed labels from the end of the name.
2565 let mut position = 0xFFFF;
2566
2567 // The last label that must be inserted, if any.
2568 let mut last_label = None;
2569
2570 // Look up each label in reverse order.
2571 while let Some(label) = name.next_back() {
2572 // Look up the labels seen thus far in the hash table.
2573 let query = (label, position);
2574 let hash = self.hasher.hash_one(query);
2575
2576 let entry =
2577 self.names.find(hash, |&name| name.eq(message, query));
2578 if let Some(entry) = entry {
2579 // We found a match, so update the position.
2580 position = entry.head;
2581 } else {
2582 // We will have to write this label.
2583 last_label = Some(label);
2584 break;
2585 }
2586 }
2587
2588 // Write out the remaining labels in the name in regular order.
2589 let mut labels = name.chain(last_label).peekable();
2590 while let Some(label) = labels.next() {
2591 let head = self.target.as_ref().len();
2592 let tail = head + label.compose_len() as usize;
2593
2594 label.compose(self)?;
2595
2596 // Remember this label for future compression, if possible.
2597 //
2598 // If some labels in this name pass the 0xC000 boundary point, then
2599 // none of its remembered labels can be used (since they are looked
2600 // up from right to left, and the rightmost ones will fail first).
2601 // We could check more thoroughly for this, but it's not worth it.
2602 if let Some(mut entry) = HashEntry::new(head, tail) {
2603 // If there is no following label, use the remaining position.
2604 if labels.peek().is_none() {
2605 entry.tail = position;
2606 }
2607
2608 let message = self.target.as_ref();
2609 let hasher = &self.hasher;
2610 let hash = entry.hash(message, hasher);
2611 self.names.insert_unique(hash, entry, |&name| {
2612 name.hash(message, hasher)
2613 });
2614 }
2615 }
2616
2617 // Write the compressed pointer or the root label.
2618 if position != 0xFFFF {
2619 (position | 0xC000).compose(self)
2620 } else {
2621 Label::root().compose(self)
2622 }
2623 }
2624
2625 fn can_compress(&self) -> bool {
2626 true
2627 }
2628}
2629
2630#[cfg(feature = "std")]
2631impl<Target: Composer> Truncate for HashCompressor<Target> {
2632 fn truncate(&mut self, len: usize) {
2633 self.target.truncate(len);
2634 if len < 0xC000 {
2635 self.names.retain(|name| name.head < len as u16);
2636 }
2637 }
2638}
2639
2640//============ Errors ========================================================
2641
2642#[derive(Clone, Copy, Debug)]
2643pub enum PushError {
2644 CountOverflow,
2645 ShortBuf,
2646}
2647
2648impl<T: Into<ShortBuf>> From<T> for PushError {
2649 fn from(_: T) -> Self {
2650 Self::ShortBuf
2651 }
2652}
2653
2654impl fmt::Display for PushError {
2655 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2656 match *self {
2657 PushError::CountOverflow => f.write_str("counter overflow"),
2658 PushError::ShortBuf => ShortBuf.fmt(f),
2659 }
2660 }
2661}
2662
2663#[cfg(feature = "std")]
2664impl std::error::Error for PushError {}
2665
2666//============ Testing =======================================================
2667
2668#[cfg(test)]
2669#[cfg(feature = "std")]
2670mod test {
2671 use super::*;
2672 use crate::base::opt;
2673 use crate::base::{Name, Serial, Ttl};
2674 use crate::rdata::{Ns, Soa, A};
2675 use core::str::FromStr;
2676
2677 #[test]
2678 fn message_builder() {
2679 // Make a domain name we can use later on.
2680 let name = Name::<Vec<u8>>::from_str("example.com").unwrap();
2681
2682 // Create a message builder wrapping a compressor wrapping a stream
2683 // target.
2684 let mut msg = MessageBuilder::from_target(StaticCompressor::new(
2685 StreamTarget::new_vec(),
2686 ))
2687 .unwrap();
2688
2689 // Set the RD bit in the header and proceed to the question section.
2690 msg.header_mut().set_rd(true);
2691 let mut msg = msg.question();
2692
2693 // Add a question and proceed to the answer section.
2694 msg.push((&name, Rtype::A)).unwrap();
2695 let mut msg = msg.answer();
2696
2697 // Add two answer and proceed to the additional sections
2698 msg.push((&name, 86400, A::from_octets(192, 0, 2, 1)))
2699 .unwrap();
2700 msg.push((&name, 86400, A::from_octets(192, 0, 2, 2)))
2701 .unwrap();
2702
2703 // Add an authority
2704 let mut msg = msg.authority();
2705 msg.push((&name, 0, Ns::from(name.clone()))).unwrap();
2706
2707 // Add additional
2708 let mut msg = msg.additional();
2709 msg.push((&name, 86400, A::from_octets(192, 0, 2, 1)))
2710 .unwrap();
2711
2712 // Convert the builder into the actual message.
2713 let target = msg.finish().into_target();
2714
2715 // Reparse message and check contents
2716 let msg = Message::from_octets(target.as_dgram_slice()).unwrap();
2717 let q = msg.first_question().unwrap();
2718 assert_eq!(q.qname(), &name);
2719 assert_eq!(q.qtype(), Rtype::A);
2720
2721 let section = msg.answer().unwrap();
2722 let mut records = section.limit_to::<A>();
2723 assert_eq!(
2724 records.next().unwrap().unwrap().data(),
2725 &A::from_octets(192, 0, 2, 1)
2726 );
2727 assert_eq!(
2728 records.next().unwrap().unwrap().data(),
2729 &A::from_octets(192, 0, 2, 2)
2730 );
2731
2732 let section = msg.authority().unwrap();
2733 let mut records = section.limit_to::<Ns<_>>();
2734 let rr = records.next().unwrap().unwrap();
2735 assert_eq!(rr.owner(), &name);
2736 assert_eq!(rr.data().nsdname(), &name);
2737
2738 let section = msg.additional().unwrap();
2739 let mut records = section.limit_to::<A>();
2740 let rr = records.next().unwrap().unwrap();
2741 assert_eq!(rr.owner(), &name);
2742 assert_eq!(rr.data(), &A::from_octets(192, 0, 2, 1));
2743 }
2744
2745 #[cfg(feature = "heapless")]
2746 #[test]
2747 fn exceed_limits() {
2748 // Create a limited message builder.
2749 let buf = heapless::Vec::<u8, 100>::new();
2750
2751 // Initialize it with a message header (12 bytes)
2752 let mut msg = MessageBuilder::from_target(buf).unwrap();
2753 let hdr_len = msg.as_slice().len();
2754
2755 // Add some bytes.
2756 msg.push(|t| t.append_slice(&[0u8; 50]), |_| Ok(()))
2757 .unwrap();
2758 assert_eq!(msg.as_slice().len(), hdr_len + 50);
2759
2760 // Set a push limit below the current length.
2761 msg.set_push_limit(25);
2762
2763 // Verify that push fails.
2764 assert!(msg.push(|t| t.append_slice(&[0u8; 1]), |_| Ok(())).is_err());
2765 assert_eq!(msg.as_slice().len(), hdr_len + 50);
2766
2767 // Remove the limit.
2768 msg.clear_push_limit();
2769
2770 // Verify that push up until capacity succeeds.
2771 for _ in (hdr_len + 50)..100 {
2772 msg.push(|t| t.append_slice(&[0u8; 1]), |_| Ok(())).unwrap();
2773 }
2774 assert_eq!(msg.as_slice().len(), 100);
2775
2776 // Verify that exceeding the underlying capacity limit fails.
2777 assert!(msg.push(|t| t.append_slice(&[0u8; 1]), |_| Ok(())).is_err());
2778 assert_eq!(msg.as_slice().len(), 100);
2779 }
2780
2781 #[test]
2782 fn opt_builder() {
2783 let mut msg = MessageBuilder::new_vec().additional();
2784
2785 // Add an OPT record.
2786 let nsid = opt::nsid::Nsid::from_octets(&b"example"[..]).unwrap();
2787 msg.opt(|o| {
2788 o.set_udp_payload_size(4096);
2789 o.push(&nsid)?;
2790 Ok(())
2791 })
2792 .unwrap();
2793
2794 let msg = msg.finish();
2795 println!("{:?}", msg);
2796 let msg = Message::from_octets(msg).unwrap();
2797 let opt = msg.opt().unwrap();
2798
2799 // Check options
2800 assert_eq!(opt.udp_payload_size(), 4096);
2801 let mut opts = opt.opt().iter::<opt::nsid::Nsid<_>>();
2802 assert_eq!(opts.next(), Some(Ok(nsid)));
2803 }
2804
2805 fn create_compressed<T: Composer>(target: T) -> T
2806 where
2807 T::AppendError: fmt::Debug,
2808 {
2809 let mut msg = MessageBuilder::from_target(target).unwrap().question();
2810 msg.header_mut().set_rcode(Rcode::NXDOMAIN);
2811 msg.header_mut().set_rd(true);
2812 msg.header_mut().set_ra(true);
2813 msg.header_mut().set_qr(true);
2814
2815 msg.push((&"example".parse::<Name<Vec<u8>>>().unwrap(), Rtype::NS))
2816 .unwrap();
2817 let mut msg = msg.authority();
2818
2819 let mname: Name<Vec<u8>> = "a.root-servers.net".parse().unwrap();
2820 let rname = "nstld.verisign-grs.com".parse().unwrap();
2821 msg.push((
2822 Name::root_slice(),
2823 86390,
2824 Soa::new(
2825 mname,
2826 rname,
2827 Serial(2020081701),
2828 Ttl::from_secs(1800),
2829 Ttl::from_secs(900),
2830 Ttl::from_secs(604800),
2831 Ttl::from_secs(86400),
2832 ),
2833 ))
2834 .unwrap();
2835 msg.finish()
2836 }
2837
2838 #[test]
2839 fn compressor() {
2840 // An example negative response to `example. NS` with an SOA to test
2841 // various compressed name situations.
2842 let expect = &[
2843 0x00, 0x00, 0x81, 0x83, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00,
2844 0x00, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x00, 0x00,
2845 0x02, 0x00, 0x01, 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, 0x01, 0x51,
2846 0x76, 0x00, 0x40, 0x01, 0x61, 0x0c, 0x72, 0x6f, 0x6f, 0x74, 0x2d,
2847 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x03, 0x6e, 0x65, 0x74,
2848 0x00, 0x05, 0x6e, 0x73, 0x74, 0x6c, 0x64, 0x0c, 0x76, 0x65, 0x72,
2849 0x69, 0x73, 0x69, 0x67, 0x6e, 0x2d, 0x67, 0x72, 0x73, 0x03, 0x63,
2850 0x6f, 0x6d, 0x00, 0x78, 0x68, 0x00, 0x25, 0x00, 0x00, 0x07, 0x08,
2851 0x00, 0x00, 0x03, 0x84, 0x00, 0x09, 0x3a, 0x80, 0x00, 0x01, 0x51,
2852 0x80,
2853 ];
2854
2855 let msg = create_compressed(StaticCompressor::new(Vec::new()));
2856 assert_eq!(&expect[..], msg.as_ref());
2857
2858 let msg = create_compressed(TreeCompressor::new(Vec::new()));
2859 assert_eq!(&expect[..], msg.as_ref());
2860 }
2861
2862 #[test]
2863 fn compress_positive_response() {
2864 // An example positive response to `A example.com.` that is compressed
2865 //
2866 // ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 0
2867 // ;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
2868 //
2869 // ;; QUESTION SECTION:
2870 // ;example.com. IN A
2871 //
2872 // ;; ANSWER SECTION:
2873 // example.com. 3600 IN A 203.0.113.1
2874 //
2875 // ;; MSG SIZE rcvd: 45
2876 let expect = &[
2877 0x00, 0x00, 0x81, 0xa0, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
2878 0x00, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x03, 0x63,
2879 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01, 0xc0, 0x0c, 0x00, 0x01,
2880 0x00, 0x01, 0x00, 0x00, 0x0e, 0x10, 0x00, 0x04, 0xcb, 0x00, 0x71,
2881 0x01,
2882 ];
2883
2884 let name = "example.com.".parse::<Name<Vec<u8>>>().unwrap();
2885 let mut msg =
2886 MessageBuilder::from_target(StaticCompressor::new(Vec::new()))
2887 .unwrap()
2888 .question();
2889 msg.header_mut().set_rcode(Rcode::NOERROR);
2890 msg.header_mut().set_rd(true);
2891 msg.header_mut().set_ra(true);
2892 msg.header_mut().set_qr(true);
2893 msg.header_mut().set_ad(true);
2894
2895 // Question
2896 msg.push((name.clone(), Rtype::A)).unwrap();
2897
2898 // Answer
2899 let mut msg = msg.answer();
2900 msg.push((name.clone(), 3600, A::from_octets(203, 0, 113, 1)))
2901 .unwrap();
2902
2903 let actual = msg.finish().into_target();
2904 assert_eq!(45, actual.len(), "unexpected response size");
2905 assert_eq!(expect[..], actual, "unexpected response data");
2906 }
2907
2908 #[cfg(feature = "std")]
2909 #[test]
2910 fn hash_compress_positive_response() {
2911 // An example positive response to `A example.com.` that is compressed
2912 //
2913 // ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 0
2914 // ;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
2915 //
2916 // ;; QUESTION SECTION:
2917 // ;example.com. IN A
2918 //
2919 // ;; ANSWER SECTION:
2920 // example.com. 3600 IN A 203.0.113.1
2921 //
2922 // ;; MSG SIZE rcvd: 45
2923 let expect = &[
2924 0x00, 0x00, 0x81, 0xa0, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
2925 0x00, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x03, 0x63,
2926 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01, 0xc0, 0x0c, 0x00, 0x01,
2927 0x00, 0x01, 0x00, 0x00, 0x0e, 0x10, 0x00, 0x04, 0xcb, 0x00, 0x71,
2928 0x01,
2929 ];
2930
2931 let name = "example.com.".parse::<Name<Vec<u8>>>().unwrap();
2932 let mut msg =
2933 MessageBuilder::from_target(HashCompressor::new(Vec::new()))
2934 .unwrap()
2935 .question();
2936 msg.header_mut().set_rcode(Rcode::NOERROR);
2937 msg.header_mut().set_rd(true);
2938 msg.header_mut().set_ra(true);
2939 msg.header_mut().set_qr(true);
2940 msg.header_mut().set_ad(true);
2941
2942 // Question
2943 msg.push((name.clone(), Rtype::A)).unwrap();
2944
2945 // Answer
2946 let mut msg = msg.answer();
2947 msg.push((name.clone(), 3600, A::from_octets(203, 0, 113, 1)))
2948 .unwrap();
2949
2950 let actual = msg.finish().into_target();
2951 assert_eq!(45, actual.len(), "unexpected response size");
2952 assert_eq!(expect[..], actual, "unexpected response data");
2953 }
2954}