Skip to content

Commit

Permalink
add: calc which header terminations are needed
Browse files Browse the repository at this point in the history
  • Loading branch information
thvdveld committed Feb 27, 2024
1 parent d308811 commit 08cefde
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 8 deletions.
8 changes: 6 additions & 2 deletions dot15d4/src/frame/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -367,11 +367,15 @@ impl<T: AsRef<[u8]> + AsMut<[u8]>> Frame<T> {
}

/// Set the Information Elements field values in the buffer, based on the given _.
pub fn set_information_elements(&mut self, ie: &InformationElementsRepr) {
pub fn set_information_elements(
&mut self,
ie: &InformationElementsRepr,
contains_payload: bool,
) {
let mut offset = 2;
offset += (!self.frame_control().sequence_number_suppression() as usize);
offset += self.addressing().len(&self.frame_control());
ie.emit(&mut self.buffer.as_mut()[offset..]);
ie.emit(&mut self.buffer.as_mut()[offset..], contains_payload);
}

/// Set the payload of the frame.
Expand Down
61 changes: 57 additions & 4 deletions dot15d4/src/frame/repr/ie/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,42 +40,95 @@ impl InformationElementsRepr {
}
}

/// The header terminations required to emit the Information Elements.
/// The first bool is the HT1, the second is the HT2, and the third is the PT.
fn header_terminations(&self, contains_payload: bool) -> (bool, bool, bool) {
match (
!self.header_information_elements.is_empty(),
!self.payload_information_elements.is_empty(),
contains_payload,
) {
// No IE lists, so no terminations.
(false, false, false) => (false, false, false),
// Only header IE list. The end of the frame can be determined by the length of the
// frame.
(true, false, false) => (false, false, false),
// Only payload IE list. The HT1 is required to terminate the header IE list.
(false, true, false) => (true, false, false),
// Both IE lists. The HT1 is required to terminate the header IE list.
// The payload HT is optional.
(true, true, false) => (true, false, false),
// No IE lists, so no terminations.
(false, false, true) => (false, false, false),
// No payload IE list. The HT2 is required to terminate the header IE list.
(true, false, true) => (false, true, false),
// No header IE list. The HT1 is required to terminate the payload IE list.
// The payload HT is optional.
(false, true, true) => (true, false, true),
// Both IE lists. The HT1 is required to terminate the header IE list.
// The payload HT is optional.
(true, true, true) => (true, false, true),
}
}

/// The buffer length required to emit the Information Elements.
pub fn buffer_len(&self) -> usize {
pub fn buffer_len(&self, contains_payload: bool) -> usize {
let mut len = 0;

let (ht1, ht2, pt) = self.header_terminations(contains_payload);

for ie in self.header_information_elements.iter() {
len += ie.buffer_len();
}

if !self.payload_information_elements.is_empty() {
if ht1 {
len += HeaderInformationElementRepr::HeaderTermination1.buffer_len();
}

if ht2 {
len += HeaderInformationElementRepr::HeaderTermination1.buffer_len();
}

for ie in self.payload_information_elements.iter() {
len += ie.buffer_len();
}

if pt {
len += PayloadInformationElementRepr::PayloadTermination.buffer_len();
}

len
}

/// Emit the Information Elements into a buffer.
pub fn emit(&self, buffer: &mut [u8]) {
pub fn emit(&self, buffer: &mut [u8], contains_payload: bool) {
let mut offset = 0;

let (ht1, ht2, pt) = self.header_terminations(contains_payload);

for ie in self.header_information_elements.iter() {
ie.emit(&mut buffer[offset..][..ie.buffer_len()]);
offset += ie.buffer_len();
}

if !self.payload_information_elements.is_empty() {
if ht1 {
HeaderInformationElementRepr::HeaderTermination1.emit(&mut buffer[offset..][..2]);
offset += 2;
}

if ht2 {
HeaderInformationElementRepr::HeaderTermination2.emit(&mut buffer[offset..][..2]);
offset += 2;
}

for ie in self.payload_information_elements.iter() {
ie.emit(&mut buffer[offset..][..ie.buffer_len()]);
offset += ie.buffer_len();
}

if pt {
PayloadInformationElementRepr::PayloadTermination.emit(&mut buffer[offset..][..2]);
offset += 2;
}
}
}
4 changes: 4 additions & 0 deletions dot15d4/src/frame/repr/ie/payloads.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use heapless::Vec;
#[derive(Debug)]
pub enum PayloadInformationElementRepr {
Mlme(Vec<NestedInformationElementRepr, 16>),
PayloadTermination,
}

impl PayloadInformationElementRepr {
Expand Down Expand Up @@ -44,6 +45,7 @@ impl PayloadInformationElementRepr {

len
}
Self::PayloadTermination => 0,
}
}

Expand All @@ -63,6 +65,7 @@ impl PayloadInformationElementRepr {
offset += ie.buffer_len();
}
}
Self::PayloadTermination => todo!(),
}
}
}
Expand All @@ -72,6 +75,7 @@ impl From<&PayloadInformationElementRepr> for PayloadGroupId {
use PayloadInformationElementRepr::*;
match val {
Mlme(_) => PayloadGroupId::Mlme,
PayloadTermination => PayloadGroupId::PayloadTermination,
}
}
}
4 changes: 2 additions & 2 deletions dot15d4/src/frame/repr/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ impl<'f> FrameRepr<'f> {
len += self.addressing_fields.buffer_len(&self.frame_control);

if let Some(ie) = &self.information_elements {
len += ie.buffer_len();
len += ie.buffer_len(self.payload.is_some());
}

if let Some(payload) = self.payload {
Expand All @@ -74,7 +74,7 @@ impl<'f> FrameRepr<'f> {
frame.set_addressing_fields(&self.addressing_fields);

if let Some(ie) = &self.information_elements {
frame.set_information_elements(ie);
frame.set_information_elements(ie, self.payload.is_some());
}

if let Some(payload) = self.payload {
Expand Down

0 comments on commit 08cefde

Please sign in to comment.