1use core::fmt;
19
20use crate::error::*;
21use crate::utils::storage::{ParseBuf, WriteBuf};
22
23bitflags::bitflags! {
24 #[repr(transparent)]
25 #[derive(Default, Debug, Copy, Clone, Eq, PartialEq, Hash)]
26 pub struct MsgFlags: u8 {
27 const DSIZ_UNICAST_NODEID = 0x01;
28 const DSIZ_GROUPCAST_NODEID = 0x02;
29 const SRC_ADDR_PRESENT = 0x04;
30 }
31
32 #[repr(transparent)]
33 #[derive(Default, Debug, Copy, Clone, Eq, PartialEq, Hash)]
34 pub struct SecFlags: u8 {
35 const GROUP_SESSION = 0x01;
37 const MSG_EXT = 0x20;
39 const CONTROL_MSG = 0x40;
42 const PRIVACY = 0x80;
47 }
48}
49
50const DSIZ_MASK: MsgFlags = MsgFlags::DSIZ_UNICAST_NODEID.union(MsgFlags::DSIZ_GROUPCAST_NODEID);
51
52impl fmt::Display for MsgFlags {
53 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
54 let mut sep = false;
55 for flag in [
56 Self::SRC_ADDR_PRESENT,
57 Self::DSIZ_UNICAST_NODEID,
58 Self::DSIZ_GROUPCAST_NODEID,
59 ] {
60 if self.contains(flag) {
61 if sep {
62 write!(f, "|")?;
63 }
64
65 let str = match flag {
66 Self::DSIZ_UNICAST_NODEID => "U",
67 Self::DSIZ_GROUPCAST_NODEID => "G",
68 Self::SRC_ADDR_PRESENT => "S",
69 _ => "?",
70 };
71
72 write!(f, "{}", str)?;
73 sep = true;
74 }
75 }
76
77 Ok(())
78 }
79}
80
81#[cfg(feature = "defmt")]
82impl defmt::Format for MsgFlags {
83 fn format(&self, f: defmt::Formatter<'_>) {
84 let mut sep = false;
85 for flag in [
86 Self::SRC_ADDR_PRESENT,
87 Self::DSIZ_UNICAST_NODEID,
88 Self::DSIZ_GROUPCAST_NODEID,
89 ] {
90 if self.contains(flag) {
91 if sep {
92 defmt::write!(f, "|");
93 }
94
95 let str = match flag {
96 Self::DSIZ_UNICAST_NODEID => "U",
97 Self::DSIZ_GROUPCAST_NODEID => "G",
98 Self::SRC_ADDR_PRESENT => "S",
99 _ => "?",
100 };
101
102 defmt::write!(f, "{}", str);
103 sep = true;
104 }
105 }
106 }
107}
108
109#[derive(Debug, Default, Clone)]
111pub struct PlainHdr {
112 flags: MsgFlags,
113 pub sess_id: u16,
114 pub(crate) sec_flags: SecFlags,
115 pub ctr: u32,
116 src_nodeid: u64,
117 dst_nodeid: u64,
118}
119
120impl PlainHdr {
121 pub const MAX_LEN: usize =
122 2
124 + 1
126 + 1
128 + 2
130 + 4
132 + 8
134 + 8;
136
137 #[inline(always)]
138 pub const fn new() -> Self {
139 Self {
140 flags: MsgFlags::empty(),
141 sess_id: 0,
142 sec_flags: SecFlags::empty(),
143 ctr: 0,
144 src_nodeid: 0,
145 dst_nodeid: 0,
146 }
147 }
148
149 pub fn get_src_nodeid(&self) -> Option<u64> {
150 if self.flags.contains(MsgFlags::SRC_ADDR_PRESENT) {
151 Some(self.src_nodeid)
152 } else {
153 None
154 }
155 }
156
157 pub fn set_src_nodeid(&mut self, id: Option<u64>) {
158 if let Some(id) = id {
159 self.flags |= MsgFlags::SRC_ADDR_PRESENT;
160 self.src_nodeid = id;
161 } else {
162 self.flags.remove(MsgFlags::SRC_ADDR_PRESENT);
163 self.src_nodeid = 0;
164 }
165 }
166
167 pub fn get_dst_unicast_nodeid(&self) -> Option<u64> {
168 if self.flags.intersection(DSIZ_MASK) == MsgFlags::DSIZ_UNICAST_NODEID {
169 Some(self.dst_nodeid)
170 } else {
171 None
172 }
173 }
174
175 pub fn set_dst_unicast_nodeid(&mut self, id: Option<u64>) {
176 if let Some(id) = id {
177 self.flags |= MsgFlags::DSIZ_UNICAST_NODEID;
178 self.flags.remove(MsgFlags::DSIZ_GROUPCAST_NODEID);
179 self.dst_nodeid = id;
180 } else {
181 self.flags.remove(DSIZ_MASK);
182 self.dst_nodeid = 0;
183 }
184 }
185
186 pub fn get_dst_groupcast_nodeid(&self) -> Option<u16> {
187 if self.flags.intersection(DSIZ_MASK) == MsgFlags::DSIZ_GROUPCAST_NODEID {
188 Some(self.dst_nodeid as u16)
189 } else {
190 None
191 }
192 }
193
194 pub fn set_dst_groupcast_nodeid(&mut self, id: Option<u16>) {
195 if let Some(id) = id {
196 self.flags |= MsgFlags::DSIZ_GROUPCAST_NODEID;
197 self.flags.remove(MsgFlags::DSIZ_UNICAST_NODEID);
198 self.dst_nodeid = id as u64;
199 } else {
200 self.flags.remove(DSIZ_MASK);
201 self.dst_nodeid = 0;
202 }
203 }
204
205 pub fn decode(&mut self, msg: &mut ParseBuf) -> Result<(), Error> {
207 self.flags = MsgFlags::from_bits(msg.le_u8()?).ok_or(ErrorCode::Invalid)?;
208 self.sess_id = msg.le_u16()?;
209 self.sec_flags = SecFlags::from_bits(msg.le_u8()?).ok_or(ErrorCode::Invalid)?;
210 self.ctr = msg.le_u32()?;
211
212 if self.flags.contains(MsgFlags::SRC_ADDR_PRESENT) {
213 self.src_nodeid = msg.le_u64()?;
214 }
215
216 if !self.flags.contains(DSIZ_MASK) {
217 if self.flags.contains(MsgFlags::DSIZ_UNICAST_NODEID) {
218 self.dst_nodeid = msg.le_u64()?;
219 } else if self.flags.contains(MsgFlags::DSIZ_GROUPCAST_NODEID) {
220 self.dst_nodeid = msg.le_u16()? as u64;
221 }
222 }
223
224 trace!("[decode] {}", self);
225 Ok(())
226 }
227
228 pub fn encode(&self, resp_buf: &mut WriteBuf) -> Result<(), Error> {
229 trace!("[encode] {}", self);
230 resp_buf.le_u8(self.flags.bits())?;
231 resp_buf.le_u16(self.sess_id)?;
232 resp_buf.le_u8(self.sec_flags.bits())?;
233 resp_buf.le_u32(self.ctr)?;
234
235 if self.flags.contains(MsgFlags::SRC_ADDR_PRESENT) {
236 resp_buf.le_u64(self.src_nodeid)?;
237 }
238
239 if !self.flags.contains(DSIZ_MASK) {
240 if self.flags.contains(MsgFlags::DSIZ_UNICAST_NODEID) {
241 resp_buf.le_u64(self.dst_nodeid)?;
242 } else if self.flags.contains(MsgFlags::DSIZ_GROUPCAST_NODEID) {
243 resp_buf.le_u16(self.dst_nodeid as u16)?;
244 }
245 }
246
247 Ok(())
248 }
249
250 pub fn is_group_session(&self) -> bool {
251 self.sec_flags.contains(SecFlags::GROUP_SESSION)
252 }
253
254 pub fn set_group_session(&mut self, group: bool) {
256 if group {
257 self.sec_flags |= SecFlags::GROUP_SESSION;
258 } else {
259 self.sec_flags.remove(SecFlags::GROUP_SESSION);
260 }
261 }
262
263 pub fn is_control_msg(&self) -> bool {
265 self.sec_flags.contains(SecFlags::CONTROL_MSG)
266 }
267
268 pub fn set_control_msg(&mut self, control: bool) {
270 if control {
271 self.sec_flags |= SecFlags::CONTROL_MSG;
272 } else {
273 self.sec_flags.remove(SecFlags::CONTROL_MSG);
274 }
275 }
276
277 pub fn is_privacy(&self) -> bool {
281 self.sec_flags.contains(SecFlags::PRIVACY)
282 }
283
284 pub fn is_encrypted(&self) -> bool {
285 self.sess_id != 0 || self.is_group_session()
286 }
287}
288
289impl fmt::Display for PlainHdr {
290 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
291 if !self.flags.is_empty() {
292 write!(f, "{},", self.flags)?;
293 }
294
295 write!(f, "SID:{:x},CTR:{:x}", self.sess_id, self.ctr)?;
296
297 if self.is_control_msg() {
298 write!(f, ",C")?;
299 }
300 if self.is_privacy() {
301 write!(f, ",P")?;
302 }
303
304 if let Some(src_nodeid) = self.get_src_nodeid() {
305 write!(f, ",SRC:{:x}", src_nodeid)?;
306 }
307
308 if let Some(dst_nodeid) = self.get_dst_unicast_nodeid() {
309 write!(f, ",DST:{:x}", dst_nodeid)?;
310 }
311
312 if let Some(dst_group_nodeid) = self.get_dst_groupcast_nodeid() {
313 write!(f, ",GRP:{:x}", dst_group_nodeid)?;
314 }
315
316 Ok(())
317 }
318}
319
320#[cfg(feature = "defmt")]
321impl defmt::Format for PlainHdr {
322 fn format(&self, f: defmt::Formatter<'_>) {
323 if !self.flags.is_empty() {
324 defmt::write!(f, "{},", self.flags);
325 }
326
327 defmt::write!(f, "SID:{:x},CTR:{:x}", self.sess_id, self.ctr);
328
329 if self.is_control_msg() {
330 defmt::write!(f, ",C");
331 }
332 if self.is_privacy() {
333 defmt::write!(f, ",P");
334 }
335
336 if let Some(src_nodeid) = self.get_src_nodeid() {
337 defmt::write!(f, ",SRC:{:x}", src_nodeid);
338 }
339
340 if let Some(dst_nodeid) = self.get_dst_unicast_nodeid() {
341 defmt::write!(f, ",DST:{:x}", dst_nodeid);
342 }
343
344 if let Some(dst_group_nodeid) = self.get_dst_groupcast_nodeid() {
345 defmt::write!(f, ",GRP:{:x}", dst_group_nodeid);
346 }
347 }
348}