1use byte::{check_len, BytesExt, TryRead, TryWrite, LE};
8use cipher::{consts::U16, BlockCipher, NewBlockCipher};
9use hash32_derive::Hash32;
10
11pub use super::frame_control::{AddressMode, FrameType, FrameVersion};
12use super::DecodeError;
13use super::{
14 frame_control::{mask, offset},
15 security::{KeyDescriptorLookup, SecurityContext},
16};
17use super::{security::AuxiliarySecurityHeader, EncodeError};
18
19#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
25#[cfg_attr(feature = "defmt", derive(defmt::Format))]
26pub struct Header {
27 pub frame_type: FrameType,
30
31 pub frame_pending: bool,
36
37 pub ack_request: bool,
44
45 pub pan_id_compress: bool,
54
55 pub seq_no_suppress: bool,
57
58 pub ie_present: bool,
60
61 pub version: FrameVersion,
63
64 pub seq: u8,
73
74 pub destination: Option<Address>,
76
77 pub source: Option<Address>,
79
80 pub auxiliary_security_header: Option<AuxiliarySecurityHeader>,
83}
84
85impl Header {
86 pub fn get_octet_size(&self) -> usize {
88 let mut len = 3;
90
91 for i in [self.destination, self.source].iter() {
92 match i {
93 Some(addr) => {
94 len += 2;
96 match addr {
98 Address::Short(..) => len += 2,
99 Address::Extended(..) => len += 8,
100 }
101 }
102 _ => {}
103 }
104 }
105 len
106 }
107
108 pub fn has_security(&self) -> bool {
110 self.auxiliary_security_header.is_some()
111 }
112}
113
114impl TryRead<'_> for Header {
115 fn try_read(bytes: &[u8], _ctx: ()) -> byte::Result<(Self, usize)> {
116 let offset = &mut 0;
117 check_len(&bytes, 3)?;
119
120 let bits: u16 = bytes.read_with(offset, LE)?;
122
123 let frame_type =
124 ((bits & mask::FRAME_TYPE) >> offset::FRAME_TYPE) as u8;
125 let security = ((bits & mask::SECURITY) >> offset::SECURITY) as u8;
126
127 let frame_pending = ((bits & mask::PENDING) >> offset::PENDING) as u8;
128 let ack_request = ((bits & mask::ACK) >> offset::ACK) as u8;
129 let pan_id_compress =
130 ((bits & mask::PAN_ID_COMPRESS) >> offset::PAN_ID_COMPRESS) as u8;
131
132 let seq_no_suppress =
133 ((bits & mask::SEQ_NO_SUPPRESS) >> offset::SEQ_NO_SUPPRESS) as u8;
134 let ie_present =
135 ((bits & mask::IE_PRESENT) >> offset::IE_PRESENT) as u8;
136
137 let dest_addr_mode =
138 ((bits & mask::DEST_ADDR_MODE) >> offset::DEST_ADDR_MODE) as u8;
139
140 let version = ((bits & mask::VERSION) >> offset::VERSION) as u8;
141 let src_addr_mode =
142 ((bits & mask::SRC_ADDR_MODE) >> offset::SRC_ADDR_MODE) as u8;
143
144 let version = FrameVersion::from_bits(version)
145 .ok_or(DecodeError::InvalidFrameVersion(version))?;
146 let frame_type = FrameType::from_bits(frame_type)
147 .ok_or(DecodeError::InvalidFrameType(frame_type))?;
148 let dest_addr_mode = AddressMode::from_bits(dest_addr_mode)?;
149 let src_addr_mode = AddressMode::from_bits(src_addr_mode)?;
150
151 let security = security > 0;
153 let frame_pending = frame_pending > 0;
154 let ack_request = ack_request > 0;
155 let pan_id_compress = pan_id_compress > 0;
156 let seq_no_suppress = seq_no_suppress > 0;
157 let ie_present = ie_present > 0;
158
159 let seq = bytes.read(offset)?;
162
163 let destination = match dest_addr_mode {
164 AddressMode::None => None,
165 AddressMode::Short => {
166 Some(Address::Short(bytes.read(offset)?, bytes.read(offset)?))
167 }
168 AddressMode::Extended => Some(Address::Extended(
169 bytes.read(offset)?,
170 bytes.read(offset)?,
171 )),
172 };
173
174 if pan_id_compress {
175 destination.ok_or(byte::Error::BadInput {
176 err: "InvalidAddressMode",
177 })?;
178 }
179
180 let source = match src_addr_mode {
181 AddressMode::None => None,
182 AddressMode::Short => {
183 if pan_id_compress {
184 Some(Address::Short(
185 destination.unwrap().pan_id(),
186 bytes.read(offset)?,
187 ))
188 } else {
189 Some(Address::Short(
190 bytes.read(offset)?,
191 bytes.read(offset)?,
192 ))
193 }
194 }
195 AddressMode::Extended => {
196 if pan_id_compress {
197 Some(Address::Extended(
198 destination.unwrap().pan_id(),
199 bytes.read(offset)?,
200 ))
201 } else {
202 Some(Address::Extended(
203 bytes.read(offset)?,
204 bytes.read(offset)?,
205 ))
206 }
207 }
208 };
209
210 let auxiliary_security_header = match security {
211 true => Some(bytes.read(offset)?),
212 false => None,
213 };
214
215 let header = Header {
216 frame_type,
217 frame_pending,
218 ack_request,
219 pan_id_compress,
220 seq_no_suppress,
221 ie_present,
222 version,
223 seq,
224 destination,
225 source,
226 auxiliary_security_header,
227 };
228
229 Ok((header, *offset))
230 }
231}
232
233impl<AEADBLKCIPH, KEYDESCLO>
234 TryWrite<&Option<&mut SecurityContext<AEADBLKCIPH, KEYDESCLO>>> for Header
235where
236 AEADBLKCIPH: NewBlockCipher + BlockCipher<BlockSize = U16>,
237 KEYDESCLO: KeyDescriptorLookup<AEADBLKCIPH::KeySize>,
238{
239 fn try_write(
240 self,
241 bytes: &mut [u8],
242 sec_ctx: &Option<&mut SecurityContext<AEADBLKCIPH, KEYDESCLO>>,
243 ) -> byte::Result<usize> {
244 let offset = &mut 0;
245 let dest_addr_mode = AddressMode::from(self.destination);
246 let src_addr_mode = AddressMode::from(self.source);
247
248 let security = self.auxiliary_security_header.is_some();
249
250 let frame_control_raw = (self.frame_type as u16) << offset::FRAME_TYPE
251 | (security as u16) << offset::SECURITY
252 | (self.frame_pending as u16) << offset::PENDING
253 | (self.ack_request as u16) << offset::ACK
254 | (self.pan_id_compress as u16) << offset::PAN_ID_COMPRESS
255 | (dest_addr_mode as u16) << offset::DEST_ADDR_MODE
256 | (self.version as u16) << offset::VERSION
257 | (src_addr_mode as u16) << offset::SRC_ADDR_MODE;
258
259 bytes.write_with(offset, frame_control_raw, LE)?;
260
261 bytes.write(offset, self.seq)?;
263
264 if (self.destination.is_none() || self.source.is_none())
265 && self.pan_id_compress
266 {
267 return Err(EncodeError::DisallowedPanIdCompress)?;
268 }
269
270 if let Some(destination) = self.destination {
272 bytes.write_with(offset, destination, AddressEncoding::Normal)?;
273 }
274
275 match (self.source, self.pan_id_compress) {
276 (Some(source), true) => {
277 bytes.write_with(
278 offset,
279 source,
280 AddressEncoding::Compressed,
281 )?;
282 }
283 (Some(source), false) => {
284 bytes.write_with(offset, source, AddressEncoding::Normal)?;
285 }
286 (None, true) => {
287 panic!("frame control request compress source address without contain this address")
288 }
289 (None, false) => (),
290 }
291
292 if security && sec_ctx.is_none() {
293 return Err(EncodeError::MissingSecurityCtx)?;
294 } else if security {
295 match self.auxiliary_security_header {
296 Some(aux_sec_head) => match sec_ctx {
297 Some(sec_ctx) => {
298 bytes.write_with(offset, aux_sec_head, sec_ctx)?;
299 }
300 None => return Err(EncodeError::UnknownError)?,
301 },
302 None => return Err(EncodeError::UnknownError)?,
303 }
304 }
305 Ok(*offset)
306 }
307}
308
309#[derive(Clone, Copy, Debug, Eq, Hash, Hash32, PartialEq)]
321#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
322#[cfg_attr(feature = "defmt", derive(defmt::Format))]
323pub struct PanId(pub u16);
324
325impl PanId {
326 pub fn broadcast() -> Self {
328 Self(0xffff)
329 }
330}
331
332impl TryWrite for PanId {
333 fn try_write(self, bytes: &mut [u8], _ctx: ()) -> byte::Result<usize> {
334 let offset = &mut 0;
335 bytes.write_with(offset, self.0, LE)?;
336 Ok(*offset)
337 }
338}
339
340impl TryRead<'_> for PanId {
341 fn try_read(bytes: &[u8], _ctx: ()) -> byte::Result<(Self, usize)> {
342 let offset = &mut 0;
343 Ok((Self(bytes.read_with(offset, LE)?), *offset))
344 }
345}
346
347#[derive(Clone, Copy, Debug, Eq, Hash, Hash32, PartialEq)]
360#[cfg_attr(feature = "defmt", derive(defmt::Format))]
361#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
362
363pub struct ShortAddress(pub u16);
364
365impl ShortAddress {
366 pub const BROADCAST: Self = ShortAddress(0xffff);
368
369 pub fn broadcast() -> Self {
371 ShortAddress(0xffff)
372 }
373}
374
375impl TryWrite for ShortAddress {
376 fn try_write(self, bytes: &mut [u8], _ctx: ()) -> byte::Result<usize> {
377 let offset = &mut 0;
378 bytes.write_with(offset, self.0, LE)?;
379 Ok(*offset)
380 }
381}
382
383impl TryRead<'_> for ShortAddress {
384 fn try_read(bytes: &[u8], _ctx: ()) -> byte::Result<(Self, usize)> {
385 let offset = &mut 0;
386 Ok((Self(bytes.read_with(offset, LE)?), *offset))
387 }
388}
389
390#[derive(Clone, Copy, Debug, Eq, Hash, Hash32, PartialEq)]
402#[cfg_attr(feature = "defmt", derive(defmt::Format))]
403#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
404
405pub struct ExtendedAddress(pub u64);
406
407impl ExtendedAddress {
408 pub const BROADCAST: Self = ExtendedAddress(0xffffffffffffffffu64);
410
411 pub fn broadcast() -> Self {
413 ExtendedAddress(0xffffffffffffffffu64)
414 }
415}
416
417impl TryWrite for ExtendedAddress {
418 fn try_write(self, bytes: &mut [u8], _ctx: ()) -> byte::Result<usize> {
419 let offset = &mut 0;
420 bytes.write_with(offset, self.0, LE)?;
421 Ok(*offset)
422 }
423}
424
425impl TryRead<'_> for ExtendedAddress {
426 fn try_read(bytes: &[u8], _ctx: ()) -> byte::Result<(Self, usize)> {
427 let offset = &mut 0;
428 Ok((Self(bytes.read_with(offset, LE)?), *offset))
429 }
430}
431
432#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
434#[cfg_attr(feature = "defmt", derive(defmt::Format))]
435#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
436pub enum Address {
437 Short(PanId, ShortAddress),
439 Extended(PanId, ExtendedAddress),
441}
442
443#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
444#[cfg_attr(feature = "defmt", derive(defmt::Format))]
445enum AddressEncoding {
446 Normal,
447 Compressed,
448}
449
450impl TryWrite<AddressEncoding> for Address {
451 fn try_write(
452 self,
453 bytes: &mut [u8],
454 enc: AddressEncoding,
455 ) -> byte::Result<usize> {
456 let offset = &mut 0;
457 match (self, enc) {
458 (Address::Short(pan_id, addr), AddressEncoding::Normal) => {
459 bytes.write(offset, pan_id)?;
460 bytes.write(offset, addr)?;
461 }
462 (Address::Short(_pan_id, addr), AddressEncoding::Compressed) => {
463 bytes.write(offset, addr)?;
464 }
465 (Address::Extended(pan_id, addr), AddressEncoding::Normal) => {
466 bytes.write(offset, pan_id)?;
467 bytes.write(offset, addr)?;
468 }
469 (Address::Extended(_pan_id, addr), AddressEncoding::Compressed) => {
470 bytes.write(offset, addr)?;
471 }
472 }
473 Ok(*offset)
474 }
475}
476
477impl Address {
478 pub fn broadcast(mode: &AddressMode) -> Option<Self> {
480 match mode {
481 AddressMode::None => None,
482 AddressMode::Short => Some(Address::Short(
483 PanId::broadcast(),
484 ShortAddress::broadcast(),
485 )),
486 AddressMode::Extended => Some(Address::Extended(
487 PanId::broadcast(),
488 ExtendedAddress::broadcast(),
489 )),
490 }
491 }
492
493 pub fn pan_id(&self) -> PanId {
495 match *self {
496 Address::Short(pan_id, _) => pan_id,
497 Address::Extended(pan_id, _) => pan_id,
498 }
499 }
500}