toe_beans/v4/message/
message.rs1use super::*;
2use crate::v4::error::Result;
3use mac_address::MacAddress;
4use std::net::Ipv4Addr;
5
6#[derive(Debug, PartialEq)]
38pub struct Message {
39 pub op: Ops,
41 pub htype: HTypes,
43 pub hlen: u8,
45 pub hops: u8,
47 pub xid: u32,
49 pub secs: u16,
51 pub flags: Flags,
53 pub ciaddr: Ipv4Addr,
55 pub yiaddr: Ipv4Addr,
57 pub siaddr: Ipv4Addr,
59 pub giaddr: Ipv4Addr,
61 pub chaddr: [u8; 16],
65 pub sname: SName,
67 pub file: File,
69 pub magic: [u8; 4],
71 pub options: Vec<MessageOptions>,
75}
76
77pub const MAGIC: [u8; 4] = [99, 130, 83, 99];
79
80impl Deliverable for Message {}
81
82impl MessageHelpers for Message {
83 fn find_option(&self, tag: u8) -> Option<&MessageOptions> {
85 self.options.iter().find(|&option| option.to_tag() == tag)
86 }
87
88 fn add_option(&mut self, option: MessageOptions) {
89 self.options.push(option);
90 }
91
92 fn get_mac_address(&self) -> MacAddress {
93 MacAddress::new([
94 self.chaddr[0],
95 self.chaddr[1],
96 self.chaddr[2],
97 self.chaddr[3],
98 self.chaddr[4],
99 self.chaddr[5],
100 ])
101 }
102}
103
104impl DecodeMessage for Message {
105 type Op = Ops;
106 type Htype = HTypes;
107 type Hlen = u8;
108 type Hops = u8;
109 type Xid = u32;
110 type Secs = u16;
111 type Flags = Flags;
112 type Ciaddr = Ipv4Addr;
113 type Yiaddr = Ipv4Addr;
114 type Siaddr = Ipv4Addr;
115 type Giaddr = Ipv4Addr;
116 type Chaddr = [u8; 16];
117 type Sname = SName;
118 type File = File;
119 type Magic = [u8; 4];
120 type Options = Vec<MessageOptions>;
121
122 type Output = Self;
123
124 fn decode_op(op: &[u8]) -> Self::Op {
125 Self::Op::from(op)
126 }
127
128 fn decode_htype(htype: &[u8]) -> Self::Htype {
129 Self::Htype::from(htype)
130 }
131
132 fn decode_hlen(hlen: &[u8]) -> Self::Hlen {
133 hlen[0]
134 }
135
136 fn decode_hops(hops: &[u8]) -> Self::Hops {
137 hops[0]
138 }
139
140 fn decode_xid(xid: &[u8]) -> Self::Xid {
141 let bytes: [u8; 4] = xid.try_into().unwrap();
142 u32::from_be_bytes(bytes)
143 }
144
145 fn decode_secs(secs: &[u8]) -> Self::Secs {
146 let bytes: [u8; 2] = secs.try_into().unwrap();
147 u16::from_be_bytes(bytes)
148 }
149
150 fn decode_flags(flags: &[u8]) -> Self::Flags {
151 let byte = flags[0];
152 let broadcast = byte & 0b10000000 == 0b10000000;
153 Flags { broadcast }
154 }
155
156 fn decode_ciaddr(ciaddr: &[u8]) -> Self::Ciaddr {
157 let bytes: [u8; 4] = ciaddr.try_into().unwrap();
158 Ipv4Addr::from(bytes)
159 }
160
161 fn decode_yiaddr(yiaddr: &[u8]) -> Self::Yiaddr {
162 let bytes: [u8; 4] = yiaddr.try_into().unwrap();
163 Ipv4Addr::from(bytes)
164 }
165
166 fn decode_siaddr(siaddr: &[u8]) -> Self::Siaddr {
167 let bytes: [u8; 4] = siaddr.try_into().unwrap();
168 Ipv4Addr::from(bytes)
169 }
170
171 fn decode_giaddr(giaddr: &[u8]) -> Self::Giaddr {
172 let bytes: [u8; 4] = giaddr.try_into().unwrap();
173 Ipv4Addr::from(bytes)
174 }
175
176 fn decode_chaddr(chaddr: &[u8]) -> Self::Chaddr {
177 let bytes: [u8; 16] = chaddr.try_into().unwrap();
178 bytes
179 }
180
181 fn decode_sname(sname: &[u8]) -> Self::Sname {
182 SName::from_slice_unchecked(sname)
183 }
184
185 fn decode_file(file: &[u8]) -> Self::File {
186 File::from_slice_unchecked(file)
187 }
188
189 fn decode_magic(_magic: &[u8]) -> Self::Magic {
190 MAGIC
191 }
192
193 fn decode_options(options: &[u8]) -> Self::Options {
194 MessageOptions::from_bytes(options)
195 }
196
197 fn from_bytes(input: &[u8]) -> Result<Self::Output> {
198 let slicer = MessageSlicer::new(input)?;
199
200 Ok(Message {
201 op: Self::decode_op(slicer.parse_op()),
202 htype: Self::decode_htype(slicer.parse_htype()),
203 hlen: Self::decode_hlen(slicer.parse_hlen()),
204 hops: Self::decode_hops(slicer.parse_hops()),
205 xid: Self::decode_xid(slicer.parse_xid()),
206 secs: Self::decode_secs(slicer.parse_secs()),
207 flags: Self::decode_flags(slicer.parse_flags()),
208 ciaddr: Self::decode_ciaddr(slicer.parse_ciaddr()),
209 yiaddr: Self::decode_yiaddr(slicer.parse_yiaddr()),
210 siaddr: Self::decode_siaddr(slicer.parse_siaddr()),
211 giaddr: Self::decode_giaddr(slicer.parse_giaddr()),
212 chaddr: Self::decode_chaddr(slicer.parse_chaddr()),
213 sname: Self::decode_sname(slicer.parse_sname()),
214 file: Self::decode_file(slicer.parse_file()),
215 magic: Self::decode_magic(slicer.parse_magic()),
216 options: Self::decode_options(slicer.parse_options()),
217 })
218 }
219}
220
221impl EncodeMessage for Message {
222 #[inline]
223 fn encode_op(&self) -> u8 {
224 (&self.op).into()
225 }
226
227 #[inline]
228 fn encode_htype(&self) -> u8 {
229 (&self.htype).into()
230 }
231
232 #[inline]
233 fn encode_hlen(&self) -> u8 {
234 self.hlen
235 }
236
237 #[inline]
238 fn encode_hops(&self) -> u8 {
239 self.hops
240 }
241
242 #[inline]
243 fn encode_xid(&self) -> [u8; 4] {
244 self.xid.to_be_bytes()
245 }
246
247 #[inline]
248 fn encode_secs(&self) -> [u8; 2] {
249 self.secs.to_be_bytes()
250 }
251
252 #[inline]
253 fn encode_flags(&self) -> [u8; 2] {
254 (&self.flags).temporary_to_bytes()
255 }
256
257 #[inline]
258 fn encode_ciaddr(&self) -> [u8; 4] {
259 self.ciaddr.octets()
260 }
261
262 #[inline]
263 fn encode_yiaddr(&self) -> [u8; 4] {
264 self.yiaddr.octets()
265 }
266
267 #[inline]
268 fn encode_siaddr(&self) -> [u8; 4] {
269 self.siaddr.octets()
270 }
271
272 #[inline]
273 fn encode_giaddr(&self) -> [u8; 4] {
274 self.giaddr.octets()
275 }
276
277 #[inline]
278 fn encode_chaddr(&self) -> [u8; 16] {
279 self.chaddr
280 }
281
282 #[inline]
283 fn encode_sname(&self) -> [u8; 64] {
284 (&self.sname).into()
285 }
286
287 #[inline]
288 fn encode_file(&self) -> [u8; 128] {
289 (&self.file).into()
290 }
291
292 #[inline]
293 fn encode_options(&self) -> Vec<u8> {
294 let mut encoded = Vec::with_capacity(self.options.len() * 2);
295
296 self.options
297 .iter()
298 .for_each(|option| option.extend_into(&mut encoded));
299
300 encoded
301 }
302}