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