Re-worked TMTC modules
All checks were successful
Rust/sat-rs/pipeline/pr-main This commit looks good

This commit is contained in:
2024-04-16 11:04:22 +02:00
parent 8cfe3b81e7
commit 63f37f0917
53 changed files with 2030 additions and 2939 deletions

View File

@ -2,10 +2,13 @@
//!
//! This module contains structures to make working with the PUS C standard easier.
//! The satrs-example application contains various usage examples of these components.
use crate::pool::{StoreAddr, StoreError};
use crate::pool::{PoolAddr, PoolError};
use crate::pus::verification::{TcStateAccepted, TcStateToken, VerificationToken};
use crate::queue::{GenericReceiveError, GenericSendError};
use crate::request::{GenericMessage, MessageMetadata, RequestId};
#[cfg(feature = "alloc")]
use crate::tmtc::PacketAsVec;
use crate::tmtc::PacketInPool;
use crate::ComponentId;
use core::fmt::{Display, Formatter};
use core::time::Duration;
@ -44,12 +47,12 @@ use self::verification::VerificationReportingProvider;
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum PusTmVariant<'time, 'src_data> {
InStore(StoreAddr),
InStore(PoolAddr),
Direct(PusTmCreator<'time, 'src_data>),
}
impl From<StoreAddr> for PusTmVariant<'_, '_> {
fn from(value: StoreAddr) -> Self {
impl From<PoolAddr> for PusTmVariant<'_, '_> {
fn from(value: PoolAddr) -> Self {
Self::InStore(value)
}
}
@ -62,10 +65,10 @@ impl<'time, 'src_data> From<PusTmCreator<'time, 'src_data>> for PusTmVariant<'ti
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum EcssTmtcError {
Store(StoreError),
Store(PoolError),
ByteConversion(ByteConversionError),
Pus(PusError),
CantSendAddr(StoreAddr),
CantSendAddr(PoolAddr),
CantSendDirectTm,
Send(GenericSendError),
Receive(GenericReceiveError),
@ -99,8 +102,8 @@ impl Display for EcssTmtcError {
}
}
impl From<StoreError> for EcssTmtcError {
fn from(value: StoreError) -> Self {
impl From<PoolError> for EcssTmtcError {
fn from(value: PoolError) -> Self {
Self::Store(value)
}
}
@ -153,15 +156,15 @@ pub trait ChannelWithId: Send {
/// Generic trait for a user supplied sender object.
///
/// This sender object is responsible for sending PUS telemetry to a TM sink.
pub trait EcssTmSenderCore: Send {
fn send_tm(&self, source_id: ComponentId, tm: PusTmVariant) -> Result<(), EcssTmtcError>;
pub trait EcssTmSender: Send {
fn send_tm(&self, sender_id: ComponentId, tm: PusTmVariant) -> Result<(), EcssTmtcError>;
}
/// Generic trait for a user supplied sender object.
///
/// This sender object is responsible for sending PUS telecommands to a TC recipient. Each
/// telecommand can optionally have a token which contains its verification state.
pub trait EcssTcSenderCore {
pub trait EcssTcSender {
fn send_tc(&self, tc: PusTcCreator, token: Option<TcStateToken>) -> Result<(), EcssTmtcError>;
}
@ -169,32 +172,32 @@ pub trait EcssTcSenderCore {
#[derive(Default)]
pub struct EcssTmDummySender {}
impl EcssTmSenderCore for EcssTmDummySender {
impl EcssTmSender for EcssTmDummySender {
fn send_tm(&self, _source_id: ComponentId, _tm: PusTmVariant) -> Result<(), EcssTmtcError> {
Ok(())
}
}
/// A PUS telecommand packet can be stored in memory using different methods. Right now,
/// A PUS telecommand packet can be stored in memory and sent using different methods. Right now,
/// storage inside a pool structure like [crate::pool::StaticMemoryPool], and storage inside a
/// `Vec<u8>` are supported.
#[non_exhaustive]
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum TcInMemory {
StoreAddr(StoreAddr),
Pool(PacketInPool),
#[cfg(feature = "alloc")]
Vec(alloc::vec::Vec<u8>),
Vec(PacketAsVec),
}
impl From<StoreAddr> for TcInMemory {
fn from(value: StoreAddr) -> Self {
Self::StoreAddr(value)
impl From<PacketInPool> for TcInMemory {
fn from(value: PacketInPool) -> Self {
Self::Pool(value)
}
}
#[cfg(feature = "alloc")]
impl From<alloc::vec::Vec<u8>> for TcInMemory {
fn from(value: alloc::vec::Vec<u8>) -> Self {
impl From<PacketAsVec> for TcInMemory {
fn from(value: PacketAsVec) -> Self {
Self::Vec(value)
}
}
@ -262,25 +265,26 @@ impl From<PusError> for TryRecvTmtcError {
}
}
impl From<StoreError> for TryRecvTmtcError {
fn from(value: StoreError) -> Self {
impl From<PoolError> for TryRecvTmtcError {
fn from(value: PoolError) -> Self {
Self::Tmtc(value.into())
}
}
/// Generic trait for a user supplied receiver object.
pub trait EcssTcReceiverCore {
pub trait EcssTcReceiver {
fn recv_tc(&self) -> Result<EcssTcAndToken, TryRecvTmtcError>;
}
/// 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. It is generally assumed that the telecommand is stored in some pool structure,
/// and the store address is passed as well. This allows efficient zero-copy forwarding of
/// telecommands.
pub trait ReceivesEcssPusTc {
/// Generic trait for objects which can send ECSS PUS telecommands.
pub trait PacketSenderPusTc: Send {
type Error;
fn pass_pus_tc(&mut self, header: &SpHeader, pus_tc: &PusTcReader) -> Result<(), Self::Error>;
fn send_pus_tc(
&self,
sender_id: ComponentId,
header: &SpHeader,
pus_tc: &PusTcReader,
) -> Result<(), Self::Error>;
}
pub trait ActiveRequestMapProvider<V>: Sized {
@ -326,7 +330,7 @@ pub trait PusReplyHandler<ActiveRequestInfo: ActiveRequestProvider, ReplyType> {
&mut self,
reply: &GenericMessage<ReplyType>,
active_request: &ActiveRequestInfo,
tm_sender: &impl EcssTmSenderCore,
tm_sender: &impl EcssTmSender,
verification_handler: &impl VerificationReportingProvider,
time_stamp: &[u8],
) -> Result<bool, Self::Error>;
@ -334,14 +338,14 @@ pub trait PusReplyHandler<ActiveRequestInfo: ActiveRequestProvider, ReplyType> {
fn handle_unrequested_reply(
&mut self,
reply: &GenericMessage<ReplyType>,
tm_sender: &impl EcssTmSenderCore,
tm_sender: &impl EcssTmSender,
) -> Result<(), Self::Error>;
/// Handle the timeout of an active request.
fn handle_request_timeout(
&mut self,
active_request: &ActiveRequestInfo,
tm_sender: &impl EcssTmSenderCore,
tm_sender: &impl EcssTmSender,
verification_handler: &impl VerificationReportingProvider,
time_stamp: &[u8],
) -> Result<(), Self::Error>;
@ -353,9 +357,7 @@ pub mod alloc_mod {
use super::*;
use crate::pus::verification::VerificationReportingProvider;
/// Extension trait for [EcssTmSenderCore].
/// Extension trait for [EcssTmSender].
///
/// It provides additional functionality, for example by implementing the [Downcast] trait
/// and the [DynClone] trait.
@ -367,36 +369,36 @@ pub mod alloc_mod {
/// [Clone].
#[cfg(feature = "alloc")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
pub trait EcssTmSender: EcssTmSenderCore + Downcast + DynClone {
pub trait EcssTmSenderExt: EcssTmSender + Downcast + DynClone {
// Remove this once trait upcasting coercion has been implemented.
// Tracking issue: https://github.com/rust-lang/rust/issues/65991
fn upcast(&self) -> &dyn EcssTmSenderCore;
fn upcast(&self) -> &dyn EcssTmSender;
// Remove this once trait upcasting coercion has been implemented.
// Tracking issue: https://github.com/rust-lang/rust/issues/65991
fn upcast_mut(&mut self) -> &mut dyn EcssTmSenderCore;
fn upcast_mut(&mut self) -> &mut dyn EcssTmSender;
}
/// Blanket implementation for all types which implement [EcssTmSenderCore] and are clonable.
impl<T> EcssTmSender for T
/// Blanket implementation for all types which implement [EcssTmSender] and are clonable.
impl<T> EcssTmSenderExt for T
where
T: EcssTmSenderCore + Clone + 'static,
T: EcssTmSender + Clone + 'static,
{
// Remove this once trait upcasting coercion has been implemented.
// Tracking issue: https://github.com/rust-lang/rust/issues/65991
fn upcast(&self) -> &dyn EcssTmSenderCore {
fn upcast(&self) -> &dyn EcssTmSender {
self
}
// Remove this once trait upcasting coercion has been implemented.
// Tracking issue: https://github.com/rust-lang/rust/issues/65991
fn upcast_mut(&mut self) -> &mut dyn EcssTmSenderCore {
fn upcast_mut(&mut self) -> &mut dyn EcssTmSender {
self
}
}
dyn_clone::clone_trait_object!(EcssTmSender);
impl_downcast!(EcssTmSender);
dyn_clone::clone_trait_object!(EcssTmSenderExt);
impl_downcast!(EcssTmSenderExt);
/// Extension trait for [EcssTcSenderCore].
/// Extension trait for [EcssTcSender].
///
/// It provides additional functionality, for example by implementing the [Downcast] trait
/// and the [DynClone] trait.
@ -408,15 +410,15 @@ pub mod alloc_mod {
/// [Clone].
#[cfg(feature = "alloc")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
pub trait EcssTcSender: EcssTcSenderCore + Downcast + DynClone {}
pub trait EcssTcSenderExt: EcssTcSender + Downcast + DynClone {}
/// Blanket implementation for all types which implement [EcssTcSenderCore] and are clonable.
impl<T> EcssTcSender for T where T: EcssTcSenderCore + Clone + 'static {}
/// Blanket implementation for all types which implement [EcssTcSender] and are clonable.
impl<T> EcssTcSenderExt for T where T: EcssTcSender + Clone + 'static {}
dyn_clone::clone_trait_object!(EcssTcSender);
impl_downcast!(EcssTcSender);
dyn_clone::clone_trait_object!(EcssTcSenderExt);
impl_downcast!(EcssTcSenderExt);
/// Extension trait for [EcssTcReceiverCore].
/// Extension trait for [EcssTcReceiver].
///
/// It provides additional functionality, for example by implementing the [Downcast] trait
/// and the [DynClone] trait.
@ -428,12 +430,12 @@ pub mod alloc_mod {
/// [Clone].
#[cfg(feature = "alloc")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
pub trait EcssTcReceiver: EcssTcReceiverCore + Downcast {}
pub trait EcssTcReceiverExt: EcssTcReceiver + Downcast {}
/// Blanket implementation for all types which implement [EcssTcReceiverCore] and are clonable.
impl<T> EcssTcReceiver for T where T: EcssTcReceiverCore + 'static {}
/// Blanket implementation for all types which implement [EcssTcReceiver] and are clonable.
impl<T> EcssTcReceiverExt for T where T: EcssTcReceiver + 'static {}
impl_downcast!(EcssTcReceiver);
impl_downcast!(EcssTcReceiverExt);
/// This trait is an abstraction for the conversion of a PUS telecommand into a generic request
/// type.
@ -457,7 +459,7 @@ pub mod alloc_mod {
&mut self,
token: VerificationToken<TcStateAccepted>,
tc: &PusTcReader,
tm_sender: &(impl EcssTmSenderCore + ?Sized),
tm_sender: &(impl EcssTmSender + ?Sized),
verif_reporter: &impl VerificationReportingProvider,
time_stamp: &[u8],
) -> Result<(ActiveRequestInfo, Request), Self::Error>;
@ -654,19 +656,18 @@ pub mod alloc_mod {
#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
pub mod std_mod {
use crate::pool::{
PoolProvider, PoolProviderWithGuards, SharedStaticMemoryPool, StoreAddr, StoreError,
PoolAddr, PoolError, PoolProvider, PoolProviderWithGuards, SharedStaticMemoryPool,
};
use crate::pus::verification::{TcStateAccepted, VerificationToken};
use crate::pus::{
EcssTcAndToken, EcssTcReceiverCore, EcssTmSenderCore, EcssTmtcError, GenericReceiveError,
EcssTcAndToken, EcssTcReceiver, EcssTmSender, EcssTmtcError, GenericReceiveError,
GenericSendError, PusTmVariant, TryRecvTmtcError,
};
use crate::tmtc::tm_helper::SharedTmPool;
use crate::tmtc::{PacketAsVec, PacketSenderWithSharedPool};
use crate::ComponentId;
use alloc::vec::Vec;
use core::time::Duration;
use spacepackets::ecss::tc::PusTcReader;
use spacepackets::ecss::tm::PusTmCreator;
use spacepackets::ecss::WritablePusPacket;
use spacepackets::time::StdTimestampError;
use spacepackets::ByteConversionError;
@ -680,25 +681,20 @@ pub mod std_mod {
use super::verification::{TcStateToken, VerificationReportingProvider};
use super::{AcceptedEcssTcAndToken, ActiveRequestProvider, TcInMemory};
use crate::tmtc::PacketInPool;
#[derive(Debug)]
pub struct PusTmInPool {
pub source_id: ComponentId,
pub store_addr: StoreAddr,
}
impl From<mpsc::SendError<StoreAddr>> for EcssTmtcError {
fn from(_: mpsc::SendError<StoreAddr>) -> Self {
impl From<mpsc::SendError<PoolAddr>> for EcssTmtcError {
fn from(_: mpsc::SendError<PoolAddr>) -> Self {
Self::Send(GenericSendError::RxDisconnected)
}
}
impl EcssTmSenderCore for mpsc::Sender<PusTmInPool> {
impl EcssTmSender for mpsc::Sender<PacketInPool> {
fn send_tm(&self, source_id: ComponentId, tm: PusTmVariant) -> Result<(), EcssTmtcError> {
match tm {
PusTmVariant::InStore(store_addr) => self
.send(PusTmInPool {
source_id,
.send(PacketInPool {
sender_id: source_id,
store_addr,
})
.map_err(|_| GenericSendError::RxDisconnected)?,
@ -708,12 +704,12 @@ pub mod std_mod {
}
}
impl EcssTmSenderCore for mpsc::SyncSender<PusTmInPool> {
impl EcssTmSender for mpsc::SyncSender<PacketInPool> {
fn send_tm(&self, source_id: ComponentId, tm: PusTmVariant) -> Result<(), EcssTmtcError> {
match tm {
PusTmVariant::InStore(store_addr) => self
.try_send(PusTmInPool {
source_id,
.try_send(PacketInPool {
sender_id: source_id,
store_addr,
})
.map_err(|e| EcssTmtcError::Send(e.into()))?,
@ -723,21 +719,15 @@ pub mod std_mod {
}
}
#[derive(Debug)]
pub struct PusTmAsVec {
pub source_id: ComponentId,
pub packet: Vec<u8>,
}
pub type MpscTmAsVecSender = mpsc::Sender<PacketAsVec>;
pub type MpscTmAsVecSender = mpsc::Sender<PusTmAsVec>;
impl EcssTmSenderCore for MpscTmAsVecSender {
impl EcssTmSender for MpscTmAsVecSender {
fn send_tm(&self, source_id: ComponentId, tm: PusTmVariant) -> Result<(), EcssTmtcError> {
match tm {
PusTmVariant::InStore(addr) => return Err(EcssTmtcError::CantSendAddr(addr)),
PusTmVariant::Direct(tm) => self
.send(PusTmAsVec {
source_id,
.send(PacketAsVec {
sender_id: source_id,
packet: tm.to_vec()?,
})
.map_err(|e| EcssTmtcError::Send(e.into()))?,
@ -746,15 +736,15 @@ pub mod std_mod {
}
}
pub type MpscTmAsVecSenderBounded = mpsc::SyncSender<PusTmAsVec>;
pub type MpscTmAsVecSenderBounded = mpsc::SyncSender<PacketAsVec>;
impl EcssTmSenderCore for MpscTmAsVecSenderBounded {
impl EcssTmSender for MpscTmAsVecSenderBounded {
fn send_tm(&self, source_id: ComponentId, tm: PusTmVariant) -> Result<(), EcssTmtcError> {
match tm {
PusTmVariant::InStore(addr) => return Err(EcssTmtcError::CantSendAddr(addr)),
PusTmVariant::Direct(tm) => self
.send(PusTmAsVec {
source_id,
.send(PacketAsVec {
sender_id: source_id,
packet: tm.to_vec()?,
})
.map_err(|e| EcssTmtcError::Send(e.into()))?,
@ -763,47 +753,9 @@ pub mod std_mod {
}
}
#[derive(Clone)]
pub struct TmInSharedPoolSender<Sender: EcssTmSenderCore> {
shared_tm_store: SharedTmPool,
sender: Sender,
}
impl<Sender: EcssTmSenderCore> TmInSharedPoolSender<Sender> {
pub fn send_direct_tm(
&self,
source_id: ComponentId,
tm: PusTmCreator,
) -> Result<(), EcssTmtcError> {
let addr = self.shared_tm_store.add_pus_tm(&tm)?;
self.sender.send_tm(source_id, PusTmVariant::InStore(addr))
}
}
impl<Sender: EcssTmSenderCore> EcssTmSenderCore for TmInSharedPoolSender<Sender> {
fn send_tm(&self, source_id: ComponentId, tm: PusTmVariant) -> Result<(), EcssTmtcError> {
if let PusTmVariant::Direct(tm) = tm {
return self.send_direct_tm(source_id, tm);
}
self.sender.send_tm(source_id, tm)
}
}
impl<Sender: EcssTmSenderCore> TmInSharedPoolSender<Sender> {
pub fn new(shared_tm_store: SharedTmPool, sender: Sender) -> Self {
Self {
shared_tm_store,
sender,
}
}
}
pub type MpscTmInSharedPoolSender = TmInSharedPoolSender<mpsc::Sender<PusTmInPool>>;
pub type MpscTmInSharedPoolSenderBounded = TmInSharedPoolSender<mpsc::SyncSender<PusTmInPool>>;
pub type MpscTcReceiver = mpsc::Receiver<EcssTcAndToken>;
impl EcssTcReceiverCore for MpscTcReceiver {
impl EcssTcReceiver for MpscTcReceiver {
fn recv_tc(&self) -> Result<EcssTcAndToken, TryRecvTmtcError> {
self.try_recv().map_err(|e| match e {
TryRecvError::Empty => TryRecvTmtcError::Empty,
@ -819,16 +771,14 @@ pub mod std_mod {
use super::*;
use crossbeam_channel as cb;
pub type TmInSharedPoolSenderWithCrossbeam = TmInSharedPoolSender<cb::Sender<PusTmInPool>>;
impl From<cb::SendError<StoreAddr>> for EcssTmtcError {
fn from(_: cb::SendError<StoreAddr>) -> Self {
impl From<cb::SendError<PoolAddr>> for EcssTmtcError {
fn from(_: cb::SendError<PoolAddr>) -> Self {
Self::Send(GenericSendError::RxDisconnected)
}
}
impl From<cb::TrySendError<StoreAddr>> for EcssTmtcError {
fn from(value: cb::TrySendError<StoreAddr>) -> Self {
impl From<cb::TrySendError<PoolAddr>> for EcssTmtcError {
fn from(value: cb::TrySendError<PoolAddr>) -> Self {
match value {
cb::TrySendError::Full(_) => Self::Send(GenericSendError::QueueFull(None)),
cb::TrySendError::Disconnected(_) => {
@ -838,37 +788,31 @@ pub mod std_mod {
}
}
impl EcssTmSenderCore for cb::Sender<PusTmInPool> {
impl EcssTmSender for cb::Sender<PacketInPool> {
fn send_tm(
&self,
source_id: ComponentId,
sender_id: ComponentId,
tm: PusTmVariant,
) -> Result<(), EcssTmtcError> {
match tm {
PusTmVariant::InStore(addr) => self
.try_send(PusTmInPool {
source_id,
store_addr: addr,
})
.try_send(PacketInPool::new(sender_id, addr))
.map_err(|e| EcssTmtcError::Send(e.into()))?,
PusTmVariant::Direct(_) => return Err(EcssTmtcError::CantSendDirectTm),
};
Ok(())
}
}
impl EcssTmSenderCore for cb::Sender<PusTmAsVec> {
impl EcssTmSender for cb::Sender<PacketAsVec> {
fn send_tm(
&self,
source_id: ComponentId,
sender_id: ComponentId,
tm: PusTmVariant,
) -> Result<(), EcssTmtcError> {
match tm {
PusTmVariant::InStore(addr) => return Err(EcssTmtcError::CantSendAddr(addr)),
PusTmVariant::Direct(tm) => self
.send(PusTmAsVec {
source_id,
packet: tm.to_vec()?,
})
.send(PacketAsVec::new(sender_id, tm.to_vec()?))
.map_err(|e| EcssTmtcError::Send(e.into()))?,
};
Ok(())
@ -1010,6 +954,8 @@ pub mod std_mod {
fn tc_slice_raw(&self) -> &[u8];
fn sender_id(&self) -> Option<ComponentId>;
fn cache_and_convert(
&mut self,
possible_packet: &TcInMemory,
@ -1032,6 +978,7 @@ pub mod std_mod {
/// [SharedStaticMemoryPool].
#[derive(Default, Clone)]
pub struct EcssTcInVecConverter {
sender_id: Option<ComponentId>,
pub pus_tc_raw: Option<Vec<u8>>,
}
@ -1039,16 +986,21 @@ pub mod std_mod {
fn cache(&mut self, tc_in_memory: &TcInMemory) -> Result<(), PusTcFromMemError> {
self.pus_tc_raw = None;
match tc_in_memory {
super::TcInMemory::StoreAddr(_) => {
super::TcInMemory::Pool(_packet_in_pool) => {
return Err(PusTcFromMemError::InvalidFormat(tc_in_memory.clone()));
}
super::TcInMemory::Vec(vec) => {
self.pus_tc_raw = Some(vec.clone());
super::TcInMemory::Vec(packet_with_sender) => {
self.pus_tc_raw = Some(packet_with_sender.packet.clone());
self.sender_id = Some(packet_with_sender.sender_id);
}
};
Ok(())
}
fn sender_id(&self) -> Option<ComponentId> {
self.sender_id
}
fn tc_slice_raw(&self) -> &[u8] {
if self.pus_tc_raw.is_none() {
return &[];
@ -1062,6 +1014,7 @@ pub mod std_mod {
/// packets should be avoided. Please note that this structure is not able to convert TCs which
/// are stored as a `Vec<u8>`.
pub struct EcssTcInSharedStoreConverter {
sender_id: Option<ComponentId>,
shared_tc_store: SharedStaticMemoryPool,
pus_buf: Vec<u8>,
}
@ -1069,15 +1022,16 @@ pub mod std_mod {
impl EcssTcInSharedStoreConverter {
pub fn new(shared_tc_store: SharedStaticMemoryPool, max_expected_tc_size: usize) -> Self {
Self {
sender_id: None,
shared_tc_store,
pus_buf: alloc::vec![0; max_expected_tc_size],
}
}
pub fn copy_tc_to_buf(&mut self, addr: StoreAddr) -> Result<(), PusTcFromMemError> {
pub fn copy_tc_to_buf(&mut self, addr: PoolAddr) -> Result<(), PusTcFromMemError> {
// Keep locked section as short as possible.
let mut tc_pool = self.shared_tc_store.write().map_err(|_| {
PusTcFromMemError::EcssTmtc(EcssTmtcError::Store(StoreError::LockError))
PusTcFromMemError::EcssTmtc(EcssTmtcError::Store(PoolError::LockError))
})?;
let tc_size = tc_pool.len_of_data(&addr).map_err(EcssTmtcError::Store)?;
if tc_size > self.pus_buf.len() {
@ -1099,8 +1053,9 @@ pub mod std_mod {
impl EcssTcInMemConverter for EcssTcInSharedStoreConverter {
fn cache(&mut self, tc_in_memory: &TcInMemory) -> Result<(), PusTcFromMemError> {
match tc_in_memory {
super::TcInMemory::StoreAddr(addr) => {
self.copy_tc_to_buf(*addr)?;
super::TcInMemory::Pool(packet_in_pool) => {
self.copy_tc_to_buf(packet_in_pool.store_addr)?;
self.sender_id = Some(packet_in_pool.sender_id);
}
super::TcInMemory::Vec(_) => {
return Err(PusTcFromMemError::InvalidFormat(tc_in_memory.clone()));
@ -1112,11 +1067,15 @@ pub mod std_mod {
fn tc_slice_raw(&self) -> &[u8] {
self.pus_buf.as_ref()
}
fn sender_id(&self) -> Option<ComponentId> {
self.sender_id
}
}
pub struct PusServiceBase<
TcReceiver: EcssTcReceiverCore,
TmSender: EcssTmSenderCore,
TcReceiver: EcssTcReceiver,
TmSender: EcssTmSender,
VerificationReporter: VerificationReportingProvider,
> {
pub id: ComponentId,
@ -1135,8 +1094,8 @@ pub mod std_mod {
/// by using the [EcssTcInMemConverter] abstraction. This object provides some convenience
/// methods to make the generic parts of TC handling easier.
pub struct PusServiceHelper<
TcReceiver: EcssTcReceiverCore,
TmSender: EcssTmSenderCore,
TcReceiver: EcssTcReceiver,
TmSender: EcssTmSender,
TcInMemConverter: EcssTcInMemConverter,
VerificationReporter: VerificationReportingProvider,
> {
@ -1145,8 +1104,8 @@ pub mod std_mod {
}
impl<
TcReceiver: EcssTcReceiverCore,
TmSender: EcssTmSenderCore,
TcReceiver: EcssTcReceiver,
TmSender: EcssTmSender,
TcInMemConverter: EcssTcInMemConverter,
VerificationReporter: VerificationReportingProvider,
> PusServiceHelper<TcReceiver, TmSender, TcInMemConverter, VerificationReporter>
@ -1177,7 +1136,7 @@ pub mod std_mod {
&self.common.tm_sender
}
/// This function can be used to poll the internal [EcssTcReceiverCore] object for the next
/// This function can be used to poll the internal [EcssTcReceiver] object for the next
/// telecommand packet. It will return `Ok(None)` if there are not packets available.
/// In any other case, it will perform the acceptance of the ECSS TC packet using the
/// internal [VerificationReportingProvider] object. It will then return the telecommand
@ -1236,14 +1195,14 @@ pub mod std_mod {
pub type PusServiceHelperStaticWithMpsc<TcInMemConverter, VerificationReporter> =
PusServiceHelper<
MpscTcReceiver,
MpscTmInSharedPoolSender,
PacketSenderWithSharedPool,
TcInMemConverter,
VerificationReporter,
>;
pub type PusServiceHelperStaticWithBoundedMpsc<TcInMemConverter, VerificationReporter> =
PusServiceHelper<
MpscTcReceiver,
MpscTmInSharedPoolSenderBounded,
PacketSenderWithSharedPool,
TcInMemConverter,
VerificationReporter,
>;
@ -1313,7 +1272,7 @@ pub mod tests {
use crate::pool::{PoolProvider, SharedStaticMemoryPool, StaticMemoryPool, StaticPoolConfig};
use crate::pus::verification::{RequestId, VerificationReporter};
use crate::tmtc::tm_helper::SharedTmPool;
use crate::tmtc::{PacketAsVec, PacketInPool, PacketSenderWithSharedPool, SharedPacketPool};
use crate::ComponentId;
use super::test_util::{TEST_APID, TEST_COMPONENT_ID_0};
@ -1370,14 +1329,14 @@ pub mod tests {
pus_buf: RefCell<[u8; 2048]>,
tm_buf: [u8; 2048],
tc_pool: SharedStaticMemoryPool,
tm_pool: SharedTmPool,
tm_pool: SharedPacketPool,
tc_sender: mpsc::SyncSender<EcssTcAndToken>,
tm_receiver: mpsc::Receiver<PusTmInPool>,
tm_receiver: mpsc::Receiver<PacketInPool>,
}
pub type PusServiceHelperStatic = PusServiceHelper<
MpscTcReceiver,
MpscTmInSharedPoolSenderBounded,
PacketSenderWithSharedPool,
EcssTcInSharedStoreConverter,
VerificationReporter,
>;
@ -1392,14 +1351,16 @@ pub mod tests {
let tc_pool = StaticMemoryPool::new(pool_cfg.clone());
let tm_pool = StaticMemoryPool::new(pool_cfg);
let shared_tc_pool = SharedStaticMemoryPool::new(RwLock::new(tc_pool));
let shared_tm_pool = SharedTmPool::new(tm_pool);
let shared_tm_pool = SharedStaticMemoryPool::new(RwLock::new(tm_pool));
let shared_tm_pool_wrapper = SharedPacketPool::new(&shared_tm_pool);
let (test_srv_tc_tx, test_srv_tc_rx) = mpsc::sync_channel(10);
let (tm_tx, tm_rx) = mpsc::sync_channel(10);
let verif_cfg = VerificationReporterCfg::new(TEST_APID, 1, 2, 8).unwrap();
let verification_handler =
VerificationReporter::new(TEST_COMPONENT_ID_0.id(), &verif_cfg);
let test_srv_tm_sender = TmInSharedPoolSender::new(shared_tm_pool.clone(), tm_tx);
let test_srv_tm_sender =
PacketSenderWithSharedPool::new(tm_tx, shared_tm_pool_wrapper.clone());
let in_store_converter =
EcssTcInSharedStoreConverter::new(shared_tc_pool.clone(), 2048);
(
@ -1407,7 +1368,7 @@ pub mod tests {
pus_buf: RefCell::new([0; 2048]),
tm_buf: [0; 2048],
tc_pool: shared_tc_pool,
tm_pool: shared_tm_pool,
tm_pool: shared_tm_pool_wrapper,
tc_sender: test_srv_tc_tx,
tm_receiver: tm_rx,
},
@ -1420,7 +1381,12 @@ pub mod tests {
),
)
}
pub fn send_tc(&self, token: &VerificationToken<TcStateAccepted>, tc: &PusTcCreator) {
pub fn send_tc(
&self,
sender_id: ComponentId,
token: &VerificationToken<TcStateAccepted>,
tc: &PusTcCreator,
) {
let mut mut_buf = self.pus_buf.borrow_mut();
let tc_size = tc.write_to_bytes(mut_buf.as_mut_slice()).unwrap();
let mut tc_pool = self.tc_pool.write().unwrap();
@ -1428,7 +1394,10 @@ pub mod tests {
drop(tc_pool);
// Send accepted TC to test service handler.
self.tc_sender
.send(EcssTcAndToken::new(addr, *token))
.send(EcssTcAndToken::new(
PacketInPool::new(sender_id, addr),
*token,
))
.expect("sending tc failed");
}
@ -1469,7 +1438,7 @@ pub mod tests {
pub struct PusServiceHandlerWithVecCommon {
current_tm: Option<Vec<u8>>,
tc_sender: mpsc::Sender<EcssTcAndToken>,
tm_receiver: mpsc::Receiver<PusTmAsVec>,
tm_receiver: mpsc::Receiver<PacketAsVec>,
}
pub type PusServiceHelperDynamic = PusServiceHelper<
MpscTcReceiver,
@ -1542,11 +1511,19 @@ pub mod tests {
}
impl PusServiceHandlerWithVecCommon {
pub fn send_tc(&self, token: &VerificationToken<TcStateAccepted>, tc: &PusTcCreator) {
pub fn send_tc(
&self,
sender_id: ComponentId,
token: &VerificationToken<TcStateAccepted>,
tc: &PusTcCreator,
) {
// Send accepted TC to test service handler.
self.tc_sender
.send(EcssTcAndToken::new(
TcInMemory::Vec(tc.to_vec().expect("pus tc conversion to vec failed")),
TcInMemory::Vec(PacketAsVec::new(
sender_id,
tc.to_vec().expect("pus tc conversion to vec failed"),
)),
*token,
))
.expect("sending tc failed");