basic TMTC infastructure for example

This commit is contained in:
2022-08-28 00:28:29 +02:00
parent 86bdf35ca3
commit 6ab691e87c
13 changed files with 179 additions and 39 deletions

View File

@ -1,20 +1,24 @@
use crate::hal::host::udp_server::ReceiveResult::{IoError, ReceiverError};
use crate::tmtc::ReceivesTc;
use std::boxed::Box;
use std::net::{SocketAddr, ToSocketAddrs, UdpSocket};
use std::vec;
use std::vec::Vec;
pub struct UdpTmtcServer<E> {
socket: UdpSocket,
pub struct UdpTcServer<E> {
pub socket: UdpSocket,
recv_buf: Vec<u8>,
sender_addr: Option<SocketAddr>,
tc_receiver: Box<dyn ReceivesTc<Error = E>>,
}
#[derive(Debug)]
pub enum ReceiveResult<E> {
IoError(std::io::Error),
ReceiverError(E),
}
impl<E> UdpTmtcServer<E> {
impl<E> UdpTcServer<E> {
pub fn new<A: ToSocketAddrs>(
addr: A,
max_recv_size: usize,
@ -22,7 +26,8 @@ impl<E> UdpTmtcServer<E> {
) -> Result<Self, std::io::Error> {
Ok(Self {
socket: UdpSocket::bind(addr)?,
recv_buf: Vec::with_capacity(max_recv_size),
recv_buf: vec![0; max_recv_size],
sender_addr: None,
tc_receiver,
})
}
@ -32,6 +37,7 @@ impl<E> UdpTmtcServer<E> {
.socket
.recv_from(&mut self.recv_buf)
.map_err(|e| IoError(e))?;
self.sender_addr = Some(res.1);
self.tc_receiver
.pass_tc(&self.recv_buf[0..res.0])
.map_err(|e| ReceiverError(e))?;

View File

@ -1,2 +1,2 @@
#[cfg(feature = "use_std")]
#[cfg(feature = "std")]
pub mod host;

View File

@ -2,7 +2,7 @@
//!
//! 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.
//! 2. [CcsdsPacketHandler] 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:
@ -11,14 +11,14 @@
//! 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
//! will be passed to the [ApidPacketHandler::handle_unknown_apid] function.
//! [CcsdsPacketHandler::valid_apids], it will pass the packet to the user provided
//! [CcsdsPacketHandler::handle_known_apid] function. If no valid APID is found, the packet
//! will be passed to the [CcsdsPacketHandler::handle_unknown_apid] function.
//!
//! # Example
//!
//! ```rust
//! use fsrc_core::tmtc::ccsds_distrib::{ApidPacketHandler, CcsdsDistributor};
//! use fsrc_core::tmtc::ccsds_distrib::{CcsdsPacketHandler, CcsdsDistributor};
//! use fsrc_core::tmtc::ReceivesTc;
//! use spacepackets::{CcsdsPacket, SpHeader};
//! use spacepackets::tc::PusTc;
@ -33,7 +33,7 @@
//! fn mutable_foo(&mut self) {}
//! }
//!
//! impl ApidPacketHandler for ConcreteApidHandler {
//! impl CcsdsPacketHandler 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> {
@ -86,7 +86,7 @@
//! ```
use crate::tmtc::{ReceivesCcsdsTc, ReceivesTc};
use downcast_rs::Downcast;
use spacepackets::{CcsdsPacket, PacketError, SpHeader};
use spacepackets::{CcsdsPacket, PacketError, SizeMissmatch, SpHeader};
/// Generic trait for a handler or dispatcher object handling CCSDS packets.
///
@ -98,7 +98,7 @@ use spacepackets::{CcsdsPacket, PacketError, SpHeader};
/// 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 {
pub trait CcsdsPacketHandler: Downcast {
type Error;
fn valid_apids(&self) -> &'static [u16];
@ -111,14 +111,14 @@ pub trait ApidPacketHandler: Downcast {
) -> Result<(), Self::Error>;
}
downcast_rs::impl_downcast!(ApidPacketHandler assoc Error);
downcast_rs::impl_downcast!(CcsdsPacketHandler assoc Error);
/// The CCSDS distributor dispatches received CCSDS packets to a user provided packet handler.
pub struct CcsdsDistributor<E> {
/// 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<dyn ApidPacketHandler<Error = E>>,
pub apid_handler: Box<dyn CcsdsPacketHandler<Error = E>>,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
@ -139,26 +139,34 @@ impl<E: 'static> ReceivesTc for CcsdsDistributor<E> {
type Error = CcsdsError<E>;
fn pass_tc(&mut self, tc_raw: &[u8]) -> Result<(), Self::Error> {
if tc_raw.len() < 7 {
return Err(CcsdsError::PacketError(
PacketError::FromBytesSliceTooSmall(SizeMissmatch {
found: tc_raw.len(),
expected: 7,
}),
));
}
let sp_header = SpHeader::from_raw_slice(tc_raw).map_err(|e| CcsdsError::PacketError(e))?;
self.dispatch_ccsds(&sp_header, tc_raw)
}
}
impl<E: 'static> CcsdsDistributor<E> {
pub fn new(apid_handler: Box<dyn ApidPacketHandler<Error = E>>) -> Self {
pub fn new(apid_handler: Box<dyn CcsdsPacketHandler<Error = E>>) -> Self {
CcsdsDistributor { apid_handler }
}
/// 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 fsrc-example.
pub fn apid_handler_ref<T: ApidPacketHandler<Error = E>>(&self) -> Option<&T> {
pub fn apid_handler_ref<T: CcsdsPacketHandler<Error = E>>(&self) -> Option<&T> {
self.apid_handler.downcast_ref::<T>()
}
/// 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<T: ApidPacketHandler<Error = E>>(&mut self) -> Option<&mut T> {
pub fn apid_handler_mut<T: CcsdsPacketHandler<Error = E>>(&mut self) -> Option<&mut T> {
self.apid_handler.downcast_mut::<T>()
}
@ -182,7 +190,7 @@ impl<E: 'static> CcsdsDistributor<E> {
#[cfg(test)]
pub(crate) mod tests {
use super::*;
use crate::tmtc::ccsds_distrib::{ApidPacketHandler, CcsdsDistributor};
use crate::tmtc::ccsds_distrib::{CcsdsDistributor, CcsdsPacketHandler};
use spacepackets::tc::PusTc;
use spacepackets::CcsdsPacket;
use std::collections::VecDeque;
@ -207,7 +215,7 @@ pub(crate) mod tests {
pub unknown_packet_queue: VecDeque<(u16, Vec<u8>)>,
}
impl ApidPacketHandler for BasicApidHandlerSharedQueue {
impl CcsdsPacketHandler for BasicApidHandlerSharedQueue {
type Error = ();
fn valid_apids(&self) -> &'static [u16] {
&[0x000, 0x002]
@ -242,7 +250,7 @@ pub(crate) mod tests {
}
}
impl ApidPacketHandler for BasicApidHandlerOwnedQueue {
impl CcsdsPacketHandler for BasicApidHandlerOwnedQueue {
type Error = ();
fn valid_apids(&self) -> &'static [u16] {

View File

@ -12,6 +12,9 @@ use spacepackets::SpHeader;
pub mod ccsds_distrib;
pub mod pus_distrib;
pub use ccsds_distrib::{CcsdsDistributor, CcsdsError, CcsdsPacketHandler};
pub use pus_distrib::{PusDistributor, PusServiceProvider};
const _RAW_PACKET_ERROR: &str = "raw-tmtc";
const _CCSDS_ERROR: &str = "ccsds-tmtc";
const _PUS_ERROR: &str = "pus-tmtc";

View File

@ -137,7 +137,8 @@ mod tests {
use crate::tmtc::ccsds_distrib::tests::{
generate_ping_tc, BasicApidHandlerOwnedQueue, BasicApidHandlerSharedQueue,
};
use crate::tmtc::ccsds_distrib::{ApidPacketHandler, CcsdsDistributor};
use crate::tmtc::ccsds_distrib::{CcsdsDistributor, CcsdsPacketHandler};
use alloc::vec::Vec;
use spacepackets::ecss::PusError;
use spacepackets::tc::PusTc;
use spacepackets::CcsdsPacket;
@ -235,11 +236,11 @@ mod tests {
};
}
impl ApidPacketHandler for ApidHandlerOwned {
impl CcsdsPacketHandler for ApidHandlerOwned {
apid_handler_impl!();
}
impl ApidPacketHandler for ApidHandlerShared {
impl CcsdsPacketHandler for ApidHandlerShared {
apid_handler_impl!();
}