From 485788adbda8b03992862dabaeb849a09a9c9c27 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 15 Mar 2024 13:58:43 +0100 Subject: [PATCH] reduce the number of generics on request handler --- satrs-example/src/pus/action.rs | 79 ++++-- satrs-example/src/pus/hk.rs | 25 +- satrs-example/src/pus/mod.rs | 57 +---- satrs-example/src/requests.rs | 87 ++++++- satrs/src/mode.rs | 438 ++++++++++++-------------------- satrs/src/pus/action.rs | 26 +- satrs/src/pus/hk.rs | 184 +++----------- satrs/src/pus/mod.rs | 108 ++++---- satrs/src/pus/mode.rs | 163 ++++++++++-- 9 files changed, 566 insertions(+), 601 deletions(-) diff --git a/satrs-example/src/pus/action.rs b/satrs-example/src/pus/action.rs index f5b779f..66c2918 100644 --- a/satrs-example/src/pus/action.rs +++ b/satrs-example/src/pus/action.rs @@ -1,7 +1,10 @@ use log::{error, warn}; use satrs::action::{ActionRequest, ActionRequestVariant}; use satrs::pool::{SharedStaticMemoryPool, StoreAddr}; -use satrs::pus::action::PusService8ActionRequestHandler; +use satrs::pus::action::{ + ActionReplyPusWithActionId, ActiveActionRequest, DefaultActiveActionRequestMap, + PusService8ActionRequestHandler, PusService8ReplyHandler, +}; use satrs::pus::verification::{ FailParams, TcStateAccepted, VerificationReporterWithSharedPoolMpscBoundedSender, VerificationReporterWithVecMpscSender, VerificationReportingProvider, VerificationToken, @@ -9,8 +12,9 @@ use satrs::pus::verification::{ use satrs::pus::{ EcssTcAndToken, EcssTcInMemConverter, EcssTcInSharedStoreConverter, EcssTcInVecConverter, EcssTcReceiverCore, EcssTmSenderCore, MpscTcReceiver, PusPacketHandlerResult, - PusPacketHandlingError, PusServiceHelper, PusTcToRequestConverter, TmAsVecSenderWithId, - TmAsVecSenderWithMpsc, TmInSharedPoolSenderWithBoundedMpsc, TmInSharedPoolSenderWithId, + PusPacketHandlingError, PusServiceHelper, PusTcToRequestConverter, ReplyHandlerHook, + TmAsVecSenderWithId, TmAsVecSenderWithMpsc, TmInSharedPoolSenderWithBoundedMpsc, + TmInSharedPoolSenderWithId, }; use satrs::request::TargetAndApidId; use satrs::spacepackets::ecss::tc::PusTcReader; @@ -22,8 +26,6 @@ use std::sync::mpsc::{self}; use crate::requests::GenericRequestRouter; -use super::GenericRoutingErrorHandler; - #[derive(Default)] pub struct ExampleActionRequestConverter {} @@ -97,19 +99,29 @@ pub fn create_action_service_static( "PUS_8_TC_RECV", pus_action_rx, ); - let pus_8_handler = PusService8ActionRequestHandler::new( + let action_request_handler = PusService8ActionRequestHandler::new( PusServiceHelper::new( action_srv_receiver, - action_srv_tm_sender, + action_srv_tm_sender.clone(), PUS_APID, verif_reporter.clone(), EcssTcInSharedStoreConverter::new(tc_pool.clone(), 2048), ), ExampleActionRequestConverter::default(), action_router, - GenericRoutingErrorHandler::<8>::default(), ); - Pus8Wrapper { pus_8_handler } + let action_reply_handler = PusService8ReplyHandler::new_from_now( + verif_reporter.clone(), + DefaultActiveActionRequestMap::default(), + 1024, + PusActionReplyHook::default(), + action_srv_tm_sender, + ) + .expect("Failed to create PUS 8 reply handler"); + Pus8Wrapper { + action_request_handler, + action_reply_handler, + } } pub fn create_action_service_dynamic( @@ -133,35 +145,69 @@ pub fn create_action_service_dynamic( "PUS_8_TC_RECV", pus_action_rx, ); - let pus_8_handler = PusService8ActionRequestHandler::new( + let action_request_handler = PusService8ActionRequestHandler::new( PusServiceHelper::new( action_srv_receiver, - action_srv_tm_sender, + action_srv_tm_sender.clone(), PUS_APID, verif_reporter.clone(), EcssTcInVecConverter::default(), ), ExampleActionRequestConverter::default(), action_router, - GenericRoutingErrorHandler::<8>::default(), ); - Pus8Wrapper { pus_8_handler } + let action_reply_handler = PusService8ReplyHandler::new_from_now( + verif_reporter.clone(), + DefaultActiveActionRequestMap::default(), + 1024, + PusActionReplyHook::default(), + action_srv_tm_sender, + ) + .expect("Failed to create PUS 8 reply handler"); + Pus8Wrapper { + action_request_handler, + action_reply_handler, + } } +#[derive(Default)] +pub struct PusActionReplyHook {} + +impl ReplyHandlerHook for PusActionReplyHook { + fn handle_unexpected_reply( + &mut self, + reply: &satrs::request::GenericMessage, + ) { + println!("received unexpected action reply {:?}", reply); + } + + fn timeout_callback(&self, active_request: &ActiveActionRequest) { + println!("active request {active_request:?} timed out"); + } + + fn timeout_error_code(&self) -> satrs::res_code::ResultU16 { + todo!() + } +} pub struct Pus8Wrapper< TcReceiver: EcssTcReceiverCore, TmSender: EcssTmSenderCore, TcInMemConverter: EcssTcInMemConverter, VerificationReporter: VerificationReportingProvider, > { - pub(crate) pus_8_handler: PusService8ActionRequestHandler< + pub(crate) action_request_handler: PusService8ActionRequestHandler< TcReceiver, TmSender, TcInMemConverter, VerificationReporter, ExampleActionRequestConverter, GenericRequestRouter, - GenericRoutingErrorHandler<8>, + >, + pub(crate) action_reply_handler: PusService8ReplyHandler< + VerificationReporter, + DefaultActiveActionRequestMap, + PusActionReplyHook, + TmSender, >, } @@ -173,7 +219,7 @@ impl< > Pus8Wrapper { pub fn handle_next_packet(&mut self) -> bool { - match self.pus_8_handler.handle_one_tc() { + match self.action_request_handler.handle_one_tc() { Ok(result) => match result { PusPacketHandlerResult::RequestHandled => {} PusPacketHandlerResult::RequestHandledPartialSuccess(e) => { @@ -193,6 +239,7 @@ impl< error!("PUS packet handling error: {error:?}") } } + // self.action_reply_handler.handle_replies(); false } } diff --git a/satrs-example/src/pus/hk.rs b/satrs-example/src/pus/hk.rs index 48a54be..8f6d608 100644 --- a/satrs-example/src/pus/hk.rs +++ b/satrs-example/src/pus/hk.rs @@ -1,18 +1,16 @@ use log::{error, warn}; use satrs::hk::{CollectionIntervalFactor, HkRequest}; use satrs::pool::{SharedStaticMemoryPool, StoreAddr}; -use satrs::pus::hk::{PusHkToRequestConverter, PusService3HkHandler}; -use satrs::pus::verification::std_mod::{ - VerificationReporterWithSharedPoolMpscBoundedSender, VerificationReporterWithVecMpscSender, -}; +use satrs::pus::hk::PusService3HkRequestHandler; use satrs::pus::verification::{ - FailParams, TcStateAccepted, VerificationReportingProvider, VerificationToken, + FailParams, TcStateAccepted, VerificationReporterWithSharedPoolMpscBoundedSender, + VerificationReporterWithVecMpscSender, VerificationReportingProvider, VerificationToken, }; use satrs::pus::{ EcssTcAndToken, EcssTcInMemConverter, EcssTcInSharedStoreConverter, EcssTcInVecConverter, EcssTcReceiverCore, EcssTmSenderCore, MpscTcReceiver, PusPacketHandlerResult, - PusPacketHandlingError, PusServiceHelper, TmAsVecSenderWithId, TmAsVecSenderWithMpsc, - TmInSharedPoolSenderWithBoundedMpsc, TmInSharedPoolSenderWithId, + PusPacketHandlingError, PusServiceHelper, PusTcToRequestConverter, TmAsVecSenderWithId, + TmAsVecSenderWithMpsc, TmInSharedPoolSenderWithBoundedMpsc, TmInSharedPoolSenderWithId, }; use satrs::request::TargetAndApidId; use satrs::spacepackets::ecss::tc::PusTcReader; @@ -24,12 +22,10 @@ use std::sync::mpsc::{self}; use crate::requests::GenericRequestRouter; -use super::GenericRoutingErrorHandler; - #[derive(Default)] pub struct ExampleHkRequestConverter {} -impl PusHkToRequestConverter for ExampleHkRequestConverter { +impl PusTcToRequestConverter for ExampleHkRequestConverter { type Error = PusPacketHandlingError; fn convert( @@ -165,7 +161,7 @@ pub fn create_hk_service_static( ); let hk_srv_receiver = MpscTcReceiver::new(TcReceiverId::PusHk as ChannelId, "PUS_8_TC_RECV", pus_hk_rx); - let pus_3_handler = PusService3HkHandler::new( + let pus_3_handler = PusService3HkRequestHandler::new( PusServiceHelper::new( hk_srv_receiver, hk_srv_tm_sender, @@ -175,7 +171,6 @@ pub fn create_hk_service_static( ), ExampleHkRequestConverter::default(), request_router, - GenericRoutingErrorHandler::default(), ); Pus3Wrapper { pus_3_handler } } @@ -198,7 +193,7 @@ pub fn create_hk_service_dynamic( ); let hk_srv_receiver = MpscTcReceiver::new(TcReceiverId::PusHk as ChannelId, "PUS_8_TC_RECV", pus_hk_rx); - let pus_3_handler = PusService3HkHandler::new( + let pus_3_handler = PusService3HkRequestHandler::new( PusServiceHelper::new( hk_srv_receiver, hk_srv_tm_sender, @@ -208,7 +203,6 @@ pub fn create_hk_service_dynamic( ), ExampleHkRequestConverter::default(), request_router, - GenericRoutingErrorHandler::default(), ); Pus3Wrapper { pus_3_handler } } @@ -219,14 +213,13 @@ pub struct Pus3Wrapper< TcInMemConverter: EcssTcInMemConverter, VerificationReporter: VerificationReportingProvider, > { - pub(crate) pus_3_handler: PusService3HkHandler< + pub(crate) pus_3_handler: PusService3HkRequestHandler< TcReceiver, TmSender, TcInMemConverter, VerificationReporter, ExampleHkRequestConverter, GenericRequestRouter, - GenericRoutingErrorHandler<3>, >, } diff --git a/satrs-example/src/pus/mod.rs b/satrs-example/src/pus/mod.rs index 2b6c3ed..60a4644 100644 --- a/satrs-example/src/pus/mod.rs +++ b/satrs-example/src/pus/mod.rs @@ -1,9 +1,7 @@ use crate::tmtc::MpscStoreAndSendError; use log::warn; use satrs::pus::verification::{FailParams, VerificationReportingProvider}; -use satrs::pus::{ - EcssTcAndToken, GenericRoutingError, PusPacketHandlerResult, PusRoutingErrorHandler, TcInMemory, -}; +use satrs::pus::{EcssTcAndToken, PusPacketHandlerResult, TcInMemory}; use satrs::spacepackets::ecss::tc::PusTcReader; use satrs::spacepackets::ecss::PusServiceId; use satrs::spacepackets::time::cds::TimeProvider; @@ -153,56 +151,3 @@ impl PusReceiver {} - -impl PusRoutingErrorHandler for GenericRoutingErrorHandler { - type Error = satrs::pus::GenericRoutingError; - - fn handle_error( - &self, - target_id: satrs::TargetId, - token: satrs::pus::verification::VerificationToken< - satrs::pus::verification::TcStateAccepted, - >, - _tc: &PusTcReader, - error: Self::Error, - time_stamp: &[u8], - verif_reporter: &impl VerificationReportingProvider, - ) { - warn!("Routing request for service {SERVICE_ID} failed: {error:?}"); - match error { - GenericRoutingError::UnknownTargetId(id) => { - let mut fail_data: [u8; 8] = [0; 8]; - fail_data.copy_from_slice(&id.to_be_bytes()); - verif_reporter - .start_failure( - token, - FailParams::new(time_stamp, &tmtc_err::UNKNOWN_TARGET_ID, &fail_data), - ) - .expect("Sending start failure failed"); - } - GenericRoutingError::SendError(_) => { - let mut fail_data: [u8; 8] = [0; 8]; - fail_data.copy_from_slice(&target_id.to_be_bytes()); - verif_reporter - .start_failure( - token, - FailParams::new(time_stamp, &tmtc_err::ROUTING_ERROR, &fail_data), - ) - .expect("Sending start failure failed"); - } - GenericRoutingError::NotEnoughAppData { expected, found } => { - let mut context_info = (found as u32).to_be_bytes().to_vec(); - context_info.extend_from_slice(&(expected as u32).to_be_bytes()); - verif_reporter - .start_failure( - token, - FailParams::new(time_stamp, &tmtc_err::NOT_ENOUGH_APP_DATA, &context_info), - ) - .expect("Sending start failure failed"); - } - } - } -} diff --git a/satrs-example/src/requests.rs b/satrs-example/src/requests.rs index 0c27b9e..6747a33 100644 --- a/satrs-example/src/requests.rs +++ b/satrs-example/src/requests.rs @@ -2,14 +2,19 @@ use std::collections::HashMap; use std::sync::mpsc; use derive_new::new; +use log::warn; use satrs::action::ActionRequest; use satrs::hk::HkRequest; use satrs::mode::ModeRequest; -use satrs::pus::hk::PusHkRequestRouter; -use satrs::pus::verification::{TcStateAccepted, VerificationToken}; +use satrs::pus::verification::{ + FailParams, TcStateAccepted, VerificationReportingProvider, VerificationToken, +}; use satrs::pus::{GenericRoutingError, PusRequestRouter}; use satrs::queue::GenericSendError; +use satrs::spacepackets::ecss::tc::PusTcReader; +use satrs::spacepackets::ecss::PusPacket; use satrs::TargetId; +use satrs_example::config::tmtc_err; #[allow(dead_code)] #[derive(Clone, Eq, PartialEq, Debug)] @@ -48,7 +53,57 @@ impl RequestWithToken { #[derive(Default, Clone)] pub struct GenericRequestRouter(pub HashMap>); -impl PusHkRequestRouter for GenericRequestRouter { +impl GenericRequestRouter { + fn handle_error_generic( + &self, + target_id: satrs::TargetId, + token: satrs::pus::verification::VerificationToken< + satrs::pus::verification::TcStateAccepted, + >, + tc: &PusTcReader, + error: GenericRoutingError, + time_stamp: &[u8], + verif_reporter: &impl VerificationReportingProvider, + ) { + warn!( + "Routing request for service {} failed: {error:?}", + tc.service() + ); + match error { + GenericRoutingError::UnknownTargetId(id) => { + let mut fail_data: [u8; 8] = [0; 8]; + fail_data.copy_from_slice(&id.to_be_bytes()); + verif_reporter + .start_failure( + token, + FailParams::new(time_stamp, &tmtc_err::UNKNOWN_TARGET_ID, &fail_data), + ) + .expect("Sending start failure failed"); + } + GenericRoutingError::SendError(_) => { + let mut fail_data: [u8; 8] = [0; 8]; + fail_data.copy_from_slice(&target_id.to_be_bytes()); + verif_reporter + .start_failure( + token, + FailParams::new(time_stamp, &tmtc_err::ROUTING_ERROR, &fail_data), + ) + .expect("Sending start failure failed"); + } + GenericRoutingError::NotEnoughAppData { expected, found } => { + let mut context_info = (found as u32).to_be_bytes().to_vec(); + context_info.extend_from_slice(&(expected as u32).to_be_bytes()); + verif_reporter + .start_failure( + token, + FailParams::new(time_stamp, &tmtc_err::NOT_ENOUGH_APP_DATA, &context_info), + ) + .expect("Sending start failure failed"); + } + } + } +} +impl PusRequestRouter for GenericRequestRouter { type Error = GenericRoutingError; fn route( @@ -68,6 +123,19 @@ impl PusHkRequestRouter for GenericRequestRouter { } Ok(()) } + fn handle_error( + &self, + target_id: satrs::TargetId, + token: satrs::pus::verification::VerificationToken< + satrs::pus::verification::TcStateAccepted, + >, + tc: &PusTcReader, + error: GenericRoutingError, + time_stamp: &[u8], + verif_reporter: &impl VerificationReportingProvider, + ) { + self.handle_error_generic(target_id, token, tc, error, time_stamp, verif_reporter) + } } impl PusRequestRouter for GenericRequestRouter { @@ -90,4 +158,17 @@ impl PusRequestRouter for GenericRequestRouter { } Ok(()) } + fn handle_error( + &self, + target_id: satrs::TargetId, + token: satrs::pus::verification::VerificationToken< + satrs::pus::verification::TcStateAccepted, + >, + tc: &PusTcReader, + error: GenericRoutingError, + time_stamp: &[u8], + verif_reporter: &impl VerificationReportingProvider, + ) { + self.handle_error_generic(target_id, token, tc, error, time_stamp, verif_reporter) + } } diff --git a/satrs/src/mode.rs b/satrs/src/mode.rs index 3a099ce..5c83788 100644 --- a/satrs/src/mode.rs +++ b/satrs/src/mode.rs @@ -1,4 +1,5 @@ use core::mem::size_of; +use satrs_shared::res_code::ResultU16; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; use spacepackets::ByteConversionError; @@ -53,7 +54,7 @@ impl ModeAndSubmode { }) } - pub fn to_be_bytes(&self, buf: &mut [u8]) -> Result { + pub fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result { if buf.len() < Self::RAW_LEN { return Err(ByteConversionError::ToSliceTooSmall { expected: Self::RAW_LEN, @@ -114,6 +115,13 @@ pub enum ModeRequest { AnnounceModeRecursive, } +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +pub struct TargetedModeRequest { + target_id: TargetId, + mode_request: ModeRequest, +} + #[derive(Debug, Copy, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub enum ModeReply { @@ -121,20 +129,15 @@ pub enum ModeReply { ModeInfo(ModeAndSubmode), /// Reply to a mode request to confirm the commanded mode was reached. ModeReply(ModeAndSubmode), - // Can not reach the commanded mode. Returns the mode which was reached in the end. - CantReachMode(ModeAndSubmode), + // Can not reach the commanded mode. Contains a reason as a [ResultU16]. + CantReachMode(ResultU16), WrongMode { expected: ModeAndSubmode, reached: ModeAndSubmode, }, } -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -pub struct TargetedModeRequest { - target_id: TargetId, - mode_request: ModeRequest, -} +pub type GenericModeReply = GenericMessage; pub trait ModeRequestSender { fn local_channel_id(&self) -> ChannelId; @@ -146,37 +149,12 @@ pub trait ModeRequestSender { ) -> Result<(), GenericTargetedMessagingError>; } -pub trait ModeReplySender { - fn local_channel_id(&self) -> ChannelId; - - fn send_mode_reply( - &self, - request_id: RequestId, - target_id: ChannelId, - reply: ModeReply, - ) -> Result<(), GenericTargetedMessagingError>; -} - pub trait ModeRequestReceiver { fn try_recv_mode_request( &self, ) -> Result>, GenericTargetedMessagingError>; } -pub trait ModeReplyReceiver { - fn try_recv_mode_reply( - &self, - ) -> Result>, GenericTargetedMessagingError>; -} - -impl> ModeReplyReceiver for MessageReceiverWithId { - fn try_recv_mode_reply( - &self, - ) -> Result>, GenericTargetedMessagingError> { - self.try_recv_message() - } -} - impl> ModeRequestReceiver for MessageReceiverWithId { @@ -214,32 +192,46 @@ pub trait ModeRequestHandler: ModeProvider { fn handle_mode_reached(&mut self) -> Result<(), GenericTargetedMessagingError>; } +pub trait ModeReplyReceiver { + fn try_recv_mode_reply( + &self, + ) -> Result>, GenericTargetedMessagingError>; +} + +impl> ModeReplyReceiver for MessageReceiverWithId { + fn try_recv_mode_reply( + &self, + ) -> Result>, GenericTargetedMessagingError> { + self.try_recv_message() + } +} + +pub trait ModeReplySender { + fn local_channel_id(&self) -> ChannelId; + + fn send_mode_reply( + &self, + request_id: RequestId, + target_id: ChannelId, + reply: ModeReply, + ) -> Result<(), GenericTargetedMessagingError>; +} + #[cfg(feature = "alloc")] #[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))] pub mod alloc_mod { - use crate::request::{ - MessageSender, MessageSenderAndReceiver, MessageSenderMap, MessageSenderMapWithId, - RequestAndReplySenderAndReceiver, + use crate::{ + mode::ModeRequest, + queue::GenericTargetedMessagingError, + request::{ + MessageSender, MessageSenderAndReceiver, MessageSenderMap, MessageSenderMapWithId, + RequestAndReplySenderAndReceiver, RequestId, + }, + ChannelId, }; use super::*; - impl> MessageSenderMap { - pub fn send_mode_request( - &self, - request_id: RequestId, - local_id: ChannelId, - target_id: ChannelId, - request: ModeRequest, - ) -> Result<(), GenericTargetedMessagingError> { - self.send_message(request_id, local_id, target_id, request) - } - - pub fn add_request_target(&mut self, target_id: ChannelId, request_sender: S) { - self.add_message_target(target_id, request_sender) - } - } - impl> MessageSenderMap { pub fn send_mode_reply( &self, @@ -271,21 +263,6 @@ pub mod alloc_mod { } } - impl> ModeRequestSender for MessageSenderMapWithId { - fn local_channel_id(&self) -> ChannelId { - self.local_channel_id - } - - fn send_mode_request( - &self, - request_id: RequestId, - target_id: ChannelId, - request: ModeRequest, - ) -> Result<(), GenericTargetedMessagingError> { - self.send_message(request_id, target_id, request) - } - } - impl, R: MessageReceiver> ModeReplySender for MessageSenderAndReceiver { @@ -317,51 +294,6 @@ pub mod alloc_mod { self.message_receiver.try_recv_message() } } - impl, R: MessageReceiver> ModeRequestReceiver - for MessageSenderAndReceiver - { - fn try_recv_mode_request( - &self, - ) -> Result>, GenericTargetedMessagingError> { - self.message_receiver.try_recv_message() - } - } - - impl, R: MessageReceiver> ModeRequestSender - for MessageSenderAndReceiver - { - fn local_channel_id(&self) -> ChannelId { - self.local_channel_id_generic() - } - - fn send_mode_request( - &self, - request_id: RequestId, - target_id: ChannelId, - request: ModeRequest, - ) -> Result<(), GenericTargetedMessagingError> { - self.message_sender_map.send_mode_request( - request_id, - self.local_channel_id(), - target_id, - request, - ) - } - } - - impl< - REPLY, - S0: MessageSender, - R0: MessageReceiver, - S1: MessageSender, - R1: MessageReceiver, - > RequestAndReplySenderAndReceiver - { - pub fn add_request_target(&mut self, target_id: ChannelId, request_sender: S0) { - self.request_sender_map - .add_message_target(target_id, request_sender) - } - } impl< REQUEST, @@ -377,34 +309,6 @@ pub mod alloc_mod { } } - impl< - REPLY, - S0: MessageSender, - R0: MessageReceiver, - S1: MessageSender, - R1: MessageReceiver, - > ModeRequestSender - for RequestAndReplySenderAndReceiver - { - fn local_channel_id(&self) -> ChannelId { - self.local_channel_id_generic() - } - - fn send_mode_request( - &self, - request_id: RequestId, - target_id: ChannelId, - request: ModeRequest, - ) -> Result<(), GenericTargetedMessagingError> { - self.request_sender_map.send_mode_request( - request_id, - self.local_channel_id(), - target_id, - request, - ) - } - } - impl< REQUEST, S0: MessageSender, @@ -448,22 +352,6 @@ pub mod alloc_mod { } } - impl< - REPLY, - S0: MessageSender, - R0: MessageReceiver, - S1: MessageSender, - R1: MessageReceiver, - > ModeRequestReceiver - for RequestAndReplySenderAndReceiver - { - fn try_recv_mode_request( - &self, - ) -> Result>, GenericTargetedMessagingError> { - self.request_receiver.try_recv_message() - } - } - /// Helper type definition for a mode handler which can handle mode requests. pub type ModeRequestHandlerInterface = MessageSenderAndReceiver; @@ -511,6 +399,127 @@ pub mod alloc_mod { /// process mode requests. pub type ModeInterface = RequestAndReplySenderAndReceiver; + + impl> MessageSenderMap { + pub fn send_mode_request( + &self, + request_id: RequestId, + local_id: ChannelId, + target_id: ChannelId, + request: ModeRequest, + ) -> Result<(), GenericTargetedMessagingError> { + self.send_message(request_id, local_id, target_id, request) + } + + pub fn add_request_target(&mut self, target_id: ChannelId, request_sender: S) { + self.add_message_target(target_id, request_sender) + } + } + + impl> ModeRequestSender for MessageSenderMapWithId { + fn local_channel_id(&self) -> ChannelId { + self.local_channel_id + } + + fn send_mode_request( + &self, + request_id: RequestId, + target_id: ChannelId, + request: ModeRequest, + ) -> Result<(), GenericTargetedMessagingError> { + self.send_message(request_id, target_id, request) + } + } + + impl, R: MessageReceiver> ModeRequestReceiver + for MessageSenderAndReceiver + { + fn try_recv_mode_request( + &self, + ) -> Result>, GenericTargetedMessagingError> { + self.message_receiver.try_recv_message() + } + } + + impl, R: MessageReceiver> ModeRequestSender + for MessageSenderAndReceiver + { + fn local_channel_id(&self) -> ChannelId { + self.local_channel_id_generic() + } + + fn send_mode_request( + &self, + request_id: RequestId, + target_id: ChannelId, + request: ModeRequest, + ) -> Result<(), GenericTargetedMessagingError> { + self.message_sender_map.send_mode_request( + request_id, + self.local_channel_id(), + target_id, + request, + ) + } + } + + impl< + REPLY, + S0: MessageSender, + R0: MessageReceiver, + S1: MessageSender, + R1: MessageReceiver, + > RequestAndReplySenderAndReceiver + { + pub fn add_request_target(&mut self, target_id: ChannelId, request_sender: S0) { + self.request_sender_map + .add_message_target(target_id, request_sender) + } + } + + impl< + REPLY, + S0: MessageSender, + R0: MessageReceiver, + S1: MessageSender, + R1: MessageReceiver, + > ModeRequestSender + for RequestAndReplySenderAndReceiver + { + fn local_channel_id(&self) -> ChannelId { + self.local_channel_id_generic() + } + + fn send_mode_request( + &self, + request_id: RequestId, + target_id: ChannelId, + request: ModeRequest, + ) -> Result<(), GenericTargetedMessagingError> { + self.request_sender_map.send_mode_request( + request_id, + self.local_channel_id(), + target_id, + request, + ) + } + } + + impl< + REPLY, + S0: MessageSender, + R0: MessageReceiver, + S1: MessageSender, + R1: MessageReceiver, + > ModeRequestReceiver + for RequestAndReplySenderAndReceiver + { + fn try_recv_mode_request( + &self, + ) -> Result>, GenericTargetedMessagingError> { + self.request_receiver.try_recv_message() + } + } } #[cfg(feature = "std")] @@ -518,6 +527,8 @@ pub mod alloc_mod { pub mod std_mod { use std::sync::mpsc; + use crate::request::GenericMessage; + use super::*; pub type ModeRequestHandlerMpsc = ModeRequestHandlerInterface< @@ -553,115 +564,4 @@ pub mod std_mod { } #[cfg(test)] -mod tests { - use std::sync::mpsc; - - use crate::{ - mode::{ModeAndSubmode, ModeReply, ModeReplySender, ModeRequestSender}, - request::GenericMessage, - }; - - use super::{ModeRequest, ModeRequestorAndHandlerMpsc, ModeRequestorMpsc}; - - const TEST_CHANNEL_ID_0: u32 = 5; - const TEST_CHANNEL_ID_1: u32 = 6; - const TEST_CHANNEL_ID_2: u32 = 7; - - #[test] - fn test_simple_mode_requestor() { - let (reply_sender, reply_receiver) = mpsc::channel(); - let (request_sender, request_receiver) = mpsc::channel(); - let mut mode_requestor = ModeRequestorMpsc::new(TEST_CHANNEL_ID_0, reply_receiver); - mode_requestor.add_message_target(TEST_CHANNEL_ID_1, request_sender); - - // Send a request and verify it arrives at the receiver. - let request_id = 2; - let sent_request = ModeRequest::ReadMode; - mode_requestor - .send_mode_request(request_id, TEST_CHANNEL_ID_1, sent_request) - .expect("send failed"); - let request = request_receiver.recv().expect("recv failed"); - assert_eq!(request.request_id, 2); - assert_eq!(request.sender_id, TEST_CHANNEL_ID_0); - assert_eq!(request.message, sent_request); - - // Send a reply and verify it arrives at the requestor. - let mode_reply = ModeReply::ModeReply(ModeAndSubmode::new(1, 5)); - reply_sender - .send(GenericMessage::new( - request_id, - TEST_CHANNEL_ID_1, - mode_reply, - )) - .expect("send failed"); - let reply = mode_requestor.try_recv_mode_reply().expect("recv failed"); - assert!(reply.is_some()); - let reply = reply.unwrap(); - assert_eq!(reply.sender_id, TEST_CHANNEL_ID_1); - assert_eq!(reply.request_id, 2); - assert_eq!(reply.message, mode_reply); - } - - #[test] - fn test_mode_requestor_and_request_handler_request_sending() { - let (_reply_sender_to_connector, reply_receiver_of_connector) = mpsc::channel(); - let (_request_sender_to_connector, request_receiver_of_connector) = mpsc::channel(); - - let (request_sender_to_channel_1, request_receiver_channel_1) = mpsc::channel(); - //let (reply_sender_to_channel_2, reply_receiver_channel_2) = mpsc::channel(); - let mut mode_connector = ModeRequestorAndHandlerMpsc::new( - TEST_CHANNEL_ID_0, - request_receiver_of_connector, - reply_receiver_of_connector, - ); - assert_eq!( - ModeRequestSender::local_channel_id(&mode_connector), - TEST_CHANNEL_ID_0 - ); - assert_eq!( - ModeReplySender::local_channel_id(&mode_connector), - TEST_CHANNEL_ID_0 - ); - assert_eq!(mode_connector.local_channel_id_generic(), TEST_CHANNEL_ID_0); - - mode_connector.add_request_target(TEST_CHANNEL_ID_1, request_sender_to_channel_1); - //mode_connector.add_reply_target(TEST_CHANNEL_ID_2, reply_sender_to_channel_2); - - // Send a request and verify it arrives at the receiver. - let request_id = 2; - let sent_request = ModeRequest::ReadMode; - mode_connector - .send_mode_request(request_id, TEST_CHANNEL_ID_1, sent_request) - .expect("send failed"); - - let request = request_receiver_channel_1.recv().expect("recv failed"); - assert_eq!(request.request_id, 2); - assert_eq!(request.sender_id, TEST_CHANNEL_ID_0); - assert_eq!(request.message, ModeRequest::ReadMode); - } - - #[test] - fn test_mode_requestor_and_request_handler_reply_sending() { - let (_reply_sender_to_connector, reply_receiver_of_connector) = mpsc::channel(); - let (_request_sender_to_connector, request_receiver_of_connector) = mpsc::channel(); - - let (reply_sender_to_channel_2, reply_receiver_channel_2) = mpsc::channel(); - let mut mode_connector = ModeRequestorAndHandlerMpsc::new( - TEST_CHANNEL_ID_0, - request_receiver_of_connector, - reply_receiver_of_connector, - ); - mode_connector.add_reply_target(TEST_CHANNEL_ID_2, reply_sender_to_channel_2); - - // Send a request and verify it arrives at the receiver. - let request_id = 2; - let sent_reply = ModeReply::ModeInfo(ModeAndSubmode::new(3, 5)); - mode_connector - .send_mode_reply(request_id, TEST_CHANNEL_ID_2, sent_reply) - .expect("send failed"); - let reply = reply_receiver_channel_2.recv().expect("recv failed"); - assert_eq!(reply.request_id, 2); - assert_eq!(reply.sender_id, TEST_CHANNEL_ID_0); - assert_eq!(reply.message, sent_reply); - } -} +mod tests {} diff --git a/satrs/src/pus/action.rs b/satrs/src/pus/action.rs index 85d3dbd..881274c 100644 --- a/satrs/src/pus/action.rs +++ b/satrs/src/pus/action.rs @@ -122,7 +122,6 @@ pub mod std_mod { VerificationReporter, RequestConverter, RequestRouter, - RoutingErrorHandler, RoutingError = GenericRoutingError, > = PusTargetedRequestHandler< TcReceiver, @@ -131,7 +130,6 @@ pub mod std_mod { VerificationReporter, RequestConverter, RequestRouter, - RoutingErrorHandler, ActionRequest, RoutingError, >; @@ -326,7 +324,7 @@ mod tests { pus::{ tests::{ PusServiceHandlerWithVecCommon, PusTestHarness, SimplePusPacketHandler, - TestConverter, TestRouter, TestRoutingErrorHandler, APP_DATA_TOO_SHORT, TEST_APID, + TestConverter, TestRouter, APP_DATA_TOO_SHORT, TEST_APID, }, verification::{ self, @@ -356,6 +354,20 @@ mod tests { .push_back((target_id, request)); self.check_for_injected_error() } + + fn handle_error( + &self, + target_id: TargetId, + token: VerificationToken, + tc: &PusTcReader, + error: Self::Error, + time_stamp: &[u8], + verif_reporter: &impl VerificationReportingProvider, + ) { + self.routing_errors + .borrow_mut() + .push_back((target_id, error)); + } } impl PusTcToRequestConverter for TestConverter<8> { @@ -413,7 +425,6 @@ mod tests { TestVerificationReporter, TestConverter<8>, TestRouter, - TestRoutingErrorHandler, >, } @@ -427,7 +438,6 @@ mod tests { srv_handler, TestConverter::default(), TestRouter::default(), - TestRoutingErrorHandler::default(), ), } } @@ -443,8 +453,8 @@ mod tests { } } delegate! { - to self.handler.routing_error_handler { - pub fn retrieve_next_error(&mut self) -> (TargetId, GenericRoutingError); + to self.handler.request_router { + pub fn retrieve_next_routing_error(&mut self) -> (TargetId, GenericRoutingError); } } } @@ -714,7 +724,7 @@ mod tests { assert_eq!(data, &[]); } - let (target_id, found_error) = action_handler.retrieve_next_error(); + let (target_id, found_error) = action_handler.retrieve_next_routing_error(); assert_eq!(target_id, TEST_APID.into()); check_error(found_error); } diff --git a/satrs/src/pus/hk.rs b/satrs/src/pus/hk.rs index 852e8f7..b44c3d2 100644 --- a/satrs/src/pus/hk.rs +++ b/satrs/src/pus/hk.rs @@ -6,6 +6,7 @@ pub use std_mod::*; #[cfg(feature = "alloc")] #[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))] +#[allow(unused_imports)] pub use alloc_mod::*; use crate::{hk::HkRequest, TargetId}; @@ -26,158 +27,33 @@ pub trait PusHkRequestRouter { #[cfg(feature = "alloc")] #[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))] -pub mod alloc_mod { - use spacepackets::ecss::tc::PusTcReader; - - use crate::pus::verification::VerificationReportingProvider; - - use super::*; - - /// This trait is an abstraction for the conversion of a PUS service 8 action telecommand into - /// a [HkRequest]. - /// - /// Having a dedicated trait for this allows maximum flexiblity and tailoring of the standard. - /// The only requirement is that a valid [TargetId] and a [HkRequest] are returned by the - /// core conversion function. - /// - /// The user should take care of performing the error handling as well. Some of the following - /// aspects might be relevant: - /// - /// - Checking the validity of the APID, service ID, subservice ID. - /// - Checking the validity of the user data. - /// - /// A [VerificationReportingProvider] is passed to the user to also allow handling - /// of the verification process as part of the PUS standard requirements. - pub trait PusHkToRequestConverter { - type Error; - fn convert( - &mut self, - token: VerificationToken, - tc: &PusTcReader, - time_stamp: &[u8], - verif_reporter: &impl VerificationReportingProvider, - ) -> Result<(TargetId, HkRequest), Self::Error>; - } -} +pub mod alloc_mod {} #[cfg(feature = "std")] #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] pub mod std_mod { - use crate::pus::{ - get_current_cds_short_timestamp, verification::VerificationReportingProvider, - EcssTcInMemConverter, EcssTcReceiverCore, EcssTmSenderCore, GenericRoutingError, - PusPacketHandlerResult, PusPacketHandlingError, PusRoutingErrorHandler, PusServiceHelper, - }; + use crate::pus::{GenericRoutingError, PusTargetedRequestHandler}; use super::*; - /// This is a generic high-level handler for the PUS service 3 housekeeping service. - /// - /// It performs the following handling steps: - /// - /// 1. Retrieve the next TC packet from the [PusServiceHelper]. The [EcssTcInMemConverter] - /// allows to configure the used telecommand memory backend. - /// 2. Convert the TC to a targeted action request using the provided - /// [PusHkToRequestConverter]. The generic error type is constrained to the - /// [PusPacketHandlerResult] for the concrete implementation which offers a packet handler. - /// 3. Route the action request using the provided [PusHkRequestRouter]. The generic error - /// type is constrained to the [GenericRoutingError] for the concrete implementation. - /// 4. Handle all routing errors using the provided [PusRoutingErrorHandler]. The generic error - /// type is constrained to the [GenericRoutingError] for the concrete implementation. - pub struct PusService3HkHandler< - TcReceiver: EcssTcReceiverCore, - TmSender: EcssTmSenderCore, - TcInMemConverter: EcssTcInMemConverter, - VerificationReporter: VerificationReportingProvider, - RequestConverter: PusHkToRequestConverter, - RequestRouter: PusHkRequestRouter, - RoutingErrorHandler: PusRoutingErrorHandler, + pub type PusService3HkRequestHandler< + TcReceiver, + TmSender, + TcInMemConverter, + VerificationReporter, + RequestConverter, + RequestRouter, RoutingError = GenericRoutingError, - > { - service_helper: - PusServiceHelper, - pub request_converter: RequestConverter, - pub request_router: RequestRouter, - pub routing_error_handler: RoutingErrorHandler, - } - - impl< - TcReceiver: EcssTcReceiverCore, - TmSender: EcssTmSenderCore, - TcInMemConverter: EcssTcInMemConverter, - VerificationReporter: VerificationReportingProvider, - RequestConverter: PusHkToRequestConverter, - RequestRouter: PusHkRequestRouter, - RoutingErrorHandler: PusRoutingErrorHandler, - RoutingError: Clone, - > - PusService3HkHandler< - TcReceiver, - TmSender, - TcInMemConverter, - VerificationReporter, - RequestConverter, - RequestRouter, - RoutingErrorHandler, - RoutingError, - > - where - PusPacketHandlingError: From, - { - pub fn new( - service_helper: PusServiceHelper< - TcReceiver, - TmSender, - TcInMemConverter, - VerificationReporter, - >, - request_converter: RequestConverter, - request_router: RequestRouter, - routing_error_handler: RoutingErrorHandler, - ) -> Self { - Self { - service_helper, - request_converter, - request_router, - routing_error_handler, - } - } - - pub fn handle_one_tc(&mut self) -> Result { - let possible_packet = self.service_helper.retrieve_and_accept_next_packet()?; - if possible_packet.is_none() { - return Ok(PusPacketHandlerResult::Empty); - } - let ecss_tc_and_token = possible_packet.unwrap(); - let tc = self - .service_helper - .tc_in_mem_converter - .convert_ecss_tc_in_memory_to_reader(&ecss_tc_and_token.tc_in_memory)?; - let mut partial_error = None; - let time_stamp = get_current_cds_short_timestamp(&mut partial_error); - let (target_id, hk_request) = self.request_converter.convert( - ecss_tc_and_token.token, - &tc, - &time_stamp, - &self.service_helper.common.verification_handler, - )?; - if let Err(e) = - self.request_router - .route(target_id, hk_request, ecss_tc_and_token.token) - { - self.routing_error_handler.handle_error( - target_id, - ecss_tc_and_token.token, - &tc, - e.clone(), - &time_stamp, - &self.service_helper.common.verification_handler, - ); - return Err(e.into()); - } - Ok(PusPacketHandlerResult::RequestHandled) - } - } + > = PusTargetedRequestHandler< + TcReceiver, + TmSender, + TcInMemConverter, + VerificationReporter, + RequestConverter, + RequestRouter, + HkRequest, + RoutingError, + >; } #[cfg(test)] @@ -194,13 +70,13 @@ mod tests { CcsdsPacket, SequenceFlags, SpHeader, }; - use crate::pus::{MpscTcReceiver, TmAsVecSenderWithMpsc}; + use crate::pus::{MpscTcReceiver, PusTcToRequestConverter, TmAsVecSenderWithMpsc}; use crate::{ hk::HkRequest, pus::{ tests::{ PusServiceHandlerWithVecCommon, PusTestHarness, SimplePusPacketHandler, - TestConverter, TestRouter, TestRoutingErrorHandler, APP_DATA_TOO_SHORT, TEST_APID, + TestConverter, TestRouter, APP_DATA_TOO_SHORT, TEST_APID, }, verification::{ tests::TestVerificationReporter, FailParams, RequestId, TcStateAccepted, @@ -212,7 +88,7 @@ mod tests { TargetId, }; - use super::{PusHkRequestRouter, PusHkToRequestConverter, PusService3HkHandler}; + use super::{PusHkRequestRouter, PusService3HkRequestHandler}; impl PusHkRequestRouter for TestRouter { type Error = GenericRoutingError; @@ -230,7 +106,7 @@ mod tests { } } - impl PusHkToRequestConverter for TestConverter<3> { + impl PusTcToRequestConverter for TestConverter<3> { type Error = PusPacketHandlingError; fn convert( &mut self, @@ -277,14 +153,13 @@ mod tests { struct Pus3HandlerWithVecTester { common: PusServiceHandlerWithVecCommon, - handler: PusService3HkHandler< + handler: PusService3HkRequestHandler< MpscTcReceiver, TmAsVecSenderWithMpsc, EcssTcInVecConverter, TestVerificationReporter, TestConverter<3>, TestRouter, - TestRoutingErrorHandler, >, } @@ -294,11 +169,10 @@ mod tests { PusServiceHandlerWithVecCommon::new_with_test_verif_sender(); Self { common, - handler: PusService3HkHandler::new( + handler: PusService3HkRequestHandler::new( srv_handler, TestConverter::default(), TestRouter::default(), - TestRoutingErrorHandler::default(), ), } } @@ -314,8 +188,8 @@ mod tests { } } delegate! { - to self.handler.routing_error_handler { - pub fn retrieve_next_error(&mut self) -> (TargetId, GenericRoutingError); + to self.handler.request_router { + pub fn retrieve_next_routing_error(&mut self) -> (TargetId, GenericRoutingError); } } } @@ -399,7 +273,7 @@ mod tests { assert_eq!(unique_id, 1); } - let (target_id, found_error) = hk_handler.retrieve_next_error(); + let (target_id, found_error) = hk_handler.retrieve_next_routing_error(); assert_eq!(target_id, TEST_APID.into()); check_error(found_error); } diff --git a/satrs/src/pus/mod.rs b/satrs/src/pus/mod.rs index 037dbce..5479951 100644 --- a/satrs/src/pus/mod.rs +++ b/satrs/src/pus/mod.rs @@ -44,7 +44,7 @@ pub use alloc_mod::*; #[cfg(feature = "std")] pub use std_mod::*; -use self::verification::{FailParams, TcStateStarted}; +use self::verification::{FailParams, TcStateStarted, VerificationReportingProvider}; #[derive(Debug, PartialEq, Eq, Clone)] pub enum PusTmWrapper<'tm> { @@ -347,6 +347,15 @@ pub trait PusRequestRouter { hk_request: Request, token: VerificationToken, ) -> Result<(), Self::Error>; + fn handle_error( + &self, + target_id: TargetId, + token: VerificationToken, + tc: &PusTcReader, + error: Self::Error, + time_stamp: &[u8], + verif_reporter: &impl VerificationReportingProvider, + ); } #[cfg(feature = "alloc")] @@ -465,19 +474,6 @@ pub mod alloc_mod { ) -> Result<(TargetId, Request), Self::Error>; } - pub trait PusRoutingErrorHandler { - type Error; - fn handle_error( - &self, - target_id: TargetId, - token: VerificationToken, - tc: &PusTcReader, - error: Self::Error, - time_stamp: &[u8], - verif_reporter: &impl VerificationReportingProvider, - ); - } - #[derive(Clone, Debug)] pub struct DefaultActiveRequestMap(pub HashMap); @@ -704,10 +700,7 @@ pub mod std_mod { pub use cb_mod::*; use super::verification::VerificationReportingProvider; - use super::{ - AcceptedEcssTcAndToken, PusRequestRouter, PusRoutingErrorHandler, PusTcToRequestConverter, - TcInMemory, - }; + use super::{AcceptedEcssTcAndToken, PusRequestRouter, PusTcToRequestConverter, TcInMemory}; impl From> for EcssTmtcError { fn from(_: mpsc::SendError) -> Self { @@ -999,7 +992,6 @@ pub mod std_mod { VerificationReporter: VerificationReportingProvider, RequestConverter: PusTcToRequestConverter, RequestRouter: PusRequestRouter, - RoutingErrorHandler: PusRoutingErrorHandler, Request, RoutingError = GenericRoutingError, > { @@ -1007,7 +999,7 @@ pub mod std_mod { PusServiceHelper, pub request_converter: RequestConverter, pub request_router: RequestRouter, - pub routing_error_handler: RoutingErrorHandler, + // pub routing_error_handler: RoutingErrorHandler, phantom: PhantomData, } @@ -1018,7 +1010,7 @@ pub mod std_mod { VerificationReporter: VerificationReportingProvider, RequestConverter: PusTcToRequestConverter, RequestRouter: PusRequestRouter, - RoutingErrorHandler: PusRoutingErrorHandler, + // RoutingErrorHandler: PusRoutingErrorHandler, Request, RoutingError: Clone, > @@ -1029,7 +1021,7 @@ pub mod std_mod { VerificationReporter, RequestConverter, RequestRouter, - RoutingErrorHandler, + // RoutingErrorHandler, Request, RoutingError, > @@ -1045,13 +1037,12 @@ pub mod std_mod { >, request_converter: RequestConverter, request_router: RequestRouter, - routing_error_handler: RoutingErrorHandler, ) -> Self { Self { service_helper, request_converter, request_router, - routing_error_handler, + // routing_error_handler, phantom: PhantomData, } } @@ -1079,7 +1070,7 @@ pub mod std_mod { self.request_router .route(target_id, action_request, ecss_tc_and_token.token) { - self.routing_error_handler.handle_error( + self.request_router.handle_error( target_id, ecss_tc_and_token.token, &tc, @@ -1451,8 +1442,8 @@ pub mod tests { }; use super::{ EcssTcAndToken, EcssTcInSharedStoreConverter, EcssTcInVecConverter, GenericRoutingError, - MpscTcReceiver, PusPacketHandlerResult, PusPacketHandlingError, PusRoutingErrorHandler, - PusServiceHelper, TcInMemory, TmAsVecSenderWithId, TmAsVecSenderWithMpsc, + MpscTcReceiver, PusPacketHandlerResult, PusPacketHandlingError, PusServiceHelper, + TcInMemory, TmAsVecSenderWithId, TmAsVecSenderWithMpsc, TmInSharedPoolSenderWithBoundedMpsc, TmInSharedPoolSenderWithId, }; @@ -1766,44 +1757,9 @@ pub mod tests { } } - #[derive(Default)] - pub struct TestRoutingErrorHandler { - pub routing_errors: RefCell>, - } - - impl PusRoutingErrorHandler for TestRoutingErrorHandler { - type Error = GenericRoutingError; - - fn handle_error( - &self, - target_id: TargetId, - _token: VerificationToken, - _tc: &PusTcReader, - error: Self::Error, - _time_stamp: &[u8], - _verif_reporter: &impl VerificationReportingProvider, - ) { - self.routing_errors - .borrow_mut() - .push_back((target_id, error)); - } - } - - impl TestRoutingErrorHandler { - pub fn is_empty(&self) -> bool { - self.routing_errors.borrow().is_empty() - } - - pub fn retrieve_next_error(&mut self) -> (TargetId, GenericRoutingError) { - if self.routing_errors.borrow().is_empty() { - panic!("no routing request available"); - } - self.routing_errors.borrow_mut().pop_front().unwrap() - } - } - pub struct TestRouter { pub routing_requests: RefCell>, + pub routing_errors: RefCell>, pub injected_routing_failure: RefCell>, } @@ -1811,6 +1767,7 @@ pub mod tests { fn default() -> Self { Self { routing_requests: Default::default(), + routing_errors: Default::default(), injected_routing_failure: Default::default(), } } @@ -1824,6 +1781,31 @@ pub mod tests { Ok(()) } + pub fn handle_error( + &self, + target_id: TargetId, + _token: VerificationToken, + _tc: &PusTcReader, + error: GenericRoutingError, + _time_stamp: &[u8], + _verif_reporter: &impl VerificationReportingProvider, + ) { + self.routing_errors + .borrow_mut() + .push_back((target_id, error)); + } + + pub fn no_routing_errors(&self) -> bool { + self.routing_errors.borrow().is_empty() + } + + pub fn retrieve_next_routing_error(&mut self) -> (TargetId, GenericRoutingError) { + if self.routing_errors.borrow().is_empty() { + panic!("no routing request available"); + } + self.routing_errors.borrow_mut().pop_front().unwrap() + } + pub fn inject_routing_error(&mut self, error: GenericRoutingError) { *self.injected_routing_failure.borrow_mut() = Some(error); } diff --git a/satrs/src/pus/mode.rs b/satrs/src/pus/mode.rs index 8d1f4ab..b5bbb85 100644 --- a/satrs/src/pus/mode.rs +++ b/satrs/src/pus/mode.rs @@ -2,7 +2,14 @@ use num_enum::{IntoPrimitive, TryFromPrimitive}; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; -use crate::{mode::ModeReply, request::GenericMessage}; +use crate::mode::ModeReply; + +#[cfg(feature = "alloc")] +#[allow(unused_imports)] +pub use alloc_mod::*; + +#[cfg(feature = "std")] +pub use std_mod::*; pub const MODE_SERVICE_ID: u8 = 200; @@ -19,8 +26,6 @@ pub enum Subservice { TmWrongModeReply = 8, } -pub type GenericModeReplyPus = GenericMessage; - #[cfg(feature = "alloc")] #[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))] pub mod alloc_mod {} @@ -33,11 +38,12 @@ pub mod std_mod { use satrs_shared::res_code::ResultU16; use spacepackets::{ ecss::tm::{PusTmCreator, PusTmSecondaryHeader}, + util::UnsignedEnum, SpHeader, }; use crate::{ - mode::{ModeReply, ModeRequest}, + mode::{GenericModeReply, ModeRequest}, pus::{ mode::Subservice, verification::{ @@ -55,7 +61,7 @@ pub mod std_mod { fn can_not_reach_mode_result_code(&self) -> ResultU16; } - use super::{GenericModeReplyPus, MODE_SERVICE_ID}; + use super::{ModeReply, MODE_SERVICE_ID}; pub type PusModeServiceRequestHandler< TcReceiver, @@ -64,7 +70,6 @@ pub mod std_mod { VerificationReporter, RequestConverter, RequestRouter, - RoutingErrorHandler, RoutingError = GenericRoutingError, > = PusTargetedRequestHandler< TcReceiver, @@ -73,7 +78,6 @@ pub mod std_mod { VerificationReporter, RequestConverter, RequestRouter, - RoutingErrorHandler, ModeRequest, RoutingError, >; @@ -124,7 +128,7 @@ pub mod std_mod { /// Main handler function to handle all received action replies. pub fn handle_mode_reply( &mut self, - mode_reply_with_id: &GenericModeReplyPus, + mode_reply_with_id: &GenericModeReply, time_stamp: &[u8], ) -> Result<(), EcssTmtcError> { let active_req = self.active_request_map.get(mode_reply_with_id.request_id); @@ -135,6 +139,7 @@ pub mod std_mod { let active_req = active_req.unwrap().clone(); let remove_entry = match mode_reply_with_id.message { ModeReply::ModeReply(reply) => { + reply.write_to_be_bytes(&mut self.tm_buf)?; let req_id = verification::RequestId::from(mode_reply_with_id.request_id); let mut sp_header = SpHeader::tm_unseg( req_id.packet_id().apid(), @@ -149,16 +154,15 @@ pub mod std_mod { 0, Some(time_stamp), ); - let pus_tm = - PusTmCreator::new(&mut sp_header, sec_header, &mut self.tm_buf, true); + let pus_tm = PusTmCreator::new(&mut sp_header, sec_header, &self.tm_buf, true); self.tm_sender.send_tm(PusTmWrapper::Direct(pus_tm))?; self.verification_reporter .completion_success(active_req.token, time_stamp) .map_err(|e| e.0)?; true } - ModeReply::CantReachMode(reached_mode) => { - let fail_data_len = reached_mode.to_be_bytes(&mut self.tm_buf)?; + ModeReply::CantReachMode(reason) => { + let fail_data_len = reason.write_to_be_bytes(&mut self.tm_buf)?; self.verification_reporter .completion_failure( active_req.token, @@ -172,9 +176,19 @@ pub mod std_mod { true } ModeReply::WrongMode { expected, reached } => { - // TODO: Generate completion failure with appropriate result code and reached - // mode as context information. - // self.verification_reporter.completion_success(active_req.token, time_stamp); + let expected_len = expected.write_to_be_bytes(&mut self.tm_buf)?; + let reached_len = + reached.write_to_be_bytes(&mut self.tm_buf[expected_len..])?; + self.verification_reporter + .completion_failure( + active_req.token, + FailParams::new( + time_stamp, + &self.user_hook.can_not_reach_mode_result_code(), + &self.tm_buf[0..expected_len + reached_len], + ), + ) + .map_err(|e| e.0)?; true } _ => true, @@ -187,3 +201,122 @@ pub mod std_mod { } } } + +#[cfg(test)] +mod tests { + + use std::sync::mpsc; + + use crate::{ + mode::{ + ModeAndSubmode, ModeReplySender, ModeRequest, ModeRequestSender, + ModeRequestorAndHandlerMpsc, ModeRequestorMpsc, + }, + pus::mode::ModeReply, + request::GenericMessage, + }; + + const TEST_CHANNEL_ID_0: u32 = 5; + const TEST_CHANNEL_ID_1: u32 = 6; + const TEST_CHANNEL_ID_2: u32 = 7; + + #[test] + fn test_simple_mode_requestor() { + let (reply_sender, reply_receiver) = mpsc::channel(); + let (request_sender, request_receiver) = mpsc::channel(); + let mut mode_requestor = ModeRequestorMpsc::new(TEST_CHANNEL_ID_0, reply_receiver); + mode_requestor.add_message_target(TEST_CHANNEL_ID_1, request_sender); + + // Send a request and verify it arrives at the receiver. + let request_id = 2; + let sent_request = ModeRequest::ReadMode; + mode_requestor + .send_mode_request(request_id, TEST_CHANNEL_ID_1, sent_request) + .expect("send failed"); + let request = request_receiver.recv().expect("recv failed"); + assert_eq!(request.request_id, 2); + assert_eq!(request.sender_id, TEST_CHANNEL_ID_0); + assert_eq!(request.message, sent_request); + + // Send a reply and verify it arrives at the requestor. + let mode_reply = ModeReply::ModeReply(ModeAndSubmode::new(1, 5)); + reply_sender + .send(GenericMessage::new( + request_id, + TEST_CHANNEL_ID_1, + mode_reply, + )) + .expect("send failed"); + let reply = mode_requestor.try_recv_mode_reply().expect("recv failed"); + assert!(reply.is_some()); + let reply = reply.unwrap(); + assert_eq!(reply.sender_id, TEST_CHANNEL_ID_1); + assert_eq!(reply.request_id, 2); + assert_eq!(reply.message, mode_reply); + } + + #[test] + fn test_mode_requestor_and_request_handler_request_sending() { + let (_reply_sender_to_connector, reply_receiver_of_connector) = mpsc::channel(); + let (_request_sender_to_connector, request_receiver_of_connector) = mpsc::channel(); + + let (request_sender_to_channel_1, request_receiver_channel_1) = mpsc::channel(); + //let (reply_sender_to_channel_2, reply_receiver_channel_2) = mpsc::channel(); + let mut mode_connector = ModeRequestorAndHandlerMpsc::new( + TEST_CHANNEL_ID_0, + request_receiver_of_connector, + reply_receiver_of_connector, + ); + assert_eq!( + ModeRequestSender::local_channel_id(&mode_connector), + TEST_CHANNEL_ID_0 + ); + assert_eq!( + ModeReplySender::local_channel_id(&mode_connector), + TEST_CHANNEL_ID_0 + ); + assert_eq!(mode_connector.local_channel_id_generic(), TEST_CHANNEL_ID_0); + + mode_connector.add_request_target(TEST_CHANNEL_ID_1, request_sender_to_channel_1); + + // Send a request and verify it arrives at the receiver. + let request_id = 2; + let sent_request = ModeRequest::ReadMode; + mode_connector + .send_mode_request(request_id, TEST_CHANNEL_ID_1, sent_request) + .expect("send failed"); + + let request = request_receiver_channel_1.recv().expect("recv failed"); + assert_eq!(request.request_id, 2); + assert_eq!(request.sender_id, TEST_CHANNEL_ID_0); + assert_eq!(request.message, ModeRequest::ReadMode); + } + + #[test] + fn test_mode_requestor_and_request_handler_reply_sending() { + let (_reply_sender_to_connector, reply_receiver_of_connector) = mpsc::channel(); + let (_request_sender_to_connector, request_receiver_of_connector) = mpsc::channel(); + + let (reply_sender_to_channel_2, reply_receiver_channel_2) = mpsc::channel(); + let mut mode_connector = ModeRequestorAndHandlerMpsc::new( + TEST_CHANNEL_ID_0, + request_receiver_of_connector, + reply_receiver_of_connector, + ); + mode_connector.add_reply_target(TEST_CHANNEL_ID_2, reply_sender_to_channel_2); + + // Send a request and verify it arrives at the receiver. + let request_id = 2; + let sent_reply = ModeReply::ModeInfo(ModeAndSubmode::new(3, 5)); + mode_connector + .send_mode_reply(request_id, TEST_CHANNEL_ID_2, sent_reply) + .expect("send failed"); + let reply = reply_receiver_channel_2.recv().expect("recv failed"); + assert_eq!(reply.request_id, 2); + assert_eq!(reply.sender_id, TEST_CHANNEL_ID_0); + assert_eq!(reply.message, sent_reply); + } + + #[test] + fn test_mode_reply_handler() {} +}