From afa9614417b3940cf919d4e91aded52ec0d2c824 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sun, 14 Aug 2022 18:13:54 +0200 Subject: [PATCH 01/10] added better generic error handling --- Cargo.lock | 28 +-- fsrc-core/Cargo.toml | 11 +- fsrc-core/src/any.rs | 8 - fsrc-core/src/error.rs | 2 +- fsrc-core/src/hal/host/udp_server.rs | 27 ++- fsrc-core/src/lib.rs | 3 +- fsrc-core/src/tmtc/ccsds_distrib.rs | 248 ++++++++++++++++++------ fsrc-core/src/tmtc/mod.rs | 17 +- fsrc-core/src/tmtc/pus_distrib.rs | 280 ++++++++++++++++++--------- spacepackets | 2 +- 10 files changed, 433 insertions(+), 193 deletions(-) delete mode 100644 fsrc-core/src/any.rs diff --git a/Cargo.lock b/Cargo.lock index 72eaf32..e63d3e4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -201,6 +201,12 @@ dependencies = [ "syn", ] +[[package]] +name = "downcast-rs" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" + [[package]] name = "embedded-hal" version = "0.2.7" @@ -216,8 +222,9 @@ name = "fsrc-core" version = "0.1.0" dependencies = [ "bus", + "downcast-rs", "num", - "postcard 1.0.1", + "postcard", "serde", "spacepackets", "thiserror", @@ -429,17 +436,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "postcard" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a25c0b0ae06fcffe600ad392aabfa535696c8973f2253d9ac83171924c58a858" -dependencies = [ - "heapless", - "postcard-cobs", - "serde", -] - [[package]] name = "postcard" version = "1.0.1" @@ -451,12 +447,6 @@ dependencies = [ "serde", ] -[[package]] -name = "postcard-cobs" -version = "0.1.5-pre" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c68cb38ed13fd7bc9dd5db8f165b7c8d9c1a315104083a2b10f11354c2af97f" - [[package]] name = "proc-macro2" version = "1.0.39" @@ -598,7 +588,7 @@ dependencies = [ "crc", "delegate", "num", - "postcard 0.7.3", + "postcard", "serde", "zerocopy", ] diff --git a/fsrc-core/Cargo.toml b/fsrc-core/Cargo.toml index 0e4d010..28a7c2a 100644 --- a/fsrc-core/Cargo.toml +++ b/fsrc-core/Cargo.toml @@ -9,7 +9,14 @@ edition = "2021" thiserror = "1.0" bus = "2.2.3" num = "0.4" -spacepackets = { path = "../spacepackets"} +downcast-rs = { version = "1.2.0" } + +[dependencies.spacepackets] +path = "../spacepackets" + +#[dependencies.downcast-rs] +#version = "1.2.0" +#default-features = false [dev-dependencies] postcard = { version = "1.0.1", features = ["use-std"] } @@ -18,4 +25,4 @@ zerocopy = "0.6.1" [features] default = ["use_std"] -use_std = [] +use_std = ["downcast-rs/std"] diff --git a/fsrc-core/src/any.rs b/fsrc-core/src/any.rs deleted file mode 100644 index b762bfb..0000000 --- a/fsrc-core/src/any.rs +++ /dev/null @@ -1,8 +0,0 @@ -use std::any::Any; - -/// This trait encapsulates being able to cast a trait object to its original concrete type -/// TODO: Add example code and maybe write derive macro because this code is always the same -pub trait AsAny { - fn as_any(&self) -> &dyn Any; - fn as_mut_any(&mut self) -> &mut dyn Any; -} diff --git a/fsrc-core/src/error.rs b/fsrc-core/src/error.rs index 3176e71..2144839 100644 --- a/fsrc-core/src/error.rs +++ b/fsrc-core/src/error.rs @@ -35,7 +35,7 @@ impl FsrcErrorRaw { } } -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Default)] pub struct SimpleStdErrorHandler {} #[cfg(feature = "use_std")] diff --git a/fsrc-core/src/hal/host/udp_server.rs b/fsrc-core/src/hal/host/udp_server.rs index d4cb29f..53a67c5 100644 --- a/fsrc-core/src/hal/host/udp_server.rs +++ b/fsrc-core/src/hal/host/udp_server.rs @@ -1,18 +1,24 @@ +use crate::hal::host::udp_server::ReceiveResult::{IoError, ReceiverError}; use crate::tmtc::ReceivesTc; use std::net::{SocketAddr, ToSocketAddrs, UdpSocket}; use std::vec::Vec; -pub struct UdpTmtcServer { +pub struct UdpTmtcServer { socket: UdpSocket, recv_buf: Vec, - tc_receiver: Box, + tc_receiver: Box>, } -impl UdpTmtcServer { - pub fn new( +pub enum ReceiveResult { + IoError(std::io::Error), + ReceiverError(E), +} + +impl UdpTmtcServer { + pub fn new( addr: A, max_recv_size: usize, - tc_receiver: Box, + tc_receiver: Box>, ) -> Result { Ok(Self { socket: UdpSocket::bind(addr)?, @@ -21,9 +27,14 @@ impl UdpTmtcServer { }) } - pub fn recv_tc(&mut self) -> Result<(usize, SocketAddr), std::io::Error> { - let res = self.socket.recv_from(&mut self.recv_buf)?; - self.tc_receiver.pass_tc(&self.recv_buf[0..res.0]); + pub fn recv_tc(&mut self) -> Result<(usize, SocketAddr), ReceiveResult> { + let res = self + .socket + .recv_from(&mut self.recv_buf) + .map_err(|e| IoError(e))?; + self.tc_receiver + .pass_tc(&self.recv_buf[0..res.0]) + .map_err(|e| ReceiverError(e))?; Ok(res) } } diff --git a/fsrc-core/src/lib.rs b/fsrc-core/src/lib.rs index a9fd769..232d7b0 100644 --- a/fsrc-core/src/lib.rs +++ b/fsrc-core/src/lib.rs @@ -1,5 +1,4 @@ //! # Core components of the Flight Software Rust Crate (FSRC) collection -pub mod any; pub mod error; pub mod event_man; pub mod events; @@ -8,3 +7,5 @@ pub mod hal; pub mod objects; pub mod pool; pub mod tmtc; + +extern crate downcast_rs; diff --git a/fsrc-core/src/tmtc/ccsds_distrib.rs b/fsrc-core/src/tmtc/ccsds_distrib.rs index d4b2643..4de2545 100644 --- a/fsrc-core/src/tmtc/ccsds_distrib.rs +++ b/fsrc-core/src/tmtc/ccsds_distrib.rs @@ -1,34 +1,138 @@ -use crate::any::AsAny; +//! CCSDS packet routing components. +//! +//! The routing components consist of two core components: +//! 1. [CcsdsDistributor] component which dispatches received packets to a user-provided handler +//! 2. [ApidPacketHandler] trait which should be implemented by the user-provided packet handler. +//! +//! The [CcsdsDistributor] implements the [ReceivesCcsdsTc] and [ReceivesTc] trait which allows to +//! pass raw or CCSDS packets to it. Upon receiving a packet, it performs the following steps: +//! +//! 1. It tries to identify the target Application Process Identifier (APID) based on the +//! respective CCSDS space packet header field. If that process fails, the error +//! will be reported to the provided [FsrcErrorHandler] instance. +//! 2. If a valid APID is found and matches one of the APIDs provided by +//! [ApidPacketHandler::valid_apids], it will pass the packet to the user provided +//! [ApidPacketHandler::handle_known_apid] function. If no valid APID is found, the packet +//! will be passed to the [ApidPacketHandler::handle_unknown_apid] function. +//! +//! # Example +//! +//! ```rust +//! use fsrc_core::error::SimpleStdErrorHandler; +//! use fsrc_core::tmtc::ccsds_distrib::{ApidPacketHandler, CcsdsDistributor}; +//! use fsrc_core::tmtc::ReceivesTc; +//! use spacepackets::{CcsdsPacket, SpHeader}; +//! use spacepackets::tc::PusTc; +//! +//! struct ConcreteApidHandler { +//! custom_field: u32 +//! } +//! +//! impl ApidPacketHandler for ConcreteApidHandler { +//! type Error = (); +//! fn valid_apids(&self) -> &'static [u16] { &[0x002] } +//! fn handle_known_apid(&mut self, sp_header: &SpHeader, tc_raw: &[u8]) -> Result<(), Self::Error> { +//! assert_eq!(sp_header.apid(), 0x002); +//! assert_eq!(tc_raw.len(), 13); +//! Ok(()) +//! } +//! fn handle_unknown_apid(&mut self, sp_header: &SpHeader, tc_raw: &[u8]) -> Result<(), Self::Error> { +//! assert_eq!(sp_header.apid(), 0x003); +//! assert_eq!(tc_raw.len(), 13); +//! Ok(()) +//! } +//! } +//! +//! let apid_handler = ConcreteApidHandler { +//! custom_field: 0x42 +//! }; +//! let err_handler = SimpleStdErrorHandler::default(); +//! let mut ccsds_distributor = CcsdsDistributor::new(Box::new(apid_handler), Box::new(err_handler)); +//! +//! // Create and pass PUS telecommand with a valid APID +//! let mut space_packet_header = SpHeader::tc(0x002, 0x34, 0).unwrap(); +//! let mut pus_tc = PusTc::new_simple(&mut space_packet_header, 17, 1, None, true); +//! let mut test_buf: [u8; 32] = [0; 32]; +//! let mut size = pus_tc +//! .write_to(test_buf.as_mut_slice()) +//! .expect("Error writing TC to buffer"); +//! let tc_slice = &test_buf[0..size]; +//! ccsds_distributor.pass_tc(&tc_slice).expect("Passing TC slice failed"); +//! +//! // Now pass a packet with an unknown APID to the distributor +//! pus_tc.set_apid(0x003); +//! size = pus_tc +//! .write_to(test_buf.as_mut_slice()) +//! .expect("Error writing TC to buffer"); +//! let tc_slice = &test_buf[0..size]; +//! ccsds_distributor.pass_tc(&tc_slice).expect("Passing TC slice failed"); +//! +//! // User helper function to retrieve concrete class +//! let concrete_handler_ref: &ConcreteApidHandler = ccsds_distributor +//! .apid_handler_ref() +//! .expect("Casting back to concrete type failed"); +//! assert_eq!(concrete_handler_ref.custom_field, 0x42); +//! ``` use crate::error::FsrcErrorHandler; -use crate::tmtc::{ReceivesTc, FROM_BYTES_SLICE_TOO_SMALL_ERROR, FROM_BYTES_ZEROCOPY_ERROR}; +use crate::tmtc::{ + ReceivesCcsdsTc, ReceivesTc, FROM_BYTES_SLICE_TOO_SMALL_ERROR, FROM_BYTES_ZEROCOPY_ERROR, +}; +use downcast_rs::Downcast; use spacepackets::{CcsdsPacket, PacketError, SpHeader}; -pub trait ApidPacketHandler: AsAny { +/// Generic trait for a handler or dispatcher object handling CCSDS packets. +/// +/// Users should implement this trait on their custom CCSDS packet handler and then pass a boxed +/// instance of this handler to the [CcsdsDistributor]. The distributor will use the trait +/// interface to dispatch received packets to the user based on the Application Process Identifier +/// (APID) field of the CCSDS packet. +/// +/// This trait automatically implements the [downcast_rs::Downcast] to allow a more convenient API +/// to cast trait objects back to their concrete type after the handler was passed to the +/// distributor. +pub trait ApidPacketHandler: Downcast { + type Error; + fn valid_apids(&self) -> &'static [u16]; - fn handle_known_apid(&mut self, sp_header: &SpHeader, tc_raw: &[u8]); - fn handle_unknown_apid(&mut self, sp_header: &SpHeader, tc_raw: &[u8]); + fn handle_known_apid(&mut self, sp_header: &SpHeader, tc_raw: &[u8]) + -> Result<(), Self::Error>; + fn handle_unknown_apid( + &mut self, + sp_header: &SpHeader, + tc_raw: &[u8], + ) -> Result<(), Self::Error>; } -pub struct CcsdsDistributor { - pub apid_handler: Box, - error_handler: Box, +downcast_rs::impl_downcast!(ApidPacketHandler assoc Error); + +/// The CCSDS distributor dispatches received CCSDS packets to a user provided packet handler. +pub struct CcsdsDistributor { + /// User provided APID handler stored as a generic trait object. + /// It can be cast back to the original concrete type using the [Self::apid_handler_ref] or + /// the [Self::apid_handler_mut] method. + pub apid_handler: Box>, + pub error_handler: Box, } -impl CcsdsDistributor { - pub fn new( - apid_handler: Box, - error_handler: Box, - ) -> Self { - CcsdsDistributor { - apid_handler, - error_handler, - } +#[derive(Debug)] +pub enum CcsdsError { + CustomError(E), + PacketError(PacketError), +} + +impl ReceivesCcsdsTc for CcsdsDistributor { + type Error = CcsdsError; + + fn pass_ccsds(&mut self, header: &SpHeader, tc_raw: &[u8]) -> Result<(), Self::Error> { + self.dispatch_ccsds(header, tc_raw) } } -impl ReceivesTc for CcsdsDistributor { - fn pass_tc(&mut self, tm_raw: &[u8]) { - let sp_header = match SpHeader::from_raw_slice(tm_raw) { +impl ReceivesTc for CcsdsDistributor { + type Error = CcsdsError; + + fn pass_tc(&mut self, tc_raw: &[u8]) -> Result<(), Self::Error> { + let sp_header = match SpHeader::from_raw_slice(tc_raw) { Ok(header) => header, Err(e) => { match e { @@ -46,17 +150,48 @@ impl ReceivesTc for CcsdsDistributor { // TODO: Unexpected error } } - return; + return Err(CcsdsError::PacketError(e)); } }; + self.dispatch_ccsds(&sp_header, tc_raw) + } +} + +impl CcsdsDistributor { + pub fn new( + apid_handler: Box>, + error_handler: Box, + ) -> Self { + CcsdsDistributor { + apid_handler, + error_handler, + } + } + + /// This function can be used to retrieve the concrete instance of the APID handler + /// after it was passed to the distributor. + pub fn apid_handler_ref>(&self) -> Option<&T> { + self.apid_handler.downcast_ref::() + } + + pub fn apid_handler_mut>(&mut self) -> Option<&mut T> { + self.apid_handler.downcast_mut::() + } + + fn dispatch_ccsds(&mut self, sp_header: &SpHeader, tc_raw: &[u8]) -> Result<(), CcsdsError> { let apid = sp_header.apid(); let valid_apids = self.apid_handler.valid_apids(); for &valid_apid in valid_apids { if valid_apid == apid { - return self.apid_handler.handle_known_apid(&sp_header, tm_raw); + return self + .apid_handler + .handle_known_apid(sp_header, tc_raw) + .map_err(|e| CcsdsError::CustomError(e)); } } - self.apid_handler.handle_unknown_apid(&sp_header, tm_raw); + self.apid_handler + .handle_unknown_apid(sp_header, tc_raw) + .map_err(|e| CcsdsError::CustomError(e)) } } @@ -65,9 +200,9 @@ pub(crate) mod tests { use super::*; use crate::error::SimpleStdErrorHandler; use crate::tmtc::ccsds_distrib::{ApidPacketHandler, CcsdsDistributor}; + use crate::tmtc::pus_distrib::PusDistribError; use spacepackets::tc::PusTc; use spacepackets::CcsdsPacket; - use std::any::Any; use std::collections::VecDeque; use std::sync::{Arc, Mutex}; @@ -82,65 +217,66 @@ pub(crate) mod tests { pub unknown_packet_queue: VecDeque<(u16, Vec)>, } - impl AsAny for BasicApidHandlerSharedQueue { - fn as_any(&self) -> &dyn Any { - self - } - - fn as_mut_any(&mut self) -> &mut dyn Any { - self - } - } - impl ApidPacketHandler for BasicApidHandlerSharedQueue { + type Error = (); fn valid_apids(&self) -> &'static [u16] { &[0x000, 0x002] } - fn handle_known_apid(&mut self, sp_header: &SpHeader, tc_raw: &[u8]) { + fn handle_known_apid( + &mut self, + sp_header: &SpHeader, + tc_raw: &[u8], + ) -> Result<(), Self::Error> { let mut vec = Vec::new(); vec.extend_from_slice(tc_raw); - self.known_packet_queue + Ok(self + .known_packet_queue .lock() .unwrap() - .push_back((sp_header.apid(), vec)); + .push_back((sp_header.apid(), vec))) } - fn handle_unknown_apid(&mut self, sp_header: &SpHeader, tc_raw: &[u8]) { + fn handle_unknown_apid( + &mut self, + sp_header: &SpHeader, + tc_raw: &[u8], + ) -> Result<(), Self::Error> { let mut vec = Vec::new(); vec.extend_from_slice(tc_raw); - self.unknown_packet_queue + Ok(self + .unknown_packet_queue .lock() .unwrap() - .push_back((sp_header.apid(), vec)); - } - } - - impl AsAny for BasicApidHandlerOwnedQueue { - fn as_any(&self) -> &dyn Any { - self - } - - fn as_mut_any(&mut self) -> &mut dyn Any { - self + .push_back((sp_header.apid(), vec))) } } impl ApidPacketHandler for BasicApidHandlerOwnedQueue { + type Error = PusDistribError<()>; + fn valid_apids(&self) -> &'static [u16] { &[0x000, 0x002] } - fn handle_known_apid(&mut self, sp_header: &SpHeader, tc_raw: &[u8]) { + fn handle_known_apid( + &mut self, + sp_header: &SpHeader, + tc_raw: &[u8], + ) -> Result<(), Self::Error> { let mut vec = Vec::new(); vec.extend_from_slice(tc_raw); - self.known_packet_queue.push_back((sp_header.apid(), vec)); + Ok(self.known_packet_queue.push_back((sp_header.apid(), vec))) } - fn handle_unknown_apid(&mut self, sp_header: &SpHeader, tc_raw: &[u8]) { + fn handle_unknown_apid( + &mut self, + sp_header: &SpHeader, + tc_raw: &[u8], + ) -> Result<(), Self::Error> { let mut vec = Vec::new(); vec.extend_from_slice(tc_raw); - self.unknown_packet_queue.push_back((sp_header.apid(), vec)); + Ok(self.unknown_packet_queue.push_back((sp_header.apid(), vec))) } } @@ -161,7 +297,7 @@ pub(crate) mod tests { pus_tc .write_to(test_buf.as_mut_slice()) .expect("Error writing TC to buffer"); - ccsds_distrib.pass_tc(&test_buf); + ccsds_distrib.pass_tc(&test_buf).expect("Passing TC failed"); let recvd = known_packet_queue.lock().unwrap().pop_front(); assert!(unknown_packet_queue.lock().unwrap().is_empty()); assert!(recvd.is_some()); @@ -187,7 +323,7 @@ pub(crate) mod tests { pus_tc .write_to(test_buf.as_mut_slice()) .expect("Error writing TC to buffer"); - ccsds_distrib.pass_tc(&test_buf); + ccsds_distrib.pass_tc(&test_buf).expect("Passing TC failed"); let recvd = unknown_packet_queue.lock().unwrap().pop_front(); assert!(known_packet_queue.lock().unwrap().is_empty()); assert!(recvd.is_some()); diff --git a/fsrc-core/src/tmtc/mod.rs b/fsrc-core/src/tmtc/mod.rs index 6a5dc58..54a22b4 100644 --- a/fsrc-core/src/tmtc/mod.rs +++ b/fsrc-core/src/tmtc/mod.rs @@ -1,5 +1,7 @@ +//! TMTC module. Contains packet routing components with special support for CCSDS and ECSS packets. use crate::error::{FsrcErrorRaw, FsrcGroupIds}; -use spacepackets::{PacketError, SpHeader}; +use spacepackets::tc::PusTc; +use spacepackets::SpHeader; pub mod ccsds_distrib; pub mod pus_distrib; @@ -24,9 +26,18 @@ const FROM_BYTES_ZEROCOPY_ERROR: FsrcErrorRaw = FsrcErrorRaw::new( ); pub trait ReceivesTc { - fn pass_tc(&mut self, tc_raw: &[u8]); + type Error; + // TODO: Maybe it makes sense to return Result<(), Self::Error> here with Error being an associated + // type.. + fn pass_tc(&mut self, tc_raw: &[u8]) -> Result<(), Self::Error>; } pub trait ReceivesCcsdsTc { - fn pass_ccsds(&mut self, header: &SpHeader, tc_raw: &[u8]) -> Result<(), PacketError>; + type Error; + fn pass_ccsds(&mut self, header: &SpHeader, tc_raw: &[u8]) -> Result<(), Self::Error>; +} + +pub trait ReceivesEcssPusTc { + type Error; + fn pass_pus_tc(&mut self, header: &SpHeader, pus_tc: &PusTc) -> Result<(), Self::Error>; } diff --git a/fsrc-core/src/tmtc/pus_distrib.rs b/fsrc-core/src/tmtc/pus_distrib.rs index 59856f5..e5256f8 100644 --- a/fsrc-core/src/tmtc/pus_distrib.rs +++ b/fsrc-core/src/tmtc/pus_distrib.rs @@ -1,54 +1,101 @@ -use crate::any::AsAny; +//! ECSS PUS packet routing components. +//! +//! The routing components consist of two core components: +//! 1. [PusDistributor] component which dispatches received packets to a user-provided handler. +//! 2. [PusServiceProvider] trait which should be implemented by the user-provided PUS packet +//! handler. +//! +//! The [PusDistributor] implements the [ReceivesCcsdsTc] and [ReceivesTc] trait which allows to +//! pass raw or CCSDS packets to it. Upon receiving a packet, it performs the following steps: +//! +//! 1. It tries to identify the target Application Process Identifier (APID) based on the +//! respective CCSDS space packet header field. If that process fails, the error +//! will be reported to the provided [FsrcErrorHandler] instance. +//! 2. If a valid APID is found and matches one of the APIDs provided by +//! [ApidPacketHandler::valid_apids], it will pass the packet to the user provided +//! [ApidPacketHandler::handle_known_apid] function. If no valid APID is found, the packet +//! will be passed to the [ApidPacketHandler::handle_unknown_apid] function. use crate::error::FsrcErrorHandler; -use crate::tmtc::{ReceivesCcsdsTc, ReceivesTc}; +use crate::tmtc::{ReceivesCcsdsTc, ReceivesEcssPusTc, ReceivesTc}; +use downcast_rs::Downcast; use spacepackets::ecss::{PusError, PusPacket}; use spacepackets::tc::PusTc; -use spacepackets::{CcsdsPacket, PacketError, SpHeader}; +use spacepackets::{PacketError, SpHeader}; -pub trait PusServiceProvider: AsAny { - fn handle_pus_tc_packet(&mut self, service: u8, apid: u16, pus_tc: &PusTc); +pub trait PusServiceProvider: Downcast { + type Error; + fn handle_pus_tc_packet( + &mut self, + service: u8, + header: &SpHeader, + pus_tc: &PusTc, + ) -> Result<(), Self::Error>; +} +downcast_rs::impl_downcast!(PusServiceProvider assoc Error); + +pub struct PusDistributor { + pub service_provider: Box>, + pub error_handler: Box, } -pub struct PusDistributor { - pub service_provider: Box, - error_handler: Box, +pub enum PusDistribError { + CustomError(E), + PusError(PusError), } -impl ReceivesTc for PusDistributor { - fn pass_tc(&mut self, tm_raw: &[u8]) { +impl ReceivesTc for PusDistributor { + type Error = PusDistribError; + fn pass_tc(&mut self, tm_raw: &[u8]) -> Result<(), Self::Error> { // Convert to ccsds and call pass_ccsds match SpHeader::from_raw_slice(tm_raw) { - Ok(sp_header) => { - self.pass_ccsds(&sp_header, tm_raw).unwrap(); - } + Ok(sp_header) => self.pass_ccsds(&sp_header, tm_raw), Err(error) => { // TODO: Error handling + match error { + PacketError::ToBytesSliceTooSmall(_) => { + //self.error_handler.error() + } + PacketError::FromBytesSliceTooSmall(_) => {} + PacketError::ToBytesZeroCopyError => {} + PacketError::FromBytesZeroCopyError => {} + } + Err(PusDistribError::PusError(PusError::PacketError(error))) } } } } -impl ReceivesCcsdsTc for PusDistributor { - fn pass_ccsds(&mut self, _header: &SpHeader, tm_raw: &[u8]) -> Result<(), PacketError> { +impl ReceivesCcsdsTc for PusDistributor { + type Error = PusDistribError; + fn pass_ccsds(&mut self, header: &SpHeader, tm_raw: &[u8]) -> Result<(), Self::Error> { // TODO: Better error handling let (tc, _) = match PusTc::new_from_raw_slice(tm_raw) { Ok(tuple) => tuple, - Err(e) => { - match e { - PusError::VersionNotSupported(_) => {} - PusError::IncorrectCrc(_) => {} - PusError::RawDataTooShort(_) => {} - PusError::NoRawData => {} - PusError::CrcCalculationMissing => {} - PusError::PacketError(_) => {} - } - return Ok(()); - } + Err(e) => return Err(PusDistribError::PusError(e)), }; self.service_provider - .handle_pus_tc_packet(tc.service(), tc.apid(), &tc); - Ok(()) + .handle_pus_tc_packet(tc.service(), header, &tc) + .map_err(|e| PusDistribError::CustomError(e)) + } +} + +impl ReceivesEcssPusTc for PusDistributor { + type Error = PusDistribError; + fn pass_pus_tc(&mut self, header: &SpHeader, pus_tc: &PusTc) -> Result<(), Self::Error> { + self.service_provider + .handle_pus_tc_packet(pus_tc.service(), header, pus_tc) + .map_err(|e| PusDistribError::CustomError(e)) + } +} + +impl PusDistributor { + pub fn service_provider_ref>(&self) -> Option<&T> { + self.service_provider.downcast_ref::() + } + + pub fn service_provider_mut>(&mut self) -> Option<&mut T> { + self.service_provider.downcast_mut::() } } @@ -61,7 +108,7 @@ mod tests { }; use crate::tmtc::ccsds_distrib::{ApidPacketHandler, CcsdsDistributor}; use spacepackets::tc::PusTc; - use std::any::Any; + use spacepackets::CcsdsPacket; use std::collections::VecDeque; use std::sync::{Arc, Mutex}; @@ -74,104 +121,149 @@ mod tests { pub pus_queue: VecDeque<(u8, u16, Vec)>, } - impl AsAny for PusHandlerSharedQueue { - fn as_any(&self) -> &dyn Any { - self - } - - fn as_mut_any(&mut self) -> &mut dyn Any { - self - } - } - impl PusServiceProvider for PusHandlerSharedQueue { - fn handle_pus_tc_packet(&mut self, service: u8, apid: u16, pus_tc: &PusTc) { + type Error = PusError; + fn handle_pus_tc_packet( + &mut self, + service: u8, + sp_header: &SpHeader, + pus_tc: &PusTc, + ) -> Result<(), Self::Error> { let mut vec: Vec = Vec::new(); - pus_tc - .append_to_vec(&mut vec) - .expect("Appending raw PUS TC to vector failed"); - self.pus_queue + pus_tc.append_to_vec(&mut vec)?; + Ok(self + .pus_queue .lock() .unwrap() - .push_back((service, apid, vec)); - } - } - - impl AsAny for PusHandlerOwnedQueue { - fn as_any(&self) -> &dyn Any { - self - } - - fn as_mut_any(&mut self) -> &mut dyn Any { - self + .push_back((service, sp_header.apid(), vec))) } } impl PusServiceProvider for PusHandlerOwnedQueue { - fn handle_pus_tc_packet(&mut self, service: u8, apid: u16, pus_tc: &PusTc) { + type Error = PusError; + fn handle_pus_tc_packet( + &mut self, + service: u8, + sp_header: &SpHeader, + pus_tc: &PusTc, + ) -> Result<(), Self::Error> { let mut vec: Vec = Vec::new(); - pus_tc - .append_to_vec(&mut vec) - .expect("Appending raw PUS TC to vector failed"); - self.pus_queue.push_back((service, apid, vec)); + pus_tc.append_to_vec(&mut vec)?; + Ok(self.pus_queue.push_back((service, sp_header.apid(), vec))) } } struct ApidHandlerShared { - pub pus_distrib: PusDistributor, + pub pus_distrib: PusDistributor, handler_base: BasicApidHandlerSharedQueue, } - impl AsAny for ApidHandlerShared { - fn as_any(&self) -> &dyn Any { - self - } - - fn as_mut_any(&mut self) -> &mut dyn Any { - self - } - } - macro_rules! apid_handler_impl { () => { + type Error = PusError; + fn valid_apids(&self) -> &'static [u16] { &[0x000, 0x002] } - fn handle_known_apid(&mut self, sp_header: &SpHeader, tc_raw: &[u8]) { + fn handle_known_apid( + &mut self, + sp_header: &SpHeader, + tc_raw: &[u8], + ) -> Result<(), Self::Error> { self.handler_base.handle_known_apid(&sp_header, tc_raw); self.pus_distrib .pass_ccsds(&sp_header, tc_raw) .expect("Passing PUS packet failed"); } - fn handle_unknown_apid(&mut self, sp_header: &SpHeader, tc_raw: &[u8]) { + fn handle_unknown_apid( + &mut self, + sp_header: &SpHeader, + tc_raw: &[u8], + ) -> Result<(), Self::Error> { self.handler_base.handle_unknown_apid(&sp_header, tc_raw); } }; } - impl ApidPacketHandler for ApidHandlerShared { - apid_handler_impl!(); - } - struct ApidHandlerOwned { - pub pus_distrib: PusDistributor, + pub pus_distrib: PusDistributor, handler_base: BasicApidHandlerOwnedQueue, } - impl AsAny for ApidHandlerOwned { - fn as_any(&self) -> &dyn Any { - self + impl ApidPacketHandler for ApidHandlerOwned { + //apid_handler_impl!(); + type Error = PusError; + + fn valid_apids(&self) -> &'static [u16] { + &[0x000, 0x002] } - fn as_mut_any(&mut self) -> &mut dyn Any { - self + fn handle_known_apid( + &mut self, + sp_header: &SpHeader, + tc_raw: &[u8], + ) -> Result<(), Self::Error> { + self.handler_base.handle_known_apid(&sp_header, tc_raw).ok(); + match self.pus_distrib.pass_ccsds(&sp_header, tc_raw) { + Ok(_) => Ok(()), + Err(e) => match e { + PusDistribError::CustomError(_) => Ok(()), + PusDistribError::PusError(e) => Err(e), + }, + } + } + + fn handle_unknown_apid( + &mut self, + sp_header: &SpHeader, + tc_raw: &[u8], + ) -> Result<(), Self::Error> { + match self.handler_base.handle_unknown_apid(&sp_header, tc_raw) { + Ok(_) => Ok(()), + Err(e) => match e { + PusDistribError::CustomError(_) => Ok(()), + PusDistribError::PusError(e) => Err(e), + }, + } } } - impl ApidPacketHandler for ApidHandlerOwned { - apid_handler_impl!(); + impl ApidPacketHandler for ApidHandlerShared { + //apid_handler_impl!(); + type Error = PusError; + + fn valid_apids(&self) -> &'static [u16] { + &[0x000, 0x002] + } + + fn handle_known_apid( + &mut self, + sp_header: &SpHeader, + tc_raw: &[u8], + ) -> Result<(), Self::Error> { + self.handler_base.handle_known_apid(&sp_header, tc_raw).ok(); + match self.pus_distrib.pass_ccsds(&sp_header, tc_raw) { + Ok(_) => Ok(()), + Err(e) => match e { + PusDistribError::CustomError(_) => Ok(()), + PusDistribError::PusError(e) => Err(e), + }, + } + } + + fn handle_unknown_apid( + &mut self, + sp_header: &SpHeader, + tc_raw: &[u8], + ) -> Result<(), Self::Error> { + Ok(self + .handler_base + .handle_unknown_apid(&sp_header, tc_raw) + .ok() + .unwrap()) + } } #[test] @@ -207,7 +299,9 @@ mod tests { .write_to(test_buf.as_mut_slice()) .expect("Error writing TC to buffer"); let tc_slice = &test_buf[0..size]; - ccsds_distrib.pass_tc(tc_slice); + ccsds_distrib + .pass_tc(tc_slice) + .expect("Passing TC slice failed"); let recvd_ccsds = known_packet_queue.lock().unwrap().pop_front(); assert!(unknown_packet_queue.lock().unwrap().is_empty()); assert!(recvd_ccsds.is_some()); @@ -246,12 +340,12 @@ mod tests { .write_to(test_buf.as_mut_slice()) .expect("Error writing TC to buffer"); let tc_slice = &test_buf[0..size]; - ccsds_distrib.pass_tc(tc_slice); + ccsds_distrib + .pass_tc(tc_slice) + .expect("Passing TC slice failed"); let apid_handler_casted_back: &mut ApidHandlerOwned = ccsds_distrib - .apid_handler - .as_mut_any() - .downcast_mut::() + .apid_handler_mut() .expect("Cast to concrete type ApidHandler failed"); assert!(!apid_handler_casted_back .handler_base @@ -259,10 +353,8 @@ mod tests { .is_empty()); let handler_casted_back: &mut PusHandlerOwnedQueue = apid_handler_casted_back .pus_distrib - .service_provider - .as_mut_any() - .downcast_mut::() - .expect("Cast to concrete type PusHandler failed"); + .service_provider_mut() + .expect("Cast to concrete type PusHandlerOwnedQueue failed"); assert!(!handler_casted_back.pus_queue.is_empty()); let (service, apid, packet_raw) = handler_casted_back.pus_queue.pop_front().unwrap(); assert_eq!(service, 17); diff --git a/spacepackets b/spacepackets index fde3fe9..1969f1b 160000 --- a/spacepackets +++ b/spacepackets @@ -1 +1 @@ -Subproject commit fde3fe9cba62b816e004a174821b2d4760003d23 +Subproject commit 1969f1bfa0ebb8327d155e5e44d5a1a2d88b955c -- 2.43.0 From e227d4f4aaf449e7b5087d329c0aa6e076da1393 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sun, 14 Aug 2022 18:47:01 +0200 Subject: [PATCH 02/10] that was complicated --- fsrc-core/src/tmtc/ccsds_distrib.rs | 5 +- fsrc-core/src/tmtc/pus_distrib.rs | 107 +++++++--------------------- 2 files changed, 29 insertions(+), 83 deletions(-) diff --git a/fsrc-core/src/tmtc/ccsds_distrib.rs b/fsrc-core/src/tmtc/ccsds_distrib.rs index 4de2545..80f7669 100644 --- a/fsrc-core/src/tmtc/ccsds_distrib.rs +++ b/fsrc-core/src/tmtc/ccsds_distrib.rs @@ -114,7 +114,7 @@ pub struct CcsdsDistributor { pub error_handler: Box, } -#[derive(Debug)] +#[derive(Debug, Copy, Clone, PartialEq)] pub enum CcsdsError { CustomError(E), PacketError(PacketError), @@ -200,7 +200,6 @@ pub(crate) mod tests { use super::*; use crate::error::SimpleStdErrorHandler; use crate::tmtc::ccsds_distrib::{ApidPacketHandler, CcsdsDistributor}; - use crate::tmtc::pus_distrib::PusDistribError; use spacepackets::tc::PusTc; use spacepackets::CcsdsPacket; use std::collections::VecDeque; @@ -253,7 +252,7 @@ pub(crate) mod tests { } impl ApidPacketHandler for BasicApidHandlerOwnedQueue { - type Error = PusDistribError<()>; + type Error = (); fn valid_apids(&self) -> &'static [u16] { &[0x000, 0x002] diff --git a/fsrc-core/src/tmtc/pus_distrib.rs b/fsrc-core/src/tmtc/pus_distrib.rs index e5256f8..5cd4c6a 100644 --- a/fsrc-core/src/tmtc/pus_distrib.rs +++ b/fsrc-core/src/tmtc/pus_distrib.rs @@ -38,6 +38,7 @@ pub struct PusDistributor { pub error_handler: Box, } +#[derive(Debug, Copy, Clone, PartialEq)] pub enum PusDistribError { CustomError(E), PusError(PusError), @@ -107,6 +108,7 @@ mod tests { BasicApidHandlerOwnedQueue, BasicApidHandlerSharedQueue, }; use crate::tmtc::ccsds_distrib::{ApidPacketHandler, CcsdsDistributor}; + use spacepackets::ecss::PusError; use spacepackets::tc::PusTc; use spacepackets::CcsdsPacket; use std::collections::VecDeque; @@ -134,7 +136,7 @@ mod tests { Ok(self .pus_queue .lock() - .unwrap() + .expect("Mutex lock failed") .push_back((service, sp_header.apid(), vec))) } } @@ -155,7 +157,12 @@ mod tests { struct ApidHandlerShared { pub pus_distrib: PusDistributor, - handler_base: BasicApidHandlerSharedQueue, + pub handler_base: BasicApidHandlerSharedQueue, + } + + struct ApidHandlerOwned { + pub pus_distrib: PusDistributor, + handler_base: BasicApidHandlerOwnedQueue, } macro_rules! apid_handler_impl { @@ -171,10 +178,17 @@ mod tests { sp_header: &SpHeader, tc_raw: &[u8], ) -> Result<(), Self::Error> { - self.handler_base.handle_known_apid(&sp_header, tc_raw); - self.pus_distrib - .pass_ccsds(&sp_header, tc_raw) - .expect("Passing PUS packet failed"); + self.handler_base + .handle_known_apid(&sp_header, tc_raw) + .ok() + .expect("Unexpected error"); + match self.pus_distrib.pass_ccsds(&sp_header, tc_raw) { + Ok(_) => Ok(()), + Err(e) => match e { + PusDistribError::CustomError(_) => Ok(()), + PusDistribError::PusError(e) => Err(e), + }, + } } fn handle_unknown_apid( @@ -182,88 +196,21 @@ mod tests { sp_header: &SpHeader, tc_raw: &[u8], ) -> Result<(), Self::Error> { - self.handler_base.handle_unknown_apid(&sp_header, tc_raw); + self.handler_base + .handle_unknown_apid(&sp_header, tc_raw) + .ok() + .expect("Unexpected error"); + Ok(()) } }; } - struct ApidHandlerOwned { - pub pus_distrib: PusDistributor, - handler_base: BasicApidHandlerOwnedQueue, - } - impl ApidPacketHandler for ApidHandlerOwned { - //apid_handler_impl!(); - type Error = PusError; - - fn valid_apids(&self) -> &'static [u16] { - &[0x000, 0x002] - } - - fn handle_known_apid( - &mut self, - sp_header: &SpHeader, - tc_raw: &[u8], - ) -> Result<(), Self::Error> { - self.handler_base.handle_known_apid(&sp_header, tc_raw).ok(); - match self.pus_distrib.pass_ccsds(&sp_header, tc_raw) { - Ok(_) => Ok(()), - Err(e) => match e { - PusDistribError::CustomError(_) => Ok(()), - PusDistribError::PusError(e) => Err(e), - }, - } - } - - fn handle_unknown_apid( - &mut self, - sp_header: &SpHeader, - tc_raw: &[u8], - ) -> Result<(), Self::Error> { - match self.handler_base.handle_unknown_apid(&sp_header, tc_raw) { - Ok(_) => Ok(()), - Err(e) => match e { - PusDistribError::CustomError(_) => Ok(()), - PusDistribError::PusError(e) => Err(e), - }, - } - } + apid_handler_impl!(); } impl ApidPacketHandler for ApidHandlerShared { - //apid_handler_impl!(); - type Error = PusError; - - fn valid_apids(&self) -> &'static [u16] { - &[0x000, 0x002] - } - - fn handle_known_apid( - &mut self, - sp_header: &SpHeader, - tc_raw: &[u8], - ) -> Result<(), Self::Error> { - self.handler_base.handle_known_apid(&sp_header, tc_raw).ok(); - match self.pus_distrib.pass_ccsds(&sp_header, tc_raw) { - Ok(_) => Ok(()), - Err(e) => match e { - PusDistribError::CustomError(_) => Ok(()), - PusDistribError::PusError(e) => Err(e), - }, - } - } - - fn handle_unknown_apid( - &mut self, - sp_header: &SpHeader, - tc_raw: &[u8], - ) -> Result<(), Self::Error> { - Ok(self - .handler_base - .handle_unknown_apid(&sp_header, tc_raw) - .ok() - .unwrap()) - } + apid_handler_impl!(); } #[test] -- 2.43.0 From c62554fc1cc3dff952c8baa9b4393d32229c8854 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sun, 14 Aug 2022 19:02:50 +0200 Subject: [PATCH 03/10] reduce duplicate code --- fsrc-core/src/tmtc/ccsds_distrib.rs | 19 +++++---- fsrc-core/src/tmtc/pus_distrib.rs | 61 ++++++++--------------------- 2 files changed, 28 insertions(+), 52 deletions(-) diff --git a/fsrc-core/src/tmtc/ccsds_distrib.rs b/fsrc-core/src/tmtc/ccsds_distrib.rs index 80f7669..2e5ad9c 100644 --- a/fsrc-core/src/tmtc/ccsds_distrib.rs +++ b/fsrc-core/src/tmtc/ccsds_distrib.rs @@ -205,6 +205,14 @@ pub(crate) mod tests { use std::collections::VecDeque; use std::sync::{Arc, Mutex}; + pub fn generate_ping_tc(buf: &mut [u8]) -> &[u8] { + let mut sph = SpHeader::tc(0x002, 0x34, 0).unwrap(); + let pus_tc = PusTc::new_simple(&mut sph, 17, 1, None, true); + let size = pus_tc.write_to(buf).expect("Error writing TC to buffer"); + assert_eq!(size, 13); + &buf[0..size] + } + pub struct BasicApidHandlerSharedQueue { pub known_packet_queue: Arc)>>>, pub unknown_packet_queue: Arc)>>>, @@ -290,19 +298,16 @@ pub(crate) mod tests { let error_handler = SimpleStdErrorHandler {}; let mut ccsds_distrib = CcsdsDistributor::new(Box::new(apid_handler), Box::new(error_handler)); - let mut sph = SpHeader::tc(0x002, 0x34, 0).unwrap(); - let pus_tc = PusTc::new_simple(&mut sph, 17, 1, None, true); let mut test_buf: [u8; 32] = [0; 32]; - pus_tc - .write_to(test_buf.as_mut_slice()) - .expect("Error writing TC to buffer"); - ccsds_distrib.pass_tc(&test_buf).expect("Passing TC failed"); + let tc_slice = generate_ping_tc(test_buf.as_mut_slice()); + + ccsds_distrib.pass_tc(tc_slice).expect("Passing TC failed"); let recvd = known_packet_queue.lock().unwrap().pop_front(); assert!(unknown_packet_queue.lock().unwrap().is_empty()); assert!(recvd.is_some()); let (apid, packet) = recvd.unwrap(); assert_eq!(apid, 0x002); - assert_eq!(packet.as_slice(), test_buf); + assert_eq!(packet, tc_slice); } #[test] diff --git a/fsrc-core/src/tmtc/pus_distrib.rs b/fsrc-core/src/tmtc/pus_distrib.rs index 5cd4c6a..04ad415 100644 --- a/fsrc-core/src/tmtc/pus_distrib.rs +++ b/fsrc-core/src/tmtc/pus_distrib.rs @@ -5,8 +5,9 @@ //! 2. [PusServiceProvider] trait which should be implemented by the user-provided PUS packet //! handler. //! -//! The [PusDistributor] implements the [ReceivesCcsdsTc] and [ReceivesTc] trait which allows to -//! pass raw or CCSDS packets to it. Upon receiving a packet, it performs the following steps: +//! The [PusDistributor] implements the [ReceivesEcssPusTc], [ReceivesCcsdsTc] and the [ReceivesTc] +//! trait which allows to pass raw packets, CCSDS packets and PUS TC packets into it. +//! Upon receiving a packet, it performs the following steps: //! //! 1. It tries to identify the target Application Process Identifier (APID) based on the //! respective CCSDS space packet header field. If that process fails, the error @@ -15,12 +16,11 @@ //! [ApidPacketHandler::valid_apids], it will pass the packet to the user provided //! [ApidPacketHandler::handle_known_apid] function. If no valid APID is found, the packet //! will be passed to the [ApidPacketHandler::handle_unknown_apid] function. -use crate::error::FsrcErrorHandler; use crate::tmtc::{ReceivesCcsdsTc, ReceivesEcssPusTc, ReceivesTc}; use downcast_rs::Downcast; use spacepackets::ecss::{PusError, PusPacket}; use spacepackets::tc::PusTc; -use spacepackets::{PacketError, SpHeader}; +use spacepackets::SpHeader; pub trait PusServiceProvider: Downcast { type Error; @@ -35,7 +35,6 @@ downcast_rs::impl_downcast!(PusServiceProvider assoc Error); pub struct PusDistributor { pub service_provider: Box>, - pub error_handler: Box, } #[derive(Debug, Copy, Clone, PartialEq)] @@ -48,36 +47,18 @@ impl ReceivesTc for PusDistributor { type Error = PusDistribError; fn pass_tc(&mut self, tm_raw: &[u8]) -> Result<(), Self::Error> { // Convert to ccsds and call pass_ccsds - match SpHeader::from_raw_slice(tm_raw) { - Ok(sp_header) => self.pass_ccsds(&sp_header, tm_raw), - Err(error) => { - // TODO: Error handling - match error { - PacketError::ToBytesSliceTooSmall(_) => { - //self.error_handler.error() - } - PacketError::FromBytesSliceTooSmall(_) => {} - PacketError::ToBytesZeroCopyError => {} - PacketError::FromBytesZeroCopyError => {} - } - Err(PusDistribError::PusError(PusError::PacketError(error))) - } - } + let sp_header = SpHeader::from_raw_slice(tm_raw) + .map_err(|e| PusDistribError::PusError(PusError::PacketError(e)))?; + self.pass_ccsds(&sp_header, tm_raw) } } impl ReceivesCcsdsTc for PusDistributor { type Error = PusDistribError; fn pass_ccsds(&mut self, header: &SpHeader, tm_raw: &[u8]) -> Result<(), Self::Error> { - // TODO: Better error handling - let (tc, _) = match PusTc::new_from_raw_slice(tm_raw) { - Ok(tuple) => tuple, - Err(e) => return Err(PusDistribError::PusError(e)), - }; - - self.service_provider - .handle_pus_tc_packet(tc.service(), header, &tc) - .map_err(|e| PusDistribError::CustomError(e)) + let (tc, _) = + PusTc::new_from_raw_slice(tm_raw).map_err(|e| PusDistribError::PusError(e))?; + self.pass_pus_tc(header, &tc) } } @@ -105,7 +86,7 @@ mod tests { use super::*; use crate::error::SimpleStdErrorHandler; use crate::tmtc::ccsds_distrib::tests::{ - BasicApidHandlerOwnedQueue, BasicApidHandlerSharedQueue, + generate_ping_tc, BasicApidHandlerOwnedQueue, BasicApidHandlerSharedQueue, }; use crate::tmtc::ccsds_distrib::{ApidPacketHandler, CcsdsDistributor}; use spacepackets::ecss::PusError; @@ -229,23 +210,18 @@ mod tests { let error_handler = SimpleStdErrorHandler {}; let pus_distrib = PusDistributor { service_provider: Box::new(pus_handler), - error_handler: Box::new(error_handler), }; let apid_handler = ApidHandlerShared { pus_distrib, handler_base, }; - let mut ccsds_distrib = CcsdsDistributor::new(Box::new(apid_handler), Box::new(error_handler)); - let mut sph = SpHeader::tc(0x002, 0x34, 0).unwrap(); - let pus_tc = PusTc::new_simple(&mut sph, 17, 1, None, true); let mut test_buf: [u8; 32] = [0; 32]; - let size = pus_tc - .write_to(test_buf.as_mut_slice()) - .expect("Error writing TC to buffer"); - let tc_slice = &test_buf[0..size]; + let tc_slice = generate_ping_tc(test_buf.as_mut_slice()); + + // Pass packet to distributor ccsds_distrib .pass_tc(tc_slice) .expect("Passing TC slice failed"); @@ -270,7 +246,6 @@ mod tests { let error_handler = SimpleStdErrorHandler {}; let pus_distrib = PusDistributor { service_provider: Box::new(pus_handler), - error_handler: Box::new(error_handler), }; let apid_handler = ApidHandlerOwned { @@ -280,13 +255,9 @@ mod tests { let mut ccsds_distrib = CcsdsDistributor::new(Box::new(apid_handler), Box::new(error_handler)); - let mut sph = SpHeader::tc(0x002, 0x34, 0).unwrap(); - let pus_tc = PusTc::new_simple(&mut sph, 17, 1, None, true); let mut test_buf: [u8; 32] = [0; 32]; - let size = pus_tc - .write_to(test_buf.as_mut_slice()) - .expect("Error writing TC to buffer"); - let tc_slice = &test_buf[0..size]; + let tc_slice = generate_ping_tc(test_buf.as_mut_slice()); + ccsds_distrib .pass_tc(tc_slice) .expect("Passing TC slice failed"); -- 2.43.0 From 44d1c6cf97eaa04ced1f771afdb3a69dcf198be9 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sun, 14 Aug 2022 19:17:49 +0200 Subject: [PATCH 04/10] provided PUS example --- fsrc-core/src/tmtc/pus_distrib.rs | 63 +++++++++++++++++++++++++++---- 1 file changed, 56 insertions(+), 7 deletions(-) diff --git a/fsrc-core/src/tmtc/pus_distrib.rs b/fsrc-core/src/tmtc/pus_distrib.rs index 04ad415..6f15698 100644 --- a/fsrc-core/src/tmtc/pus_distrib.rs +++ b/fsrc-core/src/tmtc/pus_distrib.rs @@ -9,13 +9,54 @@ //! trait which allows to pass raw packets, CCSDS packets and PUS TC packets into it. //! Upon receiving a packet, it performs the following steps: //! -//! 1. It tries to identify the target Application Process Identifier (APID) based on the -//! respective CCSDS space packet header field. If that process fails, the error -//! will be reported to the provided [FsrcErrorHandler] instance. -//! 2. If a valid APID is found and matches one of the APIDs provided by -//! [ApidPacketHandler::valid_apids], it will pass the packet to the user provided -//! [ApidPacketHandler::handle_known_apid] function. If no valid APID is found, the packet -//! will be passed to the [ApidPacketHandler::handle_unknown_apid] function. +//! 1. It tries to extract the [SpHeader] and [PusTc] objects from the raw bytestream. If this +//! process fails, a [PusDistribError::PusError] is returned to the user. +//! 2. If it was possible to extract both components, the packet will be passed to the +//! [PusServiceProvider::handle_pus_tc_packet] method provided by the user. +//! +//! # Example +//! +//! ```rust +//! use fsrc_core::tmtc::pus_distrib::{PusDistributor, PusServiceProvider}; +//! use fsrc_core::tmtc::ReceivesTc; +//! use spacepackets::SpHeader; +//! use spacepackets::tc::PusTc; +//! struct ConcretePusHandler { +//! handler_call_count: u32 +//! } +//! +//! impl PusServiceProvider for ConcretePusHandler { +//! type Error = (); +//! fn handle_pus_tc_packet(&mut self, service: u8, header: &SpHeader, pus_tc: &PusTc) -> Result<(), Self::Error> { +//! assert_eq!(service, 17); +//! assert_eq!(pus_tc.len_packed(), 13); +//! self.handler_call_count += 1; +//! Ok(()) +//! } +//! } +//! +//! let service_handler = ConcretePusHandler { +//! handler_call_count: 0 +//! }; +//! let mut pus_distributor = PusDistributor::new(Box::new(service_handler)); +//! +//! // Create and pass PUS telecommand with a valid APID +//! let mut space_packet_header = SpHeader::tc(0x002, 0x34, 0).unwrap(); +//! let mut pus_tc = PusTc::new_simple(&mut space_packet_header, 17, 1, None, true); +//! let mut test_buf: [u8; 32] = [0; 32]; +//! let mut size = pus_tc +//! .write_to(test_buf.as_mut_slice()) +//! .expect("Error writing TC to buffer"); +//! let tc_slice = &test_buf[0..size]; +//! +//! pus_distributor.pass_tc(tc_slice).expect("Passing PUS telecommand failed"); +//! +//! // User helper function to retrieve concrete class +//! let concrete_handler_ref: &ConcretePusHandler = pus_distributor +//! .service_provider_ref() +//! .expect("Casting back to concrete type failed"); +//! assert_eq!(concrete_handler_ref.handler_call_count, 1); +//! ``` use crate::tmtc::{ReceivesCcsdsTc, ReceivesEcssPusTc, ReceivesTc}; use downcast_rs::Downcast; use spacepackets::ecss::{PusError, PusPacket}; @@ -37,6 +78,14 @@ pub struct PusDistributor { pub service_provider: Box>, } +impl PusDistributor { + pub fn new(service_provider: Box>) -> Self { + PusDistributor { + service_provider + } + } +} + #[derive(Debug, Copy, Clone, PartialEq)] pub enum PusDistribError { CustomError(E), -- 2.43.0 From 287f67a4772d66e0de94da59ab113666b9af7926 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sun, 14 Aug 2022 19:37:34 +0200 Subject: [PATCH 05/10] use Downcast for Object Manager --- fsrc-core/src/objects.rs | 56 ++++++++++++++----------------- fsrc-core/src/tmtc/mod.rs | 20 +++++++++-- fsrc-core/src/tmtc/pus_distrib.rs | 11 +++--- 3 files changed, 49 insertions(+), 38 deletions(-) diff --git a/fsrc-core/src/objects.rs b/fsrc-core/src/objects.rs index 0fe5c44..34fdb90 100644 --- a/fsrc-core/src/objects.rs +++ b/fsrc-core/src/objects.rs @@ -7,7 +7,7 @@ //! //! # Examples //! -//! ``` +//! ```rust //! use std::any::Any; //! use std::error::Error; //! use fsrc_core::objects::{ManagedSystemObject, ObjectId, ObjectManager, SystemObject}; @@ -29,9 +29,6 @@ //! } //! //! impl SystemObject for ExampleSysObj { -//! fn as_any(&self) -> &dyn Any { -//! self -//! } //! //! fn get_object_id(&self) -> &ObjectId { //! &self.id @@ -39,24 +36,23 @@ //! //! fn initialize(&mut self) -> Result<(), Box> { //! self.was_initialized = true; -//! Ok(()) -//! } +//! Ok(()) //! } +//! } //! //! impl ManagedSystemObject for ExampleSysObj {} //! -//! //! let mut obj_manager = ObjectManager::default(); //! let obj_id = ObjectId { id: 0, name: "Example 0"}; //! let example_obj = ExampleSysObj::new(obj_id, 42); //! obj_manager.insert(Box::new(example_obj)); -//! let obj_back_casted: Option<&ExampleSysObj> = obj_manager.get(&obj_id); +//! let obj_back_casted: Option<&ExampleSysObj> = obj_manager.get_ref(&obj_id); //! let example_obj = obj_back_casted.unwrap(); //! assert_eq!(example_obj.id, obj_id); //! assert_eq!(example_obj.dummy, 42); //! ``` -use std::any::Any; +use downcast_rs::Downcast; use std::collections::HashMap; use std::error::Error; @@ -68,13 +64,14 @@ pub struct ObjectId { /// Each object which is stored inside the [object manager][ObjectManager] needs to implemented /// this trait -pub trait SystemObject { - fn as_any(&self) -> &dyn Any; +pub trait SystemObject: Downcast { fn get_object_id(&self) -> &ObjectId; fn initialize(&mut self) -> Result<(), Box>; } +downcast_rs::impl_downcast!(SystemObject); -pub trait ManagedSystemObject: SystemObject + Any + Send {} +pub trait ManagedSystemObject: SystemObject + Send {} +downcast_rs::impl_downcast!(ManagedSystemObject); /// Helper module to manage multiple [ManagedSystemObjects][ManagedSystemObject] by mapping them /// using an [object ID][ObjectId] @@ -114,19 +111,26 @@ impl ObjectManager { Ok(init_success) } - /// Retrieve an object stored inside the manager. The type to retrieve needs to be explicitly - /// passed as a generic parameter - pub fn get(&self, key: &ObjectId) -> Option<&T> { + /// Retrieve a reference to an object stored inside the manager. The type to retrieve needs to + /// be explicitly passed as a generic parameter or specified on the left hand side of the + /// expression. + pub fn get_ref(&self, key: &ObjectId) -> Option<&T> { + self.obj_map.get(key).and_then(|o| o.downcast_ref::()) + } + + /// Retrieve a mutable reference to an object stored inside the manager. The type to retrieve + /// needs to be explicitly passed as a generic parameter or specified on the left hand side + /// of the expression. + pub fn get_mut(&mut self, key: &ObjectId) -> Option<&mut T> { self.obj_map - .get(key) - .and_then(|o| o.as_ref().as_any().downcast_ref::()) + .get_mut(key) + .and_then(|o| o.downcast_mut::()) } } #[cfg(test)] mod tests { use crate::objects::{ManagedSystemObject, ObjectId, ObjectManager, SystemObject}; - use std::any::Any; use std::error::Error; use std::sync::{Arc, Mutex}; use std::thread; @@ -148,10 +152,6 @@ mod tests { } impl SystemObject for ExampleSysObj { - fn as_any(&self) -> &dyn Any { - self - } - fn get_object_id(&self) -> &ObjectId { &self.id } @@ -171,10 +171,6 @@ mod tests { } impl SystemObject for OtherExampleObject { - fn as_any(&self) -> &dyn Any { - self - } - fn get_object_id(&self) -> &ObjectId { &self.id } @@ -199,7 +195,7 @@ mod tests { let res = obj_manager.initialize(); assert!(res.is_ok()); assert_eq!(res.unwrap(), 1); - let obj_back_casted: Option<&ExampleSysObj> = obj_manager.get(&expl_obj_id); + let obj_back_casted: Option<&ExampleSysObj> = obj_manager.get_ref(&expl_obj_id); assert!(obj_back_casted.is_some()); let expl_obj_back_casted = obj_back_casted.unwrap(); assert_eq!(expl_obj_back_casted.dummy, 42); @@ -219,7 +215,7 @@ mod tests { let res = obj_manager.initialize(); assert!(res.is_ok()); assert_eq!(res.unwrap(), 2); - let obj_back_casted: Option<&OtherExampleObject> = obj_manager.get(&second_obj_id); + let obj_back_casted: Option<&OtherExampleObject> = obj_manager.get_ref(&second_obj_id); assert!(obj_back_casted.is_some()); let expl_obj_back_casted = obj_back_casted.unwrap(); assert_eq!(expl_obj_back_casted.string, String::from("Hello Test")); @@ -266,7 +262,7 @@ mod tests { let obj_man_0 = obj_manager.clone(); let jh0 = thread::spawn(move || { let locked_man = obj_man_0.lock().expect("Mutex lock failed"); - let obj_back_casted: Option<&ExampleSysObj> = locked_man.get(&expl_obj_id); + let obj_back_casted: Option<&ExampleSysObj> = locked_man.get_ref(&expl_obj_id); assert!(obj_back_casted.is_some()); let expl_obj_back_casted = obj_back_casted.unwrap(); assert_eq!(expl_obj_back_casted.dummy, 42); @@ -276,7 +272,7 @@ mod tests { let jh1 = thread::spawn(move || { let locked_man = obj_manager.lock().expect("Mutex lock failed"); - let obj_back_casted: Option<&OtherExampleObject> = locked_man.get(&second_obj_id); + let obj_back_casted: Option<&OtherExampleObject> = locked_man.get_ref(&second_obj_id); assert!(obj_back_casted.is_some()); let expl_obj_back_casted = obj_back_casted.unwrap(); assert_eq!(expl_obj_back_casted.string, String::from("Hello Test")); diff --git a/fsrc-core/src/tmtc/mod.rs b/fsrc-core/src/tmtc/mod.rs index 54a22b4..e08853a 100644 --- a/fsrc-core/src/tmtc/mod.rs +++ b/fsrc-core/src/tmtc/mod.rs @@ -1,4 +1,5 @@ -//! TMTC module. Contains packet routing components with special support for CCSDS and ECSS packets. +//! Telemetry and Telecommanding (TMTC) module. Contains packet routing components with special +//! support for CCSDS and ECSS packets. use crate::error::{FsrcErrorRaw, FsrcGroupIds}; use spacepackets::tc::PusTc; use spacepackets::SpHeader; @@ -25,18 +26,31 @@ const FROM_BYTES_ZEROCOPY_ERROR: FsrcErrorRaw = FsrcErrorRaw::new( "FROM_BYTES_ZEROCOPY_ERROR", ); +/// Generic trait for object which can receive any telecommands in form of a raw bytestream, with +/// no assumptions about the received protocol. +/// +/// This trait is implemented by both the [crate::tmtc::pus_distrib::PusDistributor] and the +/// [crate::tmtc::ccsds_distrib::CcsdsDistributor] which allows to pass the respective packets in +/// raw byte format into them. pub trait ReceivesTc { type Error; - // TODO: Maybe it makes sense to return Result<(), Self::Error> here with Error being an associated - // type.. fn pass_tc(&mut self, tc_raw: &[u8]) -> Result<(), Self::Error>; } +/// Generic trait for object which can receive CCSDS space packets, for example ECSS PUS packets +/// for CCSDS File Delivery Protocol (CFDP) packets. +/// +/// This trait is implemented by both the [crate::tmtc::pus_distrib::PusDistributor] and the +/// [crate::tmtc::ccsds_distrib::CcsdsDistributor] which allows +/// to pass the respective packets in raw byte format or in CCSDS format into them. pub trait ReceivesCcsdsTc { type Error; fn pass_ccsds(&mut self, header: &SpHeader, tc_raw: &[u8]) -> Result<(), Self::Error>; } +/// Generic trait for objects which can receive ECSS PUS telecommands. This trait is +/// implemented by the [crate::tmtc::pus_distrib::PusDistributor] objects to allow passing PUS TC +/// packets into it. pub trait ReceivesEcssPusTc { type Error; fn pass_pus_tc(&mut self, header: &SpHeader, pus_tc: &PusTc) -> Result<(), Self::Error>; diff --git a/fsrc-core/src/tmtc/pus_distrib.rs b/fsrc-core/src/tmtc/pus_distrib.rs index 6f15698..34a6c30 100644 --- a/fsrc-core/src/tmtc/pus_distrib.rs +++ b/fsrc-core/src/tmtc/pus_distrib.rs @@ -25,6 +25,8 @@ //! handler_call_count: u32 //! } //! +//! // This is a very simple possible service provider. It increments an internal call count field, +//! // which is used to verify the handler was called //! impl PusServiceProvider for ConcretePusHandler { //! type Error = (); //! fn handle_pus_tc_packet(&mut self, service: u8, header: &SpHeader, pus_tc: &PusTc) -> Result<(), Self::Error> { @@ -40,7 +42,7 @@ //! }; //! let mut pus_distributor = PusDistributor::new(Box::new(service_handler)); //! -//! // Create and pass PUS telecommand with a valid APID +//! // Create and pass PUS ping telecommand with a valid APID //! let mut space_packet_header = SpHeader::tc(0x002, 0x34, 0).unwrap(); //! let mut pus_tc = PusTc::new_simple(&mut space_packet_header, 17, 1, None, true); //! let mut test_buf: [u8; 32] = [0; 32]; @@ -51,7 +53,8 @@ //! //! pus_distributor.pass_tc(tc_slice).expect("Passing PUS telecommand failed"); //! -//! // User helper function to retrieve concrete class +//! // User helper function to retrieve concrete class. We check the call count here to verify +//! // that the PUS ping telecommand was routed successfully. //! let concrete_handler_ref: &ConcretePusHandler = pus_distributor //! .service_provider_ref() //! .expect("Casting back to concrete type failed"); @@ -80,9 +83,7 @@ pub struct PusDistributor { impl PusDistributor { pub fn new(service_provider: Box>) -> Self { - PusDistributor { - service_provider - } + PusDistributor { service_provider } } } -- 2.43.0 From 8418085fb1c60bd06b7e61b65e113da483579a5b Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sun, 14 Aug 2022 19:49:18 +0200 Subject: [PATCH 06/10] remove dependency on error handler --- fsrc-core/src/tmtc/ccsds_distrib.rs | 81 +++++++++++------------------ fsrc-core/src/tmtc/mod.rs | 10 ++-- fsrc-core/src/tmtc/pus_distrib.rs | 9 +--- 3 files changed, 37 insertions(+), 63 deletions(-) diff --git a/fsrc-core/src/tmtc/ccsds_distrib.rs b/fsrc-core/src/tmtc/ccsds_distrib.rs index 2e5ad9c..470cb22 100644 --- a/fsrc-core/src/tmtc/ccsds_distrib.rs +++ b/fsrc-core/src/tmtc/ccsds_distrib.rs @@ -18,14 +18,19 @@ //! # Example //! //! ```rust -//! use fsrc_core::error::SimpleStdErrorHandler; //! use fsrc_core::tmtc::ccsds_distrib::{ApidPacketHandler, CcsdsDistributor}; //! use fsrc_core::tmtc::ReceivesTc; //! use spacepackets::{CcsdsPacket, SpHeader}; //! use spacepackets::tc::PusTc; //! +//! #[derive (Default)] //! struct ConcreteApidHandler { -//! custom_field: u32 +//! known_call_count: u32, +//! unknown_call_count: u32 +//! } +//! +//! impl ConcreteApidHandler { +//! fn mutable_foo(&mut self) {} //! } //! //! impl ApidPacketHandler for ConcreteApidHandler { @@ -34,20 +39,19 @@ //! fn handle_known_apid(&mut self, sp_header: &SpHeader, tc_raw: &[u8]) -> Result<(), Self::Error> { //! assert_eq!(sp_header.apid(), 0x002); //! assert_eq!(tc_raw.len(), 13); +//! self.known_call_count += 1; //! Ok(()) //! } //! fn handle_unknown_apid(&mut self, sp_header: &SpHeader, tc_raw: &[u8]) -> Result<(), Self::Error> { //! assert_eq!(sp_header.apid(), 0x003); //! assert_eq!(tc_raw.len(), 13); +//! self.unknown_call_count += 1; //! Ok(()) //! } //! } //! -//! let apid_handler = ConcreteApidHandler { -//! custom_field: 0x42 -//! }; -//! let err_handler = SimpleStdErrorHandler::default(); -//! let mut ccsds_distributor = CcsdsDistributor::new(Box::new(apid_handler), Box::new(err_handler)); +//! let apid_handler = ConcreteApidHandler::default(); +//! let mut ccsds_distributor = CcsdsDistributor::new(Box::new(apid_handler)); //! //! // Create and pass PUS telecommand with a valid APID //! let mut space_packet_header = SpHeader::tc(0x002, 0x34, 0).unwrap(); @@ -71,12 +75,16 @@ //! let concrete_handler_ref: &ConcreteApidHandler = ccsds_distributor //! .apid_handler_ref() //! .expect("Casting back to concrete type failed"); -//! assert_eq!(concrete_handler_ref.custom_field, 0x42); +//! assert_eq!(concrete_handler_ref.known_call_count, 1); +//! assert_eq!(concrete_handler_ref.unknown_call_count, 1); +//! +//! // It's also possible to retrieve a mutable reference +//! let mutable_ref: &mut ConcreteApidHandler = ccsds_distributor +//! .apid_handler_mut() +//! .expect("Casting back to concrete type failed"); +//! mutable_ref.mutable_foo(); //! ``` -use crate::error::FsrcErrorHandler; -use crate::tmtc::{ - ReceivesCcsdsTc, ReceivesTc, FROM_BYTES_SLICE_TOO_SMALL_ERROR, FROM_BYTES_ZEROCOPY_ERROR, -}; +use crate::tmtc::{ReceivesCcsdsTc, ReceivesTc}; use downcast_rs::Downcast; use spacepackets::{CcsdsPacket, PacketError, SpHeader}; @@ -111,7 +119,6 @@ pub struct CcsdsDistributor { /// It can be cast back to the original concrete type using the [Self::apid_handler_ref] or /// the [Self::apid_handler_mut] method. pub apid_handler: Box>, - pub error_handler: Box, } #[derive(Debug, Copy, Clone, PartialEq)] @@ -132,48 +139,25 @@ impl ReceivesTc for CcsdsDistributor { type Error = CcsdsError; fn pass_tc(&mut self, tc_raw: &[u8]) -> Result<(), Self::Error> { - let sp_header = match SpHeader::from_raw_slice(tc_raw) { - Ok(header) => header, - Err(e) => { - match e { - PacketError::FromBytesSliceTooSmall(missmatch) => { - self.error_handler.error_with_two_params( - FROM_BYTES_SLICE_TOO_SMALL_ERROR, - missmatch.found as u32, - missmatch.expected as u32, - ); - } - PacketError::FromBytesZeroCopyError => { - self.error_handler.error(FROM_BYTES_ZEROCOPY_ERROR); - } - _ => { - // TODO: Unexpected error - } - } - return Err(CcsdsError::PacketError(e)); - } - }; + let sp_header = SpHeader::from_raw_slice(tc_raw).map_err(|e| CcsdsError::PacketError(e))?; self.dispatch_ccsds(&sp_header, tc_raw) } } impl CcsdsDistributor { - pub fn new( - apid_handler: Box>, - error_handler: Box, - ) -> Self { - CcsdsDistributor { - apid_handler, - error_handler, - } + pub fn new(apid_handler: Box>) -> Self { + CcsdsDistributor { apid_handler } } - /// This function can be used to retrieve the concrete instance of the APID handler - /// after it was passed to the distributor. + /// This function can be used to retrieve a reference to the concrete instance of the APID + /// handler after it was passed to the distributor. See the + /// [module documentation][crate::tmtc::ccsds_distrib] for an example. pub fn apid_handler_ref>(&self) -> Option<&T> { self.apid_handler.downcast_ref::() } + /// This function can be used to retrieve a mutable reference to the concrete instance of the + /// APID handler after it was passed to the distributor. pub fn apid_handler_mut>(&mut self) -> Option<&mut T> { self.apid_handler.downcast_mut::() } @@ -198,7 +182,6 @@ impl CcsdsDistributor { #[cfg(test)] pub(crate) mod tests { use super::*; - use crate::error::SimpleStdErrorHandler; use crate::tmtc::ccsds_distrib::{ApidPacketHandler, CcsdsDistributor}; use spacepackets::tc::PusTc; use spacepackets::CcsdsPacket; @@ -295,9 +278,7 @@ pub(crate) mod tests { known_packet_queue: known_packet_queue.clone(), unknown_packet_queue: unknown_packet_queue.clone(), }; - let error_handler = SimpleStdErrorHandler {}; - let mut ccsds_distrib = - CcsdsDistributor::new(Box::new(apid_handler), Box::new(error_handler)); + let mut ccsds_distrib = CcsdsDistributor::new(Box::new(apid_handler)); let mut test_buf: [u8; 32] = [0; 32]; let tc_slice = generate_ping_tc(test_buf.as_mut_slice()); @@ -318,9 +299,7 @@ pub(crate) mod tests { known_packet_queue: known_packet_queue.clone(), unknown_packet_queue: unknown_packet_queue.clone(), }; - let error_handler = SimpleStdErrorHandler {}; - let mut ccsds_distrib = - CcsdsDistributor::new(Box::new(apid_handler), Box::new(error_handler)); + let mut ccsds_distrib = CcsdsDistributor::new(Box::new(apid_handler)); let mut sph = SpHeader::tc(0x004, 0x34, 0).unwrap(); let pus_tc = PusTc::new_simple(&mut sph, 17, 1, None, true); let mut test_buf: [u8; 32] = [0; 32]; diff --git a/fsrc-core/src/tmtc/mod.rs b/fsrc-core/src/tmtc/mod.rs index e08853a..25482b8 100644 --- a/fsrc-core/src/tmtc/mod.rs +++ b/fsrc-core/src/tmtc/mod.rs @@ -7,22 +7,22 @@ use spacepackets::SpHeader; pub mod ccsds_distrib; pub mod pus_distrib; -const RAW_PACKET_ERROR: &str = "raw-tmtc"; +const _RAW_PACKET_ERROR: &str = "raw-tmtc"; const _CCSDS_ERROR: &str = "ccsds-tmtc"; const _PUS_ERROR: &str = "pus-tmtc"; // TODO: A macro for general and unknown errors would be nice -const FROM_BYTES_SLICE_TOO_SMALL_ERROR: FsrcErrorRaw = FsrcErrorRaw::new( +const _FROM_BYTES_SLICE_TOO_SMALL_ERROR: FsrcErrorRaw = FsrcErrorRaw::new( FsrcGroupIds::Tmtc as u8, 0, - RAW_PACKET_ERROR, + _RAW_PACKET_ERROR, "FROM_BYTES_SLICE_TOO_SMALL_ERROR", ); -const FROM_BYTES_ZEROCOPY_ERROR: FsrcErrorRaw = FsrcErrorRaw::new( +const _FROM_BYTES_ZEROCOPY_ERROR: FsrcErrorRaw = FsrcErrorRaw::new( FsrcGroupIds::Tmtc as u8, 1, - RAW_PACKET_ERROR, + _RAW_PACKET_ERROR, "FROM_BYTES_ZEROCOPY_ERROR", ); diff --git a/fsrc-core/src/tmtc/pus_distrib.rs b/fsrc-core/src/tmtc/pus_distrib.rs index 34a6c30..7ace4e3 100644 --- a/fsrc-core/src/tmtc/pus_distrib.rs +++ b/fsrc-core/src/tmtc/pus_distrib.rs @@ -134,7 +134,6 @@ impl PusDistributor { #[cfg(test)] mod tests { use super::*; - use crate::error::SimpleStdErrorHandler; use crate::tmtc::ccsds_distrib::tests::{ generate_ping_tc, BasicApidHandlerOwnedQueue, BasicApidHandlerSharedQueue, }; @@ -257,7 +256,6 @@ mod tests { unknown_packet_queue: unknown_packet_queue.clone(), }; - let error_handler = SimpleStdErrorHandler {}; let pus_distrib = PusDistributor { service_provider: Box::new(pus_handler), }; @@ -266,8 +264,7 @@ mod tests { pus_distrib, handler_base, }; - let mut ccsds_distrib = - CcsdsDistributor::new(Box::new(apid_handler), Box::new(error_handler)); + let mut ccsds_distrib = CcsdsDistributor::new(Box::new(apid_handler)); let mut test_buf: [u8; 32] = [0; 32]; let tc_slice = generate_ping_tc(test_buf.as_mut_slice()); @@ -293,7 +290,6 @@ mod tests { fn test_as_any_cast() { let pus_handler = PusHandlerOwnedQueue::default(); let handler_base = BasicApidHandlerOwnedQueue::default(); - let error_handler = SimpleStdErrorHandler {}; let pus_distrib = PusDistributor { service_provider: Box::new(pus_handler), }; @@ -302,8 +298,7 @@ mod tests { pus_distrib, handler_base, }; - let mut ccsds_distrib = - CcsdsDistributor::new(Box::new(apid_handler), Box::new(error_handler)); + let mut ccsds_distrib = CcsdsDistributor::new(Box::new(apid_handler)); let mut test_buf: [u8; 32] = [0; 32]; let tc_slice = generate_ping_tc(test_buf.as_mut_slice()); -- 2.43.0 From 207fa55bf3d69ca722a11897135bf5022bd2b985 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sun, 14 Aug 2022 19:51:51 +0200 Subject: [PATCH 07/10] disable std by default for downcast --- .idea/runConfigurations/Doctest.xml | 19 +++++++++++++++++++ fsrc-core/Cargo.toml | 7 +++---- 2 files changed, 22 insertions(+), 4 deletions(-) create mode 100644 .idea/runConfigurations/Doctest.xml diff --git a/.idea/runConfigurations/Doctest.xml b/.idea/runConfigurations/Doctest.xml new file mode 100644 index 0000000..73a8b79 --- /dev/null +++ b/.idea/runConfigurations/Doctest.xml @@ -0,0 +1,19 @@ + + + + \ No newline at end of file diff --git a/fsrc-core/Cargo.toml b/fsrc-core/Cargo.toml index 28a7c2a..f3c9cd2 100644 --- a/fsrc-core/Cargo.toml +++ b/fsrc-core/Cargo.toml @@ -9,14 +9,13 @@ edition = "2021" thiserror = "1.0" bus = "2.2.3" num = "0.4" -downcast-rs = { version = "1.2.0" } [dependencies.spacepackets] path = "../spacepackets" -#[dependencies.downcast-rs] -#version = "1.2.0" -#default-features = false +[dependencies.downcast-rs] +version = "1.2.0" +default-features = false [dev-dependencies] postcard = { version = "1.0.1", features = ["use-std"] } -- 2.43.0 From 65cbb1411c2922b76ee566178f2ce211dfa8c5a0 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sun, 14 Aug 2022 20:02:16 +0200 Subject: [PATCH 08/10] update docs --- fsrc-core/src/lib.rs | 8 ++++++++ fsrc-core/src/tmtc/ccsds_distrib.rs | 4 ++-- fsrc-core/src/tmtc/mod.rs | 5 +++++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/fsrc-core/src/lib.rs b/fsrc-core/src/lib.rs index 232d7b0..f9bed14 100644 --- a/fsrc-core/src/lib.rs +++ b/fsrc-core/src/lib.rs @@ -1,4 +1,12 @@ //! # Core components of the Flight Software Rust Crate (FSRC) collection +//! +//! This is a collection of Rust crates which can be used to build On-Board Software for remote +//! systems like satellites of rovers. It has special support for space tailored protocols +//! like the ones provided by CCSDS and ECSS. +//! +//! The crates can generally be used in a `no_std` environment, but some crates expect that the +//! [alloc](https://doc.rust-lang.org/alloc) crate is available to allow boxed trait objects. +//! These are used to supply user code to the crates. pub mod error; pub mod event_man; pub mod events; diff --git a/fsrc-core/src/tmtc/ccsds_distrib.rs b/fsrc-core/src/tmtc/ccsds_distrib.rs index 470cb22..f4b526b 100644 --- a/fsrc-core/src/tmtc/ccsds_distrib.rs +++ b/fsrc-core/src/tmtc/ccsds_distrib.rs @@ -8,8 +8,8 @@ //! pass raw or CCSDS packets to it. Upon receiving a packet, it performs the following steps: //! //! 1. It tries to identify the target Application Process Identifier (APID) based on the -//! respective CCSDS space packet header field. If that process fails, the error -//! will be reported to the provided [FsrcErrorHandler] instance. +//! respective CCSDS space packet header field. If that process fails, a [PacketError] is +//! returned to the user //! 2. If a valid APID is found and matches one of the APIDs provided by //! [ApidPacketHandler::valid_apids], it will pass the packet to the user provided //! [ApidPacketHandler::handle_known_apid] function. If no valid APID is found, the packet diff --git a/fsrc-core/src/tmtc/mod.rs b/fsrc-core/src/tmtc/mod.rs index 25482b8..4b6fe16 100644 --- a/fsrc-core/src/tmtc/mod.rs +++ b/fsrc-core/src/tmtc/mod.rs @@ -1,5 +1,10 @@ //! Telemetry and Telecommanding (TMTC) module. Contains packet routing components with special //! support for CCSDS and ECSS packets. +//! +//! The distributor modules provided by this module use trait objects provided by the user to +//! directly dispatch received packets to packet listeners based on packet fields like the CCSDS +//! Application Process ID (APID) or the ECSS PUS service type. This allows for fast packet +//! routing without the overhead and complication of using message queues. However, it also requires use crate::error::{FsrcErrorRaw, FsrcGroupIds}; use spacepackets::tc::PusTc; use spacepackets::SpHeader; -- 2.43.0 From 1bf8138a9455dd1b0552374195962f6335cc2df6 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 16 Aug 2022 11:15:23 +0200 Subject: [PATCH 09/10] bump spacepackets, clippy fixes --- .idea/runConfigurations/Check.xml | 7 ++++--- .idea/runConfigurations/Clippy.xml | 2 +- .idea/runConfigurations/Test.xml | 3 ++- Cargo.lock | 20 +------------------- fsrc-core/src/events.rs | 4 ++-- fsrc-core/src/executable.rs | 2 +- fsrc-core/src/pool.rs | 6 +++--- fsrc-core/src/tmtc/ccsds_distrib.rs | 2 +- fsrc-core/src/tmtc/pus_distrib.rs | 8 ++++---- spacepackets | 2 +- 10 files changed, 20 insertions(+), 36 deletions(-) diff --git a/.idea/runConfigurations/Check.xml b/.idea/runConfigurations/Check.xml index 7742dee..44c4c7f 100644 --- a/.idea/runConfigurations/Check.xml +++ b/.idea/runConfigurations/Check.xml @@ -1,12 +1,13 @@ -