smoltcp/wire/sixlowpan/
frag.rs1use super::{DISPATCH_FIRST_FRAGMENT_HEADER, DISPATCH_FRAGMENT_HEADER};
6use crate::wire::{Error, Result};
7use crate::wire::{Ieee802154Address, Ieee802154Repr};
8use byteorder::{ByteOrder, NetworkEndian};
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
12#[cfg_attr(feature = "defmt", derive(defmt::Format))]
13pub struct Key {
14 pub(crate) ll_src_addr: Ieee802154Address,
15 pub(crate) ll_dst_addr: Ieee802154Address,
16 pub(crate) datagram_size: u16,
17 pub(crate) datagram_tag: u16,
18}
19
20#[derive(Debug, Clone)]
45#[cfg_attr(feature = "defmt", derive(defmt::Format))]
46pub struct Packet<T: AsRef<[u8]>> {
47 buffer: T,
48}
49
50pub const FIRST_FRAGMENT_HEADER_SIZE: usize = 4;
51pub const NEXT_FRAGMENT_HEADER_SIZE: usize = 5;
52
53mod field {
54 use crate::wire::field::*;
55
56 pub const DISPATCH: usize = 0;
57 pub const DATAGRAM_SIZE: Field = 0..2;
58 pub const DATAGRAM_TAG: Field = 2..4;
59 pub const DATAGRAM_OFFSET: usize = 4;
60
61 pub const FIRST_FRAGMENT_REST: Rest = super::FIRST_FRAGMENT_HEADER_SIZE..;
62 pub const NEXT_FRAGMENT_REST: Rest = super::NEXT_FRAGMENT_HEADER_SIZE..;
63}
64
65impl<T: AsRef<[u8]>> Packet<T> {
66 pub const fn new_unchecked(buffer: T) -> Self {
68 Self { buffer }
69 }
70
71 pub fn new_checked(buffer: T) -> Result<Self> {
76 let packet = Self::new_unchecked(buffer);
77 packet.check_len()?;
78
79 let dispatch = packet.dispatch();
80
81 if dispatch != DISPATCH_FIRST_FRAGMENT_HEADER && dispatch != DISPATCH_FRAGMENT_HEADER {
82 return Err(Error);
83 }
84
85 Ok(packet)
86 }
87
88 pub fn check_len(&self) -> Result<()> {
91 let buffer = self.buffer.as_ref();
92 if buffer.is_empty() {
93 return Err(Error);
94 }
95
96 match self.dispatch() {
97 DISPATCH_FIRST_FRAGMENT_HEADER if buffer.len() >= FIRST_FRAGMENT_HEADER_SIZE => Ok(()),
98 DISPATCH_FIRST_FRAGMENT_HEADER if buffer.len() < FIRST_FRAGMENT_HEADER_SIZE => {
99 Err(Error)
100 }
101 DISPATCH_FRAGMENT_HEADER if buffer.len() >= NEXT_FRAGMENT_HEADER_SIZE => Ok(()),
102 DISPATCH_FRAGMENT_HEADER if buffer.len() < NEXT_FRAGMENT_HEADER_SIZE => Err(Error),
103 _ => Err(Error),
104 }
105 }
106
107 pub fn into_inner(self) -> T {
109 self.buffer
110 }
111
112 pub fn dispatch(&self) -> u8 {
114 let raw = self.buffer.as_ref();
115 raw[field::DISPATCH] >> 3
116 }
117
118 pub fn datagram_size(&self) -> u16 {
120 let raw = self.buffer.as_ref();
121 NetworkEndian::read_u16(&raw[field::DATAGRAM_SIZE]) & 0b111_1111_1111
122 }
123
124 pub fn datagram_tag(&self) -> u16 {
126 let raw = self.buffer.as_ref();
127 NetworkEndian::read_u16(&raw[field::DATAGRAM_TAG])
128 }
129
130 pub fn datagram_offset(&self) -> u8 {
132 match self.dispatch() {
133 DISPATCH_FIRST_FRAGMENT_HEADER => 0,
134 DISPATCH_FRAGMENT_HEADER => {
135 let raw = self.buffer.as_ref();
136 raw[field::DATAGRAM_OFFSET]
137 }
138 _ => unreachable!(),
139 }
140 }
141
142 pub fn is_first_fragment(&self) -> bool {
144 self.dispatch() == DISPATCH_FIRST_FRAGMENT_HEADER
145 }
146
147 pub fn get_key(&self, ieee802154_repr: &Ieee802154Repr) -> Key {
149 Key {
150 ll_src_addr: ieee802154_repr.src_addr.unwrap(),
151 ll_dst_addr: ieee802154_repr.dst_addr.unwrap(),
152 datagram_size: self.datagram_size(),
153 datagram_tag: self.datagram_tag(),
154 }
155 }
156}
157
158impl<'a, T: AsRef<[u8]> + ?Sized> Packet<&'a T> {
159 pub fn payload(&self) -> &'a [u8] {
161 match self.dispatch() {
162 DISPATCH_FIRST_FRAGMENT_HEADER => {
163 let raw = self.buffer.as_ref();
164 &raw[field::FIRST_FRAGMENT_REST]
165 }
166 DISPATCH_FRAGMENT_HEADER => {
167 let raw = self.buffer.as_ref();
168 &raw[field::NEXT_FRAGMENT_REST]
169 }
170 _ => unreachable!(),
171 }
172 }
173}
174
175impl<T: AsRef<[u8]> + AsMut<[u8]>> Packet<T> {
176 fn set_dispatch_field(&mut self, value: u8) {
177 let raw = self.buffer.as_mut();
178 raw[field::DISPATCH] = (raw[field::DISPATCH] & !(0b11111 << 3)) | (value << 3);
179 }
180
181 fn set_datagram_size(&mut self, size: u16) {
182 let raw = self.buffer.as_mut();
183 let mut v = NetworkEndian::read_u16(&raw[field::DATAGRAM_SIZE]);
184 v = (v & !0b111_1111_1111) | size;
185
186 NetworkEndian::write_u16(&mut raw[field::DATAGRAM_SIZE], v);
187 }
188
189 fn set_datagram_tag(&mut self, tag: u16) {
190 let raw = self.buffer.as_mut();
191 NetworkEndian::write_u16(&mut raw[field::DATAGRAM_TAG], tag);
192 }
193
194 fn set_datagram_offset(&mut self, offset: u8) {
195 let raw = self.buffer.as_mut();
196 raw[field::DATAGRAM_OFFSET] = offset;
197 }
198}
199
200#[derive(Debug, PartialEq, Eq, Clone, Copy)]
202pub enum Repr {
203 FirstFragment { size: u16, tag: u16 },
204 Fragment { size: u16, tag: u16, offset: u8 },
205}
206
207impl core::fmt::Display for Repr {
208 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
209 match self {
210 Repr::FirstFragment { size, tag } => {
211 write!(f, "FirstFrag size={size} tag={tag}")
212 }
213 Repr::Fragment { size, tag, offset } => {
214 write!(f, "NthFrag size={size} tag={tag} offset={offset}")
215 }
216 }
217 }
218}
219
220#[cfg(feature = "defmt")]
221impl defmt::Format for Repr {
222 fn format(&self, fmt: defmt::Formatter) {
223 match self {
224 Repr::FirstFragment { size, tag } => {
225 defmt::write!(fmt, "FirstFrag size={} tag={}", size, tag);
226 }
227 Repr::Fragment { size, tag, offset } => {
228 defmt::write!(fmt, "NthFrag size={} tag={} offset={}", size, tag, offset);
229 }
230 }
231 }
232}
233
234impl Repr {
235 pub fn parse<T: AsRef<[u8]>>(packet: &Packet<T>) -> Result<Self> {
237 packet.check_len()?;
238 let size = packet.datagram_size();
239 let tag = packet.datagram_tag();
240
241 match packet.dispatch() {
242 DISPATCH_FIRST_FRAGMENT_HEADER => Ok(Self::FirstFragment { size, tag }),
243 DISPATCH_FRAGMENT_HEADER => Ok(Self::Fragment {
244 size,
245 tag,
246 offset: packet.datagram_offset(),
247 }),
248 _ => Err(Error),
249 }
250 }
251
252 pub const fn buffer_len(&self) -> usize {
254 match self {
255 Self::FirstFragment { .. } => field::FIRST_FRAGMENT_REST.start,
256 Self::Fragment { .. } => field::NEXT_FRAGMENT_REST.start,
257 }
258 }
259
260 pub fn emit<T: AsRef<[u8]> + AsMut<[u8]>>(&self, packet: &mut Packet<T>) {
262 match self {
263 Self::FirstFragment { size, tag } => {
264 packet.set_dispatch_field(DISPATCH_FIRST_FRAGMENT_HEADER);
265 packet.set_datagram_size(*size);
266 packet.set_datagram_tag(*tag);
267 }
268 Self::Fragment { size, tag, offset } => {
269 packet.set_dispatch_field(DISPATCH_FRAGMENT_HEADER);
270 packet.set_datagram_size(*size);
271 packet.set_datagram_tag(*tag);
272 packet.set_datagram_offset(*offset);
273 }
274 }
275 }
276}