toe_beans/v4/message/options/
options.rs1use super::super::Slicer;
2use super::{
3 AddressListOption, AddressOption, FileOption, MaxMessage, MessageTypes, OpaqueOption,
4 OverloadOptions, SNameOption, StringOption, TimeOffset, TimeOption,
5};
6use crate::v4::{MIN_OPTIONS_SIZE, NON_MAGIC_SIZE};
7use log::{trace, warn};
8use serde::{Deserialize, Serialize};
9
10#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
15pub enum MessageOptions {
16 Pad,
18 Netmask(AddressOption),
20 TimeOffset(TimeOffset),
22 Router(AddressListOption),
24 DnsServer(AddressListOption),
26 HostName(StringOption),
29 DomainName(StringOption),
31 Broadcast(AddressOption),
33 RequestedIp(AddressOption),
37 LeaseTime(TimeOption),
43 Overload(OverloadOptions),
45 MessageType(MessageTypes),
47 ServerIdentifier(AddressOption),
49 RequestedOptions(Vec<u8>),
51 Message(StringOption),
53 MaxMessage(MaxMessage),
55 T1(TimeOption),
57 T2(TimeOption),
59 VendorId(OpaqueOption),
61 ClientId(OpaqueOption),
63 SName(SNameOption),
65 FileName(FileOption),
67 RapidCommit,
80 SubnetSelect(AddressOption),
82 End,
84 Other(u8, u8, Vec<u8>),
86}
87
88impl MessageOptions {
89 pub fn to_tag(&self) -> u8 {
92 match self {
93 Self::Pad => 0,
94 Self::Netmask(_) => 1,
95 Self::TimeOffset(_) => 2,
96 Self::Router(_) => 3,
97 Self::DnsServer(_) => 6,
98 Self::HostName(_) => 12,
99 Self::DomainName(_) => 15,
100 Self::Broadcast(_) => 28,
101 Self::RequestedIp(_) => 50,
102 Self::LeaseTime(_) => 51,
103 Self::Overload(_) => 52,
104 Self::MessageType(_) => 53,
105 Self::ServerIdentifier(_) => 54,
106 Self::RequestedOptions(_) => 55,
107 Self::Message(_) => 56,
108 Self::MaxMessage(_) => 57,
109 Self::T1(_) => 58,
110 Self::T2(_) => 59,
111 Self::VendorId(_) => 60,
112 Self::ClientId(_) => 61,
113 Self::SName(_) => 66,
114 Self::FileName(_) => 67,
115 Self::RapidCommit => 80,
116 Self::SubnetSelect(_) => 118,
117 Self::End => 255,
118 Self::Other(x, _, _) => *x,
119 }
120 }
121
122 fn from_tag_value(tag: u8, value: &[u8]) -> Self {
125 match tag {
126 1 => Self::Netmask(value.into()),
127 2 => Self::TimeOffset(value.into()),
128 3 => Self::Router(value.into()),
129 6 => Self::DnsServer(value.into()),
130 12 => Self::HostName(value.into()),
131 15 => Self::DomainName(value.into()),
132 28 => Self::Broadcast(value.into()),
133 50 => Self::RequestedIp(value.into()),
134 51 => Self::LeaseTime(value.into()),
135 52 => Self::Overload(value.into()),
136 53 => Self::MessageType(MessageTypes::from(value)),
137 54 => Self::ServerIdentifier(value.into()),
138 55 => Self::RequestedOptions(value.into()),
139 56 => Self::Message(value.into()),
140 57 => Self::MaxMessage(value.into()),
141 58 => Self::T1(value.into()),
142 59 => Self::T2(value.into()),
143 60 => Self::VendorId(value.into()),
144 61 => Self::ClientId(value.into()),
145 66 => Self::SName(value.into()),
146 67 => Self::FileName(value.into()),
147 118 => Self::SubnetSelect(value.into()),
148 _ => Self::Other(tag, value.len() as u8, value.into()),
149 }
150 }
151
152 #[inline]
154 pub fn extend_into(&self, bytes: &mut Vec<u8>) {
155 match self {
156 Self::Pad => bytes.push(0),
157 Self::End => {
158 warn!("The End option is automatically handled during encode/decode. Don't use it.")
159 }
160 Self::RapidCommit => bytes.push(80),
161 Self::LeaseTime(x) => x.extend_into(bytes, 51),
162 Self::T1(x) => x.extend_into(bytes, 58),
163 Self::T2(x) => x.extend_into(bytes, 59),
164 Self::RequestedIp(x) => x.extend_into(bytes, 50),
165 Self::ServerIdentifier(x) => x.extend_into(bytes, 54),
166 Self::MessageType(x) => x.extend_into(bytes, 53),
167 Self::Netmask(x) => x.extend_into(bytes, 1),
168 Self::Broadcast(x) => x.extend_into(bytes, 28),
169 Self::Overload(x) => x.extend_into(bytes, 52),
170 Self::SName(x) => x.extend_into(bytes, 66),
171 Self::FileName(x) => x.extend_into(bytes, 67),
172 Self::Router(x) => x.extend_into(bytes, 3),
173 Self::DnsServer(x) => x.extend_into(bytes, 6),
174 Self::MaxMessage(x) => x.extend_into(bytes, 57),
175 Self::HostName(x) => x.extend_into(bytes, 12),
176 Self::DomainName(x) => x.extend_into(bytes, 15),
177 Self::Message(x) => x.extend_into(bytes, 56),
178 Self::SubnetSelect(x) => x.extend_into(bytes, 118),
179 Self::VendorId(x) => x.extend_into(bytes, 60),
180 Self::ClientId(x) => x.extend_into(bytes, 61),
181 Self::TimeOffset(x) => x.extend_into(bytes, 2),
182
183 Self::RequestedOptions(v) => {
184 bytes.push(55);
185 bytes.push(v.len() as u8);
186 bytes.extend(v.iter());
187 }
188
189 Self::Other(t, l, v) => {
190 bytes.push(*t);
191 bytes.push(*l);
192 bytes.extend(v);
193 }
194 };
195 }
196}
197
198#[derive(Debug, PartialEq)]
200pub struct MessageOptionsList(Vec<MessageOptions>);
201
202impl MessageOptionsList {
203 #[inline]
205 pub fn find_option(&self, tag: u8) -> Option<&MessageOptions> {
206 self.0.iter().find(|&option| option.to_tag() == tag)
207 }
208
209 #[inline]
211 pub fn add_option(&mut self, option: MessageOptions) {
212 self.0.push(option);
213 }
214
215 #[deprecated]
218 pub fn get(&self, index: usize) -> Option<&MessageOptions> {
219 self.0.get(index)
220 }
221
222 #[deprecated]
225 pub fn set(&mut self, index: usize, option: MessageOptions) {
226 self.0[index] = option;
227 }
228
229 #[inline]
231 pub fn from_bytes(bytes: &[u8]) -> Self {
232 let mut slicer = Slicer::new(bytes);
233 let mut options: Vec<MessageOptions> = Vec::with_capacity(NON_MAGIC_SIZE);
234
235 while let Some(tag) = slicer.slice(1) {
237 trace!("parsing option {:?}", tag);
238 match tag[0] {
239 0 => {} 80 => {
241 options.push(MessageOptions::RapidCommit);
242 }
243 255 => {
244 break; }
247 tag_with_length => {
248 match slicer.slice(1) {
250 Some(length) => match slicer.slice(length[0] as usize) {
251 Some(value) => {
252 options.push(MessageOptions::from_tag_value(tag_with_length, value))
253 }
254 None => break, },
256 None => break, }
258 }
259 }
260 }
261
262 Self(options)
263 }
264}
265
266impl From<Vec<MessageOptions>> for MessageOptionsList {
267 fn from(options: Vec<MessageOptions>) -> Self {
268 Self(options)
269 }
270}
271
272impl From<&MessageOptionsList> for Vec<u8> {
273 #[inline]
274 fn from(list: &MessageOptionsList) -> Self {
275 let mut encoded = Vec::with_capacity(MIN_OPTIONS_SIZE);
276
277 list.0
278 .iter()
279 .for_each(|option| option.extend_into(&mut encoded));
280
281 encoded
282 }
283}