1use super::MAGIC;
2use crate::v4::{MAX_MESSAGE_SIZE, MagicBuffer};
3use std::fmt::Debug;
4use tracing::trace;
5
6pub trait Encodable: EncodeMessage + Debug {}
9
10pub trait EncodeMessage {
21 fn encode_op(&self) -> u8;
23 fn encode_htype(&self) -> u8;
25 fn encode_hlen(&self) -> u8;
27 fn encode_hops(&self) -> u8;
29 fn encode_xid(&self) -> [u8; 4];
31 fn encode_secs(&self) -> [u8; 2];
33 fn encode_flags(&self) -> [u8; 2];
35 fn encode_ciaddr(&self) -> [u8; 4];
37 fn encode_yiaddr(&self) -> [u8; 4];
39 fn encode_siaddr(&self) -> [u8; 4];
41 fn encode_giaddr(&self) -> [u8; 4];
43 fn encode_chaddr(&self) -> [u8; 16];
45 fn encode_sname(&self) -> [u8; 64];
47 fn encode_file(&self) -> [u8; 128];
49 fn encode_options(&self) -> Vec<u8>;
51
52 fn encode_magic(&self) -> MagicBuffer {
54 MAGIC
55 }
56
57 fn to_bytes(&self) -> Vec<u8> {
61 trace!("to_bytes");
62
63 let mut encoder = Encoder {
64 output: Vec::with_capacity(MAX_MESSAGE_SIZE),
65 };
66
67 trace!("encode op");
68 encoder.encode_byte(self.encode_op());
69 trace!("encode htype");
70 encoder.encode_byte(self.encode_htype());
71 trace!("encode hlen");
72 encoder.encode_byte(self.encode_hlen());
73 trace!("encode hops");
74 encoder.encode_byte(self.encode_hops());
75 trace!("encode xid");
76 encoder.encode_bytes(&self.encode_xid());
77 trace!("encode secs");
78 encoder.encode_bytes(&self.encode_secs());
79 trace!("encode flags");
80 encoder.encode_bytes(&self.encode_flags());
81 trace!("encode ciaddr");
82 encoder.encode_bytes(&self.encode_ciaddr());
83 trace!("encode yiaddr");
84 encoder.encode_bytes(&self.encode_yiaddr());
85 trace!("encode siaddr");
86 encoder.encode_bytes(&self.encode_siaddr());
87 trace!("encode giaddr");
88 encoder.encode_bytes(&self.encode_giaddr());
89 trace!("encode chaddr");
90 encoder.encode_bytes(&self.encode_chaddr());
91 trace!("encode sname");
92 encoder.encode_bytes(&self.encode_sname());
93 trace!("encode file");
94 encoder.encode_bytes(&self.encode_file());
95 trace!("encode magic");
96 encoder.encode_bytes(&self.encode_magic());
97 trace!("encode options");
98 encoder.encode_bytes(self.encode_options().as_slice());
99
100 encoder.encode_byte(255);
102
103 encoder.output
104 }
105}
106
107#[derive(Debug)]
109pub struct Encoder {
110 output: Vec<u8>,
112}
113
114impl Encoder {
116 #[inline]
117 fn encode_bytes(&mut self, v: &[u8]) {
118 trace!("encode_bytes");
119 self.output.extend_from_slice(v);
120 }
121
122 #[inline]
123 fn encode_byte(&mut self, v: u8) {
124 trace!("encode_byte");
125 self.output.push(v);
126 }
127}
128
129#[cfg(test)]
132mod tests {
133 use std::net::Ipv4Addr;
134
135 use super::*;
136 use crate::v4::*;
137
138 #[test]
139 fn test_to_bytes() {
140 init_logger(true);
141
142 let message = Message {
143 op: Ops::Request,
144 htype: HTypes::Ethernet,
145 hlen: 6,
146 hops: 1,
147 xid: 4,
148 secs: 2,
149 flags: Flags { broadcast: true },
150 ciaddr: Ipv4Addr::new(1, 1, 1, 1),
151 yiaddr: Ipv4Addr::new(1, 1, 1, 1),
152 siaddr: Ipv4Addr::new(1, 1, 1, 1),
153 giaddr: Ipv4Addr::new(1, 1, 1, 1),
154 chaddr: [3; 16],
155 sname: SName::new(c"000000000000000000000000000000000000000000000000000000000000000").unwrap(),
156 file: File::new(c"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@").unwrap(),
157 magic: [99, 130, 83, 99],
158 options: vec![
159 MessageOptions::MessageType(MessageTypes::Discover),
160 ].into(),
161 };
162
163 let expected = vec![
164 1, 1, 6, 1, 0, 0, 0, 4, 0, 2, 128, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
165 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
166 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
167 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
168 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
169 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
170 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
171 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
172 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
173 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
174 64, 64, 64, 64, 64, 0, 99, 130, 83, 99, 53, 1, 1, 255,
175 ];
176
177 assert_eq!(message.to_bytes(), expected);
178 }
179}