X-Git-Url: https://code.octet-stream.net/m17rt/blobdiff_plain/1f6748dd3cbe8df84adbeb905424ab284f4208b4..4e2358c2ade1278f4835bc263e7df1dd8e74e8c9:/m17core/src/tnc.rs diff --git a/m17core/src/tnc.rs b/m17core/src/tnc.rs index a847683..ae95628 100644 --- a/m17core/src/tnc.rs +++ b/m17core/src/tnc.rs @@ -26,7 +26,7 @@ impl SoftTnc { } /// Process an individual `Frame` that has been decoded by the modem. - pub fn handle_frame(&mut self, frame: Frame) -> Result<(), SoftTncError> { + pub fn handle_frame(&mut self, frame: Frame) { match frame { Frame::Lsf(lsf) => { // A new LSF implies a clean slate. @@ -40,6 +40,8 @@ impl SoftTnc { }) } Mode::Stream => { + let kiss = KissFrame::new_stream_setup(&lsf.0).unwrap(); + self.kiss_to_host(kiss); self.state = State::RxStream(RxStreamState { lsf, index: 0 }); } } @@ -63,6 +65,7 @@ impl SoftTnc { let end = start + payload_len; rx.packet[start..(start + payload_len)] .copy_from_slice(&packet.payload); + // TODO: compatible packets should be sent on port 0 too let kiss = KissFrame::new_full_packet(&rx.lsf.0, &rx.packet[0..end]) .unwrap(); @@ -87,9 +90,8 @@ impl SoftTnc { self.state = State::RxAcquiringStream(RxAcquiringStreamState { lich }); } else { rx.index = stream.frame_number + 1; - let kiss = KissFrame::new_stream_data(&stream.stream_data).unwrap(); + let kiss = KissFrame::new_stream_data(&stream).unwrap(); self.kiss_to_host(kiss); - // TODO: handle LICH contents to track META content // TODO: end stream if LICH updates indicate non-META part has changed // (this implies a new station) if stream.end_of_stream { @@ -125,7 +127,6 @@ impl SoftTnc { } } } - Ok(()) } /// Update the number of samples that have been received by the incoming stream, as a form of timekeeping @@ -143,7 +144,7 @@ impl SoftTnc { /// /// After each frame input, this should be consumed in a loop until length 0 is returned. /// This component will never block. Upstream interface can provide blocking `read()` if desired. - pub fn read_kiss(&mut self, target_buf: &mut [u8]) -> Result { + pub fn read_kiss(&mut self, target_buf: &mut [u8]) -> usize { match self.outgoing_kiss.as_mut() { Some(outgoing) => { let n = (outgoing.kiss_frame.len - outgoing.sent).min(target_buf.len()); @@ -153,13 +154,13 @@ impl SoftTnc { if outgoing.sent == outgoing.kiss_frame.len { self.outgoing_kiss = None; } - Ok(n) + n } - None => Ok(0), + None => 0, } } - pub fn write_kiss(&mut self, buf: &[u8]) -> Result { + pub fn write_kiss(&mut self, buf: &[u8]) -> usize { let target_buf = self.kiss_buffer.buf_remaining(); let n = buf.len().min(target_buf.len()); target_buf[0..n].copy_from_slice(&buf[0..n]); @@ -167,7 +168,7 @@ impl SoftTnc { while let Some(_kiss_frame) = self.kiss_buffer.next_frame() { // TODO: handle host-to-TNC message } - Ok(n) + n } fn kiss_to_host(&mut self, kiss_frame: KissFrame) { @@ -178,7 +179,7 @@ impl SoftTnc { } } -#[derive(Debug)] +#[derive(Debug, PartialEq, Eq, Clone)] pub enum SoftTncError { General(&'static str), InvalidState, @@ -228,3 +229,204 @@ struct RxPacketState { /// this will be between 0 and 32 inclusive. count: usize, } + +#[cfg(test)] +mod tests { + use super::*; + use crate::kiss::{KissCommand, PORT_STREAM}; + use crate::protocol::StreamFrame; + + // TODO: finish all handle_frame tests as below + // this will be much more straightforward when we have a way to create LSFs programatically + + // receiving a single-frame packet + + // receiving a multi-frame packet + + // part of one packet and then another + + #[test] + fn tnc_receive_stream() { + let lsf = LsfFrame([ + 255, 255, 255, 255, 255, 255, 0, 0, 0, 159, 221, 81, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 131, 53, + ]); + let stream1 = StreamFrame { + lich_idx: 0, + lich_part: [255, 255, 255, 255, 255], + frame_number: 0, + end_of_stream: false, + stream_data: [ + 128, 0, 119, 115, 220, 252, 41, 235, 8, 0, 116, 195, 94, 244, 45, 75, + ], + }; + let stream2 = StreamFrame { + lich_idx: 1, + lich_part: [255, 0, 0, 0, 159], + frame_number: 1, + end_of_stream: true, + stream_data: [ + 17, 0, 94, 82, 216, 135, 181, 15, 30, 0, 125, 195, 152, 183, 41, 57, + ], + }; + let mut tnc = SoftTnc::new(); + let mut kiss = KissFrame::new_empty(); + assert_eq!(tnc.read_kiss(&mut kiss.data), 0); + + tnc.handle_frame(Frame::Lsf(lsf)); + kiss.len = tnc.read_kiss(&mut kiss.data); + assert_eq!(kiss.command().unwrap(), KissCommand::DataFrame); + assert_eq!(kiss.port().unwrap(), PORT_STREAM); + + let mut payload_buf = [0u8; 2048]; + let n = kiss.decode_payload(&mut payload_buf).unwrap(); + assert_eq!(n, 30); + + tnc.handle_frame(Frame::Stream(stream1)); + kiss.len = tnc.read_kiss(&mut kiss.data); + assert_eq!(kiss.command().unwrap(), KissCommand::DataFrame); + assert_eq!(kiss.port().unwrap(), PORT_STREAM); + + let n = kiss.decode_payload(&mut payload_buf).unwrap(); + assert_eq!(n, 26); + + tnc.handle_frame(Frame::Stream(stream2)); + kiss.len = tnc.read_kiss(&mut kiss.data); + assert_eq!(kiss.command().unwrap(), KissCommand::DataFrame); + assert_eq!(kiss.port().unwrap(), PORT_STREAM); + + let n = kiss.decode_payload(&mut payload_buf).unwrap(); + assert_eq!(n, 26); + } + + #[test] + fn tnc_acquire_stream() { + let frames = [ + StreamFrame { + lich_idx: 0, + lich_part: [255, 255, 255, 255, 255], + frame_number: 0, + end_of_stream: false, + stream_data: [ + 128, 0, 119, 115, 220, 252, 41, 235, 8, 0, 116, 195, 94, 244, 45, 75, + ], + }, + StreamFrame { + lich_idx: 1, + lich_part: [255, 0, 0, 0, 159], + frame_number: 1, + end_of_stream: false, + stream_data: [ + 17, 0, 94, 82, 216, 135, 181, 15, 30, 0, 125, 195, 152, 183, 41, 57, + ], + }, + StreamFrame { + lich_idx: 2, + lich_part: [221, 81, 5, 5, 0], + frame_number: 2, + end_of_stream: false, + stream_data: [ + 17, 128, 93, 74, 154, 167, 169, 11, 20, 0, 116, 91, 158, 220, 45, 111, + ], + }, + StreamFrame { + lich_idx: 3, + lich_part: [0, 0, 0, 0, 0], + frame_number: 3, + end_of_stream: false, + stream_data: [ + 15, 128, 114, 83, 218, 252, 59, 111, 31, 128, 116, 91, 84, 231, 45, 105, + ], + }, + StreamFrame { + lich_idx: 4, + lich_part: [0, 0, 0, 0, 0], + frame_number: 4, + end_of_stream: false, + stream_data: [ + 9, 128, 119, 115, 220, 220, 57, 15, 48, 128, 124, 83, 158, 236, 181, 91, + ], + }, + StreamFrame { + lich_idx: 5, + lich_part: [0, 0, 0, 131, 53], + frame_number: 5, + end_of_stream: false, + stream_data: [ + 52, 0, 116, 90, 152, 167, 225, 216, 32, 0, 116, 83, 156, 212, 33, 216, + ], + }, + ]; + + let mut tnc = SoftTnc::new(); + let mut kiss = KissFrame::new_empty(); + for f in frames { + tnc.handle_frame(Frame::Stream(f)); + } + kiss.len = tnc.read_kiss(&mut kiss.data); + let mut payload_buf = [0u8; 2048]; + let n = kiss.decode_payload(&mut payload_buf).unwrap(); + assert_eq!(n, 30); + assert_eq!( + &payload_buf[0..30], + [ + 255, 255, 255, 255, 255, 255, 0, 0, 0, 159, 221, 81, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 131, 53, + ] + ); + } + + #[test] + fn tnc_handle_skipped_stream_frame() { + let lsf = LsfFrame([ + 255, 255, 255, 255, 255, 255, 0, 0, 0, 159, 221, 81, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 131, 53, + ]); + let stream1 = StreamFrame { + lich_idx: 0, + lich_part: [255, 255, 255, 255, 255], + frame_number: 0, + end_of_stream: false, + stream_data: [ + 128, 0, 119, 115, 220, 252, 41, 235, 8, 0, 116, 195, 94, 244, 45, 75, + ], + }; + let stream3 = StreamFrame { + lich_idx: 2, + lich_part: [221, 81, 5, 5, 0], + frame_number: 2, + end_of_stream: false, + stream_data: [ + 17, 128, 93, 74, 154, 167, 169, 11, 20, 0, 116, 91, 158, 220, 45, 111, + ], + }; + let mut tnc = SoftTnc::new(); + let mut kiss = KissFrame::new_empty(); + assert_eq!(tnc.read_kiss(&mut kiss.data), 0); + + tnc.handle_frame(Frame::Lsf(lsf)); + kiss.len = tnc.read_kiss(&mut kiss.data); + assert_eq!(kiss.command().unwrap(), KissCommand::DataFrame); + assert_eq!(kiss.port().unwrap(), PORT_STREAM); + + let mut payload_buf = [0u8; 2048]; + let n = kiss.decode_payload(&mut payload_buf).unwrap(); + assert_eq!(n, 30); + + tnc.handle_frame(Frame::Stream(stream1)); + kiss.len = tnc.read_kiss(&mut kiss.data); + assert_eq!(kiss.command().unwrap(), KissCommand::DataFrame); + assert_eq!(kiss.port().unwrap(), PORT_STREAM); + + let n = kiss.decode_payload(&mut payload_buf).unwrap(); + assert_eq!(n, 26); + + tnc.handle_frame(Frame::Stream(stream3)); + kiss.len = tnc.read_kiss(&mut kiss.data); + assert_eq!(kiss.command().unwrap(), KissCommand::DataFrame); + assert_eq!(kiss.port().unwrap(), PORT_STREAM); + + let n = kiss.decode_payload(&mut payload_buf).unwrap(); + assert_eq!(n, 26); + } +}