From 1b1501ac34de485da9af1e159c7b220e60ff86c0 Mon Sep 17 00:00:00 2001 From: Thomas Karpiniec Date: Sat, 1 Feb 2025 14:16:44 +1100 Subject: [PATCH] Add and test error if packet payload is too large --- m17app/src/app.rs | 45 +++++++++++++++++++++++++++++--- m17app/src/error.rs | 7 ++++- m17app/src/lib.rs | 3 +++ m17app/src/test_util.rs | 36 +++++++++++++++++++++++++ tools/m17rt-txpacket/src/main.rs | 3 ++- 5 files changed, 89 insertions(+), 5 deletions(-) create mode 100644 m17app/src/test_util.rs diff --git a/m17app/src/app.rs b/m17app/src/app.rs index 7f17df6..0abfab6 100644 --- a/m17app/src/app.rs +++ b/m17app/src/app.rs @@ -1,4 +1,5 @@ use crate::adapter::{PacketAdapter, StreamAdapter}; +use crate::error::M17Error; use crate::link_setup::LinkSetup; use crate::tnc::Tnc; use crate::{LsfFrame, PacketType, StreamFrame}; @@ -85,11 +86,18 @@ pub struct TxHandle { } impl TxHandle { - pub fn transmit_packet(&self, link_setup: &LinkSetup, packet_type: PacketType, payload: &[u8]) { + pub fn transmit_packet( + &self, + link_setup: &LinkSetup, + packet_type: PacketType, + payload: &[u8], + ) -> Result<(), M17Error> { let (pack_type, pack_type_len) = packet_type.as_proto(); if pack_type_len + payload.len() > 823 { - // TODO: error for invalid transmission type - return; + return Err(M17Error::PacketTooLarge { + provided: payload.len(), + capacity: 823 - pack_type_len, + }); } let mut full_payload = vec![]; full_payload.extend_from_slice(&pack_type[0..pack_type_len]); @@ -98,6 +106,7 @@ impl TxHandle { full_payload.extend_from_slice(&crc.to_be_bytes()); let kiss_frame = KissFrame::new_full_packet(&link_setup.raw.0, &full_payload).unwrap(); let _ = self.event_tx.send(TncControlEvent::Kiss(kiss_frame)); + Ok(()) } pub fn transmit_stream_start(&self, link_setup: &LinkSetup) { @@ -283,3 +292,33 @@ fn spawn_writer(mut tnc: T, event_rx: mpsc::Receiver) { } }); } + +#[cfg(test)] +mod tests { + use crate::{link_setup::M17Address, test_util::NullTnc}; + + use super::*; + + #[test] + fn packet_payload_len() { + let app = M17App::new(NullTnc); + let res = app.tx().transmit_packet( + &LinkSetup::new_packet(&M17Address::new_broadcast(), &M17Address::new_broadcast()), + PacketType::Raw, + &[0u8; 100], + ); + assert_eq!(res, Ok(())); + let res = app.tx().transmit_packet( + &LinkSetup::new_packet(&M17Address::new_broadcast(), &M17Address::new_broadcast()), + PacketType::Raw, + &[0u8; 900], + ); + assert_eq!( + res, + Err(M17Error::PacketTooLarge { + provided: 900, + capacity: 822 + }) + ); + } +} diff --git a/m17app/src/error.rs b/m17app/src/error.rs index 36d5ac0..acbf397 100644 --- a/m17app/src/error.rs +++ b/m17app/src/error.rs @@ -1,6 +1,6 @@ use thiserror::Error; -#[derive(Debug, Error)] +#[derive(Debug, Error, PartialEq, Eq, Clone)] pub enum M17Error { #[error("given callsign contains at least one character invalid in M17: {0}")] InvalidCallsignCharacters(char), @@ -16,4 +16,9 @@ pub enum M17Error { #[error("unable to set up RTL-SDR receiver")] RtlSdrInit, + + #[error( + "provided packet payload is too large: provided {provided} bytes, capacity {capacity}" + )] + PacketTooLarge { provided: usize, capacity: usize }, } diff --git a/m17app/src/lib.rs b/m17app/src/lib.rs index 9113515..1881df3 100755 --- a/m17app/src/lib.rs +++ b/m17app/src/lib.rs @@ -10,5 +10,8 @@ pub mod soundcard; pub mod soundmodem; pub mod tnc; +#[cfg(test)] +mod test_util; + // Protocol definitions needed to implement stream and packet adapters or create fully custom LSFs pub use m17core::protocol::{LsfFrame, PacketType, StreamFrame}; diff --git a/m17app/src/test_util.rs b/m17app/src/test_util.rs new file mode 100644 index 0000000..ea654f1 --- /dev/null +++ b/m17app/src/test_util.rs @@ -0,0 +1,36 @@ +use std::io::{Read, Write}; + +use crate::tnc::Tnc; + +#[derive(Clone)] +pub(crate) struct NullTnc; + +impl Tnc for NullTnc { + fn try_clone(&mut self) -> Result { + Ok(self.clone()) + } + + fn start(&mut self) -> Result<(), crate::tnc::TncError> { + Ok(()) + } + + fn close(&mut self) -> Result<(), crate::tnc::TncError> { + Ok(()) + } +} + +impl Write for NullTnc { + fn write(&mut self, _buf: &[u8]) -> std::io::Result { + Ok(0) + } + + fn flush(&mut self) -> std::io::Result<()> { + Ok(()) + } +} + +impl Read for NullTnc { + fn read(&mut self, _buf: &mut [u8]) -> std::io::Result { + Ok(0) + } +} diff --git a/tools/m17rt-txpacket/src/main.rs b/tools/m17rt-txpacket/src/main.rs index 916edf2..3e72e23 100644 --- a/tools/m17rt-txpacket/src/main.rs +++ b/tools/m17rt-txpacket/src/main.rs @@ -20,7 +20,8 @@ fn main() { let link_setup = LinkSetup::new_packet(&source, &destination); let payload = b"Hello, world!"; app.tx() - .transmit_packet(&link_setup, PacketType::Sms, payload); + .transmit_packet(&link_setup, PacketType::Sms, payload) + .unwrap(); std::thread::sleep(std::time::Duration::from_secs(1)); app.close(); -- 2.39.5