toe_beans/v4/message/
mod.rs1mod decode;
2mod encode;
3mod file;
4mod flags;
5mod helpers;
6mod htype;
7mod op;
8mod options;
9mod slicer;
10mod sname;
11mod socket;
12mod undecoded;
13
14pub use self::decode::*;
15pub use self::encode::*;
16pub use self::file::*;
17pub use self::flags::*;
18pub use self::helpers::*;
19pub use self::htype::*;
20pub use self::op::*;
21pub use self::options::*;
22pub use self::slicer::*;
23pub use self::sname::*;
24pub use self::socket::*;
25pub use self::undecoded::*;
26
27use mac_address::MacAddress;
28use std::net::Ipv4Addr;
29
30pub const MESSAGE_FIXED_FIELDS_SIZE: usize = 236;
32
33pub const MAX_MESSAGE_SIZE: usize = MESSAGE_FIXED_FIELDS_SIZE + MIN_OPTIONS_SIZE;
38
39#[derive(Debug, PartialEq)]
71pub struct Message {
72 pub op: Ops,
74 pub htype: HTypes,
76 pub hlen: u8,
78 pub hops: u8,
80 pub xid: u32,
82 pub secs: u16,
84 pub flags: Flags,
86 pub ciaddr: Ipv4Addr,
88 pub yiaddr: Ipv4Addr,
90 pub siaddr: Ipv4Addr,
92 pub giaddr: Ipv4Addr,
94 pub chaddr: [u8; 16],
98 pub sname: SName,
100 pub file: File,
102 pub magic: MagicBuffer,
104 pub options: MessageOptionsList,
108}
109
110impl Encodable for Message {}
111impl Decodable for Message {}
112
113impl MessageHelpers for Message {
114 fn find_option(&self, tag: u8) -> Option<&MessageOptions> {
116 self.options.find_option(tag)
117 }
118
119 fn add_option(&mut self, option: MessageOptions) {
120 self.options.add_option(option);
121 }
122
123 fn get_mac_address(&self) -> MacAddress {
124 MacAddress::new([
125 self.chaddr[0],
126 self.chaddr[1],
127 self.chaddr[2],
128 self.chaddr[3],
129 self.chaddr[4],
130 self.chaddr[5],
131 ])
132 }
133}
134
135impl DecodeMessage for Message {
136 type Op = Ops;
137 type Htype = HTypes;
138 type Hlen = u8;
139 type Hops = u8;
140 type Xid = u32;
141 type Secs = u16;
142 type Flags = Flags;
143 type Ciaddr = Ipv4Addr;
144 type Yiaddr = Ipv4Addr;
145 type Siaddr = Ipv4Addr;
146 type Giaddr = Ipv4Addr;
147 type Chaddr = [u8; 16];
148 type Sname = SName;
149 type File = File;
150 type Magic = MagicBuffer;
151 type Options = MessageOptionsList;
152
153 type Output = Self;
154
155 fn decode_op(undecoded: &UndecodedMessage) -> Self::Op {
156 Self::Op::from(undecoded.slice_op())
157 }
158
159 fn decode_htype(undecoded: &UndecodedMessage) -> Self::Htype {
160 Self::Htype::from(undecoded.slice_htype())
161 }
162
163 fn decode_hlen(undecoded: &UndecodedMessage) -> Self::Hlen {
164 undecoded.slice_hlen()
165 }
166
167 fn decode_hops(undecoded: &UndecodedMessage) -> Self::Hops {
168 undecoded.slice_hops()
169 }
170
171 fn decode_xid(undecoded: &UndecodedMessage) -> Self::Xid {
172 let bytes = undecoded.slice_xid();
173 u32::from_be_bytes(bytes)
174 }
175
176 fn decode_secs(undecoded: &UndecodedMessage) -> Self::Secs {
177 let bytes = undecoded.slice_secs();
178 u16::from_be_bytes(bytes)
179 }
180
181 fn decode_flags(undecoded: &UndecodedMessage) -> Self::Flags {
182 Self::Flags::from(undecoded.slice_flags_temporary())
183 }
184
185 fn decode_ciaddr(undecoded: &UndecodedMessage) -> Self::Ciaddr {
186 let bytes = undecoded.slice_ciaddr();
187 Ipv4Addr::from(bytes)
188 }
189
190 fn decode_yiaddr(undecoded: &UndecodedMessage) -> Self::Yiaddr {
191 let bytes = undecoded.slice_yiaddr();
192 Ipv4Addr::from(bytes)
193 }
194
195 fn decode_siaddr(undecoded: &UndecodedMessage) -> Self::Siaddr {
196 let bytes = undecoded.slice_siaddr();
197 Ipv4Addr::from(bytes)
198 }
199
200 fn decode_giaddr(undecoded: &UndecodedMessage) -> Self::Giaddr {
201 let bytes = undecoded.slice_giaddr();
202 Ipv4Addr::from(bytes)
203 }
204
205 fn decode_chaddr(undecoded: &UndecodedMessage) -> Self::Chaddr {
206 undecoded.slice_chaddr()
207 }
208
209 fn decode_sname(undecoded: &UndecodedMessage) -> Self::Sname {
210 SName::from_array(undecoded.slice_sname())
211 }
212
213 fn decode_file(undecoded: &UndecodedMessage) -> Self::File {
214 File::from_array(undecoded.slice_file())
215 }
216
217 fn decode_magic(_magic: &UndecodedMessage) -> Self::Magic {
218 MAGIC
219 }
220
221 fn decode_options(undecoded: &UndecodedMessage) -> Self::Options {
222 MessageOptionsList::from_bytes(&undecoded.slice_options())
223 }
224
225 fn from_bytes(undecoded: &UndecodedMessage) -> Self::Output {
226 Message {
227 op: Self::decode_op(undecoded),
228 htype: Self::decode_htype(undecoded),
229 hlen: Self::decode_hlen(undecoded),
230 hops: Self::decode_hops(undecoded),
231 xid: Self::decode_xid(undecoded),
232 secs: Self::decode_secs(undecoded),
233 flags: Self::decode_flags(undecoded),
234 ciaddr: Self::decode_ciaddr(undecoded),
235 yiaddr: Self::decode_yiaddr(undecoded),
236 siaddr: Self::decode_siaddr(undecoded),
237 giaddr: Self::decode_giaddr(undecoded),
238 chaddr: Self::decode_chaddr(undecoded),
239 sname: Self::decode_sname(undecoded),
240 file: Self::decode_file(undecoded),
241 magic: Self::decode_magic(undecoded),
242 options: Self::decode_options(undecoded),
243 }
244 }
245}
246
247impl EncodeMessage for Message {
248 #[inline]
249 fn encode_op(&self) -> u8 {
250 (&self.op).into()
251 }
252
253 #[inline]
254 fn encode_htype(&self) -> u8 {
255 (&self.htype).into()
256 }
257
258 #[inline]
259 fn encode_hlen(&self) -> u8 {
260 self.hlen
261 }
262
263 #[inline]
264 fn encode_hops(&self) -> u8 {
265 self.hops
266 }
267
268 #[inline]
269 fn encode_xid(&self) -> [u8; 4] {
270 self.xid.to_be_bytes()
271 }
272
273 #[inline]
274 fn encode_secs(&self) -> [u8; 2] {
275 self.secs.to_be_bytes()
276 }
277
278 #[inline]
279 fn encode_flags(&self) -> [u8; 2] {
280 self.flags.temporary_to_bytes()
281 }
282
283 #[inline]
284 fn encode_ciaddr(&self) -> [u8; 4] {
285 self.ciaddr.octets()
286 }
287
288 #[inline]
289 fn encode_yiaddr(&self) -> [u8; 4] {
290 self.yiaddr.octets()
291 }
292
293 #[inline]
294 fn encode_siaddr(&self) -> [u8; 4] {
295 self.siaddr.octets()
296 }
297
298 #[inline]
299 fn encode_giaddr(&self) -> [u8; 4] {
300 self.giaddr.octets()
301 }
302
303 #[inline]
304 fn encode_chaddr(&self) -> [u8; 16] {
305 self.chaddr
306 }
307
308 #[inline]
309 fn encode_sname(&self) -> [u8; 64] {
310 (&self.sname).into()
311 }
312
313 #[inline]
314 fn encode_file(&self) -> [u8; 128] {
315 (&self.file).into()
316 }
317
318 #[inline]
319 fn encode_options(&self) -> Vec<u8> {
320 (&self.options).into()
321 }
322}
323
324#[cfg(test)]
327mod tests {
328 use super::*;
329
330 #[test]
331 fn test_max_message_size_is_large_enough() {
332 assert!(MAX_MESSAGE_SIZE >= 548);
335 }
336}