1use crate::link::constant;
2use crate::link::error::*;
3use crate::link::header::{AnyAddress, ControlField, Header};
4use crate::link::LinkErrorMode;
5use crate::util::slice_ext::*;
6
7use scursor::{ReadCursor, ReadError};
8
9#[derive(Copy, Clone)]
10enum ParseState {
11 FindSync1,
12 FindSync2,
13 ReadHeader,
14 ReadBody(Header, usize), }
16
17pub(crate) struct FramePayload {
18 length: usize,
19 buffer: [u8; constant::MAX_FRAME_PAYLOAD_LENGTH],
20}
21
22impl FramePayload {
23 pub(crate) fn new() -> Self {
24 Self {
25 length: 0,
26 buffer: [0; constant::MAX_FRAME_PAYLOAD_LENGTH],
27 }
28 }
29
30 pub(crate) fn clear(&mut self) {
31 self.length = 0;
32 }
33
34 pub(crate) fn get(&self) -> &[u8] {
35 &self.buffer[0..self.length]
36 }
37
38 pub(crate) fn push(&mut self, data: &[u8]) -> Result<(), LogicError> {
39 let mut buff = self.buffer.as_mut();
40 let dest = buff.np_get_mut(self.length..self.length + data.len())?;
41 dest.copy_from_slice(data);
42 self.length += data.len();
43 Ok(())
44 }
45}
46
47impl Default for FramePayload {
48 fn default() -> Self {
49 Self::new()
50 }
51}
52
53pub(crate) struct Parser {
54 mode: LinkErrorMode,
55 state: ParseState,
56}
57
58impl From<ReadError> for ParseError {
59 fn from(_: ReadError) -> Self {
60 ParseError::BadLogic(LogicError::BadRead)
61 }
62}
63
64impl From<FrameError> for ParseError {
65 fn from(err: FrameError) -> Self {
66 ParseError::BadFrame(err)
67 }
68}
69
70impl From<LogicError> for ParseError {
71 fn from(err: LogicError) -> Self {
72 ParseError::BadLogic(err)
73 }
74}
75
76impl Parser {
77 pub(crate) fn new(mode: LinkErrorMode) -> Parser {
78 Parser {
79 mode,
80 state: ParseState::FindSync1,
81 }
82 }
83
84 pub(crate) fn reset(&mut self) {
85 self.state = ParseState::FindSync1;
86 }
87
88 pub(crate) fn parse(
89 &mut self,
90 cursor: &mut ReadCursor,
91 payload: &mut FramePayload,
92 ) -> Result<Option<Header>, ParseError> {
93 loop {
94 if self.mode == LinkErrorMode::Close {
95 return self.parse_impl(cursor, payload);
96 }
97
98 let res = cursor.transaction(|cur| self.parse_impl(cur, payload));
99
100 match res {
101 Ok(x) => return Ok(x),
102 Err(_) => {
103 let _ = cursor.read_u8(); self.reset();
105 }
107 }
108 }
109 }
110
111 fn parse_impl(
112 &mut self,
113 cursor: &mut ReadCursor,
114 payload: &mut FramePayload,
115 ) -> Result<Option<Header>, ParseError> {
116 loop {
117 let start = cursor.remaining();
118
119 match self.state {
120 ParseState::FindSync1 => self.parse_sync1(cursor)?,
121 ParseState::FindSync2 => self.parse_sync2(cursor)?,
122 ParseState::ReadHeader => self.parse_header(cursor)?,
123 ParseState::ReadBody(header, length) => {
124 if let Some(()) = self.parse_body(length, cursor, payload)? {
125 return Ok(Some(header));
126 }
127 }
128 }
129
130 let end = cursor.remaining();
131
132 if start == end {
133 return Ok(None);
135 }
136 }
137 }
138
139 fn calc_trailer_length(data_length: u8) -> usize {
140 let div16: usize = data_length as usize / constant::MAX_BLOCK_SIZE;
141 let mod16: usize = data_length as usize % constant::MAX_BLOCK_SIZE;
142
143 if mod16 == 0 {
144 div16 * constant::MAX_BLOCK_SIZE_WITH_CRC
145 } else {
146 (div16 * constant::MAX_BLOCK_SIZE_WITH_CRC) + mod16 + constant::CRC_LENGTH
147 }
148 }
149
150 fn parse_sync1(&mut self, cursor: &mut ReadCursor) -> Result<(), ParseError> {
151 if cursor.is_empty() {
152 return Ok(());
153 }
154
155 let x = cursor.read_u8()?;
156
157 if x != 0x05 {
158 return Err(FrameError::UnexpectedStart1(x).into());
159 }
160
161 self.state = ParseState::FindSync2;
162 Ok(())
163 }
164
165 fn parse_sync2(&mut self, cursor: &mut ReadCursor) -> Result<(), ParseError> {
166 if cursor.is_empty() {
167 return Ok(());
168 }
169
170 let x = cursor.read_u8()?;
171
172 if x != 0x64 {
173 return Err(FrameError::UnexpectedStart2(x).into());
174 }
175
176 self.state = ParseState::ReadHeader;
177 Ok(())
178 }
179
180 fn parse_header(&mut self, cursor: &mut ReadCursor) -> Result<(), ParseError> {
181 if cursor.remaining() < 8 {
182 return Ok(());
183 }
184
185 let crc_bytes = cursor.read_bytes(6)?;
186 let crc_value = cursor.read_u16_le()?;
187
188 let mut cursor = ReadCursor::new(crc_bytes);
189 let len = cursor.read_u8()?;
190
191 let header = Header::new(
192 ControlField::from(cursor.read_u8()?),
193 AnyAddress::from(cursor.read_u16_le()?),
194 AnyAddress::from(cursor.read_u16_le()?),
195 );
196
197 if len < 5 {
198 return Err(FrameError::BadLength(len).into());
199 }
200
201 let expected_crc = super::crc::calc_crc_with_0564(crc_bytes);
202 if crc_value != expected_crc {
203 return Err(FrameError::BadHeaderCrc.into());
204 }
205
206 let trailer_length = Self::calc_trailer_length(len - 5); self.state = ParseState::ReadBody(header, trailer_length);
209 Ok(())
210 }
211
212 fn parse_body(
213 &mut self,
214 trailer_length: usize,
215 cursor: &mut ReadCursor,
216 payload: &mut FramePayload,
217 ) -> Result<Option<()>, ParseError> {
218 if cursor.remaining() < trailer_length {
219 return Ok(None);
220 }
221
222 payload.clear();
223
224 let body = cursor.read_bytes(trailer_length)?;
225
226 for block in body.chunks(18) {
227 if block.len() < 3 {
228 return Err(LogicError::BadSize.into());
230 }
231
232 let data_len = block.len() - 2;
233
234 let (data, crc) = block.np_split_at(data_len)?;
235 let crc_value = ReadCursor::new(crc).read_u16_le()?;
236 let calc_crc = super::crc::calc_crc(data);
237
238 if crc_value != calc_crc {
239 return Err(FrameError::BadBodyCrc.into());
240 }
241
242 payload.push(data)?;
244 }
245
246 self.state = ParseState::FindSync1;
247 Ok(Some(()))
248 }
249}
250
251#[cfg(test)]
252mod test {
253 use super::super::test_data::*;
254 use super::*;
255
256 fn test_frame_parsing(parser: &mut Parser, frame: &TestFrame) {
257 let mut cursor = ReadCursor::new(frame.bytes);
258 let mut payload = FramePayload::new();
259 let header: Header = parser.parse(&mut cursor, &mut payload).unwrap().unwrap();
260 assert_eq!(cursor.remaining(), 0);
261 assert_eq!(header, frame.header);
262 assert_eq!(payload.get(), frame.payload)
263 }
264
265 #[test]
266 fn catches_bad_start1() {
267 let mut parser = Parser::new(LinkErrorMode::Close);
268 let mut cursor = ReadCursor::new(&[0x06]);
269 let mut payload = FramePayload::new();
270
271 assert_eq!(
272 parser.parse(&mut cursor, &mut payload),
273 Err(ParseError::BadFrame(FrameError::UnexpectedStart1(0x06)))
274 );
275
276 assert!(cursor.is_empty());
277 }
278
279 #[test]
280 fn catches_bad_start2() {
281 let mut parser = Parser::new(LinkErrorMode::Close);
282 let mut cursor = ReadCursor::new(&[0x05, 0x65]);
283 let mut payload = FramePayload::new();
284
285 assert_eq!(
286 parser.parse(&mut cursor, &mut payload),
287 Err(ParseError::BadFrame(FrameError::UnexpectedStart2(0x65)))
288 );
289
290 assert!(cursor.is_empty());
291 }
292
293 #[test]
294 fn catches_bad_length() {
295 let mut parser = Parser::new(LinkErrorMode::Close);
296 let mut cursor =
297 ReadCursor::new(&[0x05, 0x64, 0x04, 0xC0, 0x01, 0x00, 0x00, 0x04, 0xE9, 0x21]);
298 let mut payload = FramePayload::new();
299
300 assert_eq!(
301 parser.parse(&mut cursor, &mut payload),
302 Err(ParseError::BadFrame(FrameError::BadLength(4)))
303 );
304 assert_eq!(cursor.remaining(), 0);
305 }
306
307 #[test]
308 fn header_parse_catches_bad_crc() {
309 let mut parser = Parser::new(LinkErrorMode::Close);
310 let mut cursor =
311 ReadCursor::new(&[0x05, 0x64, 0x05, 0xC0, 0x01, 0x00, 0x00, 0x04, 0xE9, 0x20]);
312 let mut payload = FramePayload::new();
313
314 assert_eq!(
315 parser.parse(&mut cursor, &mut payload),
316 Err(ParseError::BadFrame(FrameError::BadHeaderCrc))
317 );
318 assert_eq!(cursor.remaining(), 0);
319 }
320
321 #[test]
322 fn catches_bad_crc_in_body() {
323 let data: [u8; 27] = [
324 0x05, 0x64, 0x14, 0xF3, 0x01, 0x00, 0x00, 0x04, 0x0A, 0x3B, 0xC0, 0xC3, 0x01, 0x3C, 0x02, 0x06, 0x3C, 0x03, 0x06, 0x3C, 0x04, 0x06, 0x3C, 0x01,
327 0x06, 0x9A, 0xFF,
328 ];
329
330 let mut parser = Parser::new(LinkErrorMode::Close);
331 let mut cursor = ReadCursor::new(&data);
332 let mut payload = FramePayload::new();
333
334 assert_eq!(
335 parser.parse(&mut cursor, &mut payload),
336 Err(ParseError::BadFrame(FrameError::BadBodyCrc)),
337 );
338 assert_eq!(cursor.remaining(), 0);
339 }
340
341 #[test]
342 fn can_parse_multiple_different_frames_sequentially() {
343 let mut parser = Parser::new(LinkErrorMode::Close);
344 test_frame_parsing(&mut parser, &RESET_LINK);
345 test_frame_parsing(&mut parser, &ACK);
346 test_frame_parsing(&mut parser, &CONFIRM_USER_DATA);
347 }
348
349 #[test]
350 fn can_consume_leading_garbage_in_discard_mode() {
351 let mut parser = Parser::new(LinkErrorMode::Discard);
352 let data = [
354 0x06, 0x05, 0x07, 0x05, 0x64, 0x05, 0x05, 0x64, 0x05, 0xC0, 0x01, 0x00, 0x00, 0x04,
355 0xE9, 0x21,
356 ];
357 let mut cursor = ReadCursor::new(&data);
358 let mut payload = FramePayload::new();
359
360 assert_eq!(
362 parser.parse(&mut cursor, &mut payload),
363 Ok(Some(RESET_LINK.header)),
364 );
365 }
366}