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 log::{trace, warn};
7use serde::{Deserialize, Serialize};
8
9#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
14pub enum MessageOptions {
15 Pad,
17 Netmask(AddressOption),
19 TimeOffset(TimeOffset),
21 Router(AddressListOption),
23 DnsServer(AddressListOption),
25 HostName(StringOption),
28 DomainName(StringOption),
30 Broadcast(AddressOption),
32 RequestedIp(AddressOption),
36 LeaseTime(TimeOption),
42 Overload(OverloadOptions),
44 MessageType(MessageTypes),
46 ServerIdentifier(AddressOption),
48 RequestedOptions(Vec<u8>),
50 Message(StringOption),
52 MaxMessage(MaxMessage),
54 T1(TimeOption),
56 T2(TimeOption),
58 VendorId(OpaqueOption),
60 ClientId(OpaqueOption),
62 SName(SNameOption),
64 FileName(FileOption),
66 RapidCommit,
79 SubnetSelect(AddressOption),
81 End,
83 Other(u8, u8, Vec<u8>),
85}
86
87impl MessageOptions {
88 pub fn to_tag(&self) -> u8 {
91 match self {
92 Self::Pad => 0,
93 Self::Netmask(_) => 1,
94 Self::TimeOffset(_) => 2,
95 Self::Router(_) => 3,
96 Self::DnsServer(_) => 6,
97 Self::HostName(_) => 12,
98 Self::DomainName(_) => 15,
99 Self::Broadcast(_) => 28,
100 Self::RequestedIp(_) => 50,
101 Self::LeaseTime(_) => 51,
102 Self::Overload(_) => 52,
103 Self::MessageType(_) => 53,
104 Self::ServerIdentifier(_) => 54,
105 Self::RequestedOptions(_) => 55,
106 Self::Message(_) => 56,
107 Self::MaxMessage(_) => 57,
108 Self::T1(_) => 58,
109 Self::T2(_) => 59,
110 Self::VendorId(_) => 60,
111 Self::ClientId(_) => 61,
112 Self::SName(_) => 66,
113 Self::FileName(_) => 67,
114 Self::RapidCommit => 80,
115 Self::SubnetSelect(_) => 118,
116 Self::End => 255,
117 Self::Other(x, _, _) => *x,
118 }
119 }
120
121 fn from_tag_value(tag: u8, value: &[u8]) -> Self {
124 match tag {
125 1 => Self::Netmask(value.into()),
126 2 => Self::TimeOffset(value.into()),
127 3 => Self::Router(value.into()),
128 6 => Self::DnsServer(value.into()),
129 12 => Self::HostName(value.into()),
130 15 => Self::DomainName(value.into()),
131 28 => Self::Broadcast(value.into()),
132 50 => Self::RequestedIp(value.into()),
133 51 => Self::LeaseTime(value.into()),
134 52 => Self::Overload(value.into()),
135 53 => Self::MessageType(MessageTypes::from(value)),
136 54 => Self::ServerIdentifier(value.into()),
137 55 => Self::RequestedOptions(value.into()),
138 56 => Self::Message(value.into()),
139 57 => Self::MaxMessage(value.into()),
140 58 => Self::T1(value.into()),
141 59 => Self::T2(value.into()),
142 60 => Self::VendorId(value.into()),
143 61 => Self::ClientId(value.into()),
144 66 => Self::SName(value.into()),
145 67 => Self::FileName(value.into()),
146 118 => Self::SubnetSelect(value.into()),
147 _ => Self::Other(tag, value.len() as u8, value.into()),
148 }
149 }
150
151 #[inline]
153 pub fn extend_into(&self, bytes: &mut Vec<u8>) {
154 match self {
155 Self::Pad => bytes.push(0),
156 Self::End => {
157 warn!("The End option is automatically handled during encode/decode. Don't use it.")
158 }
159 Self::RapidCommit => bytes.push(80),
160 Self::LeaseTime(x) => x.extend_into(bytes, 51),
161 Self::T1(x) => x.extend_into(bytes, 58),
162 Self::T2(x) => x.extend_into(bytes, 59),
163 Self::RequestedIp(x) => x.extend_into(bytes, 50),
164 Self::ServerIdentifier(x) => x.extend_into(bytes, 54),
165 Self::MessageType(x) => x.extend_into(bytes, 53),
166 Self::Netmask(x) => x.extend_into(bytes, 1),
167 Self::Broadcast(x) => x.extend_into(bytes, 28),
168 Self::Overload(x) => x.extend_into(bytes, 52),
169 Self::SName(x) => x.extend_into(bytes, 66),
170 Self::FileName(x) => x.extend_into(bytes, 67),
171 Self::Router(x) => x.extend_into(bytes, 3),
172 Self::DnsServer(x) => x.extend_into(bytes, 6),
173 Self::MaxMessage(x) => x.extend_into(bytes, 57),
174 Self::HostName(x) => x.extend_into(bytes, 12),
175 Self::DomainName(x) => x.extend_into(bytes, 15),
176 Self::Message(x) => x.extend_into(bytes, 56),
177 Self::SubnetSelect(x) => x.extend_into(bytes, 118),
178 Self::VendorId(x) => x.extend_into(bytes, 60),
179 Self::ClientId(x) => x.extend_into(bytes, 61),
180 Self::TimeOffset(x) => x.extend_into(bytes, 2),
181
182 Self::RequestedOptions(v) => {
183 bytes.push(55);
184 bytes.push(v.len() as u8);
185 bytes.extend(v.iter());
186 }
187
188 Self::Other(t, l, v) => {
189 bytes.push(*t);
190 bytes.push(*l);
191 bytes.extend(v);
192 }
193 };
194 }
195
196 pub fn from_bytes(bytes: &[u8]) -> Vec<Self> {
198 let mut slicer = Slicer::new(bytes);
199 let mut options: Vec<MessageOptions> = Vec::with_capacity(308);
200
201 while let Some(tag) = slicer.slice(1) {
203 trace!("parsing option {:?}", tag);
204 match tag[0] {
205 0 => {} 80 => {
207 options.push(Self::RapidCommit);
208 }
209 255 => {
210 break; }
213 tag_with_length => {
214 match slicer.slice(1) {
216 Some(length) => match slicer.slice(length[0] as usize) {
217 Some(value) => {
218 options.push(MessageOptions::from_tag_value(tag_with_length, value))
219 }
220 None => break, },
222 None => break, }
224 }
225 }
226 }
227
228 options
229 }
230}