xref: /webrtc/mdns/src/message/header.rs (revision 7ceeeeb0)
1 use super::*;
2 
3 // Header is a representation of a DNS message header.
4 #[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
5 pub struct Header {
6     pub id: u16,
7     pub response: bool,
8     pub op_code: OpCode,
9     pub authoritative: bool,
10     pub truncated: bool,
11     pub recursion_desired: bool,
12     pub recursion_available: bool,
13     pub rcode: RCode,
14 }
15 
16 impl fmt::Display for Header {
17     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
18         write!(
19             f,
20             "dnsmessage.Header{{id: {}, response: {}, op_code: {}, authoritative: {}, truncated: {}, recursion_desired: {}, recursion_available: {}, rcode: {} }}",
21             self.id,
22             self.response,
23             self.op_code,
24             self.authoritative,
25             self.truncated,
26             self.recursion_desired,
27             self.recursion_available,
28             self.rcode
29         )
30     }
31 }
32 
33 impl Header {
34     pub fn pack(&self) -> (u16, u16) {
35         let id = self.id;
36         let mut bits = (self.op_code as u16) << 11 | self.rcode as u16;
37         if self.recursion_available {
38             bits |= HEADER_BIT_RA
39         }
40         if self.recursion_desired {
41             bits |= HEADER_BIT_RD
42         }
43         if self.truncated {
44             bits |= HEADER_BIT_TC
45         }
46         if self.authoritative {
47             bits |= HEADER_BIT_AA
48         }
49         if self.response {
50             bits |= HEADER_BIT_QR
51         }
52 
53         (id, bits)
54     }
55 }
56 
57 #[derive(Copy, Clone, PartialOrd, PartialEq, Eq)]
58 pub enum Section {
59     NotStarted = 0,
60     Header = 1,
61     Questions = 2,
62     Answers = 3,
63     Authorities = 4,
64     Additionals = 5,
65     Done = 6,
66 }
67 
68 impl Default for Section {
69     fn default() -> Self {
70         Section::NotStarted
71     }
72 }
73 
74 impl From<u8> for Section {
75     fn from(v: u8) -> Self {
76         match v {
77             0 => Section::NotStarted,
78             1 => Section::Header,
79             2 => Section::Questions,
80             3 => Section::Answers,
81             4 => Section::Authorities,
82             5 => Section::Additionals,
83             _ => Section::Done,
84         }
85     }
86 }
87 
88 impl fmt::Display for Section {
89     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
90         let s = match *self {
91             Section::NotStarted => "NotStarted",
92             Section::Header => "Header",
93             Section::Questions => "question",
94             Section::Answers => "answer",
95             Section::Authorities => "authority",
96             Section::Additionals => "additional",
97             Section::Done => "Done",
98         };
99         write!(f, "{}", s)
100     }
101 }
102 
103 // header is the wire format for a DNS message header.
104 #[derive(Default)]
105 pub struct HeaderInternal {
106     pub id: u16,
107     pub bits: u16,
108     pub questions: u16,
109     pub answers: u16,
110     pub authorities: u16,
111     pub additionals: u16,
112 }
113 
114 impl HeaderInternal {
115     pub(crate) fn count(&self, sec: Section) -> u16 {
116         match sec {
117             Section::Questions => self.questions,
118             Section::Answers => self.answers,
119             Section::Authorities => self.authorities,
120             Section::Additionals => self.additionals,
121             _ => 0,
122         }
123     }
124 
125     // pack appends the wire format of the header to msg.
126     pub(crate) fn pack(&self, mut msg: Vec<u8>) -> Vec<u8> {
127         msg = pack_uint16(msg, self.id);
128         msg = pack_uint16(msg, self.bits);
129         msg = pack_uint16(msg, self.questions);
130         msg = pack_uint16(msg, self.answers);
131         msg = pack_uint16(msg, self.authorities);
132         msg = pack_uint16(msg, self.additionals);
133         msg
134     }
135 
136     pub(crate) fn unpack(&mut self, msg: &[u8], off: usize) -> Result<usize> {
137         let (id, off) = unpack_uint16(msg, off)?;
138         self.id = id;
139 
140         let (bits, off) = unpack_uint16(msg, off)?;
141         self.bits = bits;
142 
143         let (questions, off) = unpack_uint16(msg, off)?;
144         self.questions = questions;
145 
146         let (answers, off) = unpack_uint16(msg, off)?;
147         self.answers = answers;
148 
149         let (authorities, off) = unpack_uint16(msg, off)?;
150         self.authorities = authorities;
151 
152         let (additionals, off) = unpack_uint16(msg, off)?;
153         self.additionals = additionals;
154 
155         Ok(off)
156     }
157 
158     pub(crate) fn header(&self) -> Header {
159         Header {
160             id: self.id,
161             response: (self.bits & HEADER_BIT_QR) != 0,
162             op_code: ((self.bits >> 11) & 0xF) as OpCode,
163             authoritative: (self.bits & HEADER_BIT_AA) != 0,
164             truncated: (self.bits & HEADER_BIT_TC) != 0,
165             recursion_desired: (self.bits & HEADER_BIT_RD) != 0,
166             recursion_available: (self.bits & HEADER_BIT_RA) != 0,
167             rcode: RCode::from((self.bits & 0xF) as u8),
168         }
169     }
170 }
171