Re-worked TMTC modules
All checks were successful
Rust/sat-rs/pipeline/pr-main This commit looks good
All checks were successful
Rust/sat-rs/pipeline/pr-main This commit looks good
This commit is contained in:
@ -195,610 +195,7 @@ pub mod std_mod {
|
||||
mpsc::SyncSender<GenericMessage<ActionRequest>>,
|
||||
mpsc::Receiver<GenericMessage<ActionReplyPus>>,
|
||||
>;
|
||||
|
||||
/*
|
||||
pub type ModeRequestorAndHandlerMpsc = ModeInterface<
|
||||
mpsc::Sender<GenericMessage<ModeRequest>>,
|
||||
mpsc::Receiver<GenericMessage<ModeReply>>,
|
||||
mpsc::Sender<GenericMessage<ModeReply>>,
|
||||
mpsc::Receiver<GenericMessage<ModeRequest>>,
|
||||
>;
|
||||
pub type ModeRequestorAndHandlerMpscBounded = ModeInterface<
|
||||
mpsc::SyncSender<GenericMessage<ModeRequest>>,
|
||||
mpsc::Receiver<GenericMessage<ModeReply>>,
|
||||
mpsc::SyncSender<GenericMessage<ModeReply>>,
|
||||
mpsc::Receiver<GenericMessage<ModeRequest>>,
|
||||
>;
|
||||
*/
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
/*
|
||||
use core::{cell::RefCell, time::Duration};
|
||||
use std::{sync::mpsc, time::SystemTimeError};
|
||||
|
||||
use alloc::{collections::VecDeque, vec::Vec};
|
||||
use delegate::delegate;
|
||||
|
||||
use spacepackets::{
|
||||
ecss::{
|
||||
tc::{PusTcCreator, PusTcReader},
|
||||
tm::PusTmReader,
|
||||
PusPacket,
|
||||
},
|
||||
time::{cds, TimeWriter},
|
||||
CcsdsPacket,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
action::ActionRequestVariant,
|
||||
params::{self, ParamsRaw, WritableToBeBytes},
|
||||
pus::{
|
||||
tests::{
|
||||
PusServiceHandlerWithVecCommon, PusTestHarness, SimplePusPacketHandler,
|
||||
TestConverter, TestRouter, APP_DATA_TOO_SHORT,
|
||||
},
|
||||
verification::{
|
||||
self,
|
||||
tests::{SharedVerificationMap, TestVerificationReporter, VerificationStatus},
|
||||
FailParams, TcStateAccepted, TcStateNone, TcStateStarted,
|
||||
VerificationReportingProvider,
|
||||
},
|
||||
EcssTcInMemConverter, EcssTcInVecConverter, EcssTmtcError, GenericRoutingError,
|
||||
MpscTcReceiver, PusPacketHandlerResult, PusPacketHandlingError, PusRequestRouter,
|
||||
PusServiceHelper, PusTcToRequestConverter, TmAsVecSenderWithMpsc,
|
||||
},
|
||||
};
|
||||
|
||||
use super::*;
|
||||
|
||||
impl<Request> PusRequestRouter<Request> for TestRouter<Request> {
|
||||
type Error = GenericRoutingError;
|
||||
|
||||
fn route(
|
||||
&self,
|
||||
target_id: TargetId,
|
||||
request: Request,
|
||||
_token: VerificationToken<TcStateAccepted>,
|
||||
) -> Result<(), Self::Error> {
|
||||
self.routing_requests
|
||||
.borrow_mut()
|
||||
.push_back((target_id, request));
|
||||
self.check_for_injected_error()
|
||||
}
|
||||
|
||||
fn handle_error(
|
||||
&self,
|
||||
target_id: TargetId,
|
||||
token: VerificationToken<TcStateAccepted>,
|
||||
tc: &PusTcReader,
|
||||
error: Self::Error,
|
||||
time_stamp: &[u8],
|
||||
verif_reporter: &impl VerificationReportingProvider,
|
||||
) {
|
||||
self.routing_errors
|
||||
.borrow_mut()
|
||||
.push_back((target_id, error));
|
||||
}
|
||||
}
|
||||
|
||||
impl PusTcToRequestConverter<ActionRequest> for TestConverter<8> {
|
||||
type Error = PusPacketHandlingError;
|
||||
fn convert(
|
||||
&mut self,
|
||||
token: VerificationToken<TcStateAccepted>,
|
||||
tc: &PusTcReader,
|
||||
time_stamp: &[u8],
|
||||
verif_reporter: &impl VerificationReportingProvider,
|
||||
) -> Result<(TargetId, ActionRequest), Self::Error> {
|
||||
self.conversion_request.push_back(tc.raw_data().to_vec());
|
||||
self.check_service(tc)?;
|
||||
let target_id = tc.apid();
|
||||
if tc.user_data().len() < 4 {
|
||||
verif_reporter
|
||||
.start_failure(
|
||||
token,
|
||||
FailParams::new(
|
||||
time_stamp,
|
||||
&APP_DATA_TOO_SHORT,
|
||||
(tc.user_data().len() as u32).to_be_bytes().as_ref(),
|
||||
),
|
||||
)
|
||||
.expect("start success failure");
|
||||
return Err(PusPacketHandlingError::NotEnoughAppData {
|
||||
expected: 4,
|
||||
found: tc.user_data().len(),
|
||||
});
|
||||
}
|
||||
if tc.subservice() == 1 {
|
||||
verif_reporter
|
||||
.start_success(token, time_stamp)
|
||||
.expect("start success failure");
|
||||
return Ok((
|
||||
target_id.into(),
|
||||
ActionRequest {
|
||||
action_id: u32::from_be_bytes(tc.user_data()[0..4].try_into().unwrap()),
|
||||
variant: ActionRequestVariant::VecData(tc.user_data()[4..].to_vec()),
|
||||
},
|
||||
));
|
||||
}
|
||||
Err(PusPacketHandlingError::InvalidAppData(
|
||||
"unexpected app data".into(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PusDynRequestHandler<const SERVICE: u8, Request> {
|
||||
srv_helper: PusServiceHelper<
|
||||
MpscTcReceiver,
|
||||
TmAsVecSenderWithMpsc,
|
||||
EcssTcInVecConverter,
|
||||
TestVerificationReporter,
|
||||
>,
|
||||
request_converter: TestConverter<SERVICE>,
|
||||
request_router: TestRouter<Request>,
|
||||
}
|
||||
|
||||
struct Pus8RequestTestbenchWithVec {
|
||||
common: PusServiceHandlerWithVecCommon<TestVerificationReporter>,
|
||||
handler: PusDynRequestHandler<8, ActionRequest>,
|
||||
}
|
||||
|
||||
impl Pus8RequestTestbenchWithVec {
|
||||
pub fn new() -> Self {
|
||||
let (common, srv_helper) = PusServiceHandlerWithVecCommon::new_with_test_verif_sender();
|
||||
Self {
|
||||
common,
|
||||
handler: PusDynRequestHandler {
|
||||
srv_helper,
|
||||
request_converter: TestConverter::default(),
|
||||
request_router: TestRouter::default(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
delegate! {
|
||||
to self.handler.request_converter {
|
||||
pub fn check_next_conversion(&mut self, tc: &PusTcCreator);
|
||||
}
|
||||
}
|
||||
delegate! {
|
||||
to self.handler.request_router {
|
||||
pub fn retrieve_next_request(&mut self) -> (TargetId, ActionRequest);
|
||||
}
|
||||
}
|
||||
delegate! {
|
||||
to self.handler.request_router {
|
||||
pub fn retrieve_next_routing_error(&mut self) -> (TargetId, GenericRoutingError);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PusTestHarness for Pus8RequestTestbenchWithVec {
|
||||
delegate! {
|
||||
to self.common {
|
||||
fn send_tc(&mut self, tc: &PusTcCreator) -> VerificationToken<TcStateAccepted>;
|
||||
fn read_next_tm(&mut self) -> PusTmReader<'_>;
|
||||
fn check_no_tm_available(&self) -> bool;
|
||||
fn check_next_verification_tm(
|
||||
&self,
|
||||
subservice: u8,
|
||||
expected_request_id: verification::RequestId,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
impl SimplePusPacketHandler for Pus8RequestTestbenchWithVec {
|
||||
fn handle_one_tc(&mut self) -> Result<PusPacketHandlerResult, PusPacketHandlingError> {
|
||||
let possible_packet = self.handler.srv_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
|
||||
.handler
|
||||
.srv_helper
|
||||
.tc_in_mem_converter
|
||||
.convert_ecss_tc_in_memory_to_reader(&ecss_tc_and_token.tc_in_memory)?;
|
||||
let time_stamp = cds::TimeProvider::from_now_with_u16_days()
|
||||
.expect("timestamp generation failed")
|
||||
.to_vec()
|
||||
.unwrap();
|
||||
let (target_id, action_request) = self.handler.request_converter.convert(
|
||||
ecss_tc_and_token.token,
|
||||
&tc,
|
||||
&time_stamp,
|
||||
&self.handler.srv_helper.common.verification_handler,
|
||||
)?;
|
||||
if let Err(e) = self.handler.request_router.route(
|
||||
target_id,
|
||||
action_request,
|
||||
ecss_tc_and_token.token,
|
||||
) {
|
||||
self.handler.request_router.handle_error(
|
||||
target_id,
|
||||
ecss_tc_and_token.token,
|
||||
&tc,
|
||||
e.clone(),
|
||||
&time_stamp,
|
||||
&self.handler.srv_helper.common.verification_handler,
|
||||
);
|
||||
return Err(e.into());
|
||||
}
|
||||
Ok(PusPacketHandlerResult::RequestHandled)
|
||||
}
|
||||
}
|
||||
|
||||
const TIMEOUT_ERROR_CODE: ResultU16 = ResultU16::new(1, 2);
|
||||
const COMPLETION_ERROR_CODE: ResultU16 = ResultU16::new(2, 0);
|
||||
const COMPLETION_ERROR_CODE_STEP: ResultU16 = ResultU16::new(2, 1);
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct TestReplyHandlerHook {
|
||||
pub unexpected_replies: VecDeque<GenericActionReplyPus>,
|
||||
pub timeouts: RefCell<VecDeque<ActivePusActionRequest>>,
|
||||
}
|
||||
|
||||
impl ReplyHandlerHook<ActivePusActionRequest, ActionReplyPusWithActionId> for TestReplyHandlerHook {
|
||||
fn handle_unexpected_reply(&mut self, reply: &GenericActionReplyPus) {
|
||||
self.unexpected_replies.push_back(reply.clone());
|
||||
}
|
||||
|
||||
fn timeout_callback(&self, active_request: &ActivePusActionRequest) {
|
||||
self.timeouts.borrow_mut().push_back(active_request.clone());
|
||||
}
|
||||
|
||||
fn timeout_error_code(&self) -> ResultU16 {
|
||||
TIMEOUT_ERROR_CODE
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Pus8ReplyTestbench {
|
||||
verif_reporter: TestVerificationReporter,
|
||||
#[allow(dead_code)]
|
||||
ecss_tm_receiver: mpsc::Receiver<Vec<u8>>,
|
||||
handler: PusService8ReplyHandler<
|
||||
TestVerificationReporter,
|
||||
DefaultActiveActionRequestMap,
|
||||
TestReplyHandlerHook,
|
||||
mpsc::Sender<Vec<u8>>,
|
||||
>,
|
||||
}
|
||||
|
||||
impl Pus8ReplyTestbench {
|
||||
pub fn new(normal_ctor: bool) -> Self {
|
||||
let reply_handler_hook = TestReplyHandlerHook::default();
|
||||
let shared_verif_map = SharedVerificationMap::default();
|
||||
let test_verif_reporter = TestVerificationReporter::new(shared_verif_map.clone());
|
||||
let (ecss_tm_sender, ecss_tm_receiver) = mpsc::channel();
|
||||
let reply_handler = if normal_ctor {
|
||||
PusService8ReplyHandler::new_from_now_with_default_map(
|
||||
test_verif_reporter.clone(),
|
||||
128,
|
||||
reply_handler_hook,
|
||||
ecss_tm_sender,
|
||||
)
|
||||
.expect("creating reply handler failed")
|
||||
} else {
|
||||
PusService8ReplyHandler::new_from_now(
|
||||
test_verif_reporter.clone(),
|
||||
DefaultActiveActionRequestMap::default(),
|
||||
128,
|
||||
reply_handler_hook,
|
||||
ecss_tm_sender,
|
||||
)
|
||||
.expect("creating reply handler failed")
|
||||
};
|
||||
Self {
|
||||
verif_reporter: test_verif_reporter,
|
||||
ecss_tm_receiver,
|
||||
handler: reply_handler,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init_handling_for_request(
|
||||
&mut self,
|
||||
request_id: RequestId,
|
||||
_action_id: ActionId,
|
||||
) -> VerificationToken<TcStateStarted> {
|
||||
assert!(!self.handler.request_active(request_id));
|
||||
// let action_req = ActionRequest::new(action_id, ActionRequestVariant::NoData);
|
||||
let token = self.add_tc_with_req_id(request_id.into());
|
||||
let token = self
|
||||
.verif_reporter
|
||||
.acceptance_success(token, &[])
|
||||
.expect("acceptance success failure");
|
||||
let token = self
|
||||
.verif_reporter
|
||||
.start_success(token, &[])
|
||||
.expect("start success failure");
|
||||
let verif_info = self
|
||||
.verif_reporter
|
||||
.verification_info(&verification::RequestId::from(request_id))
|
||||
.expect("no verification info found");
|
||||
assert!(verif_info.started.expect("request was not started"));
|
||||
assert!(verif_info.accepted.expect("request was not accepted"));
|
||||
token
|
||||
}
|
||||
|
||||
pub fn next_unrequested_reply(&self) -> Option<GenericActionReplyPus> {
|
||||
self.handler.user_hook.unexpected_replies.front().cloned()
|
||||
}
|
||||
|
||||
pub fn assert_request_completion_success(&self, step: Option<u16>, request_id: RequestId) {
|
||||
let verif_info = self
|
||||
.verif_reporter
|
||||
.verification_info(&verification::RequestId::from(request_id))
|
||||
.expect("no verification info found");
|
||||
self.assert_request_completion_common(request_id, &verif_info, step, true);
|
||||
}
|
||||
|
||||
pub fn assert_request_completion_failure(
|
||||
&self,
|
||||
step: Option<u16>,
|
||||
request_id: RequestId,
|
||||
fail_enum: ResultU16,
|
||||
fail_data: &[u8],
|
||||
) {
|
||||
let verif_info = self
|
||||
.verif_reporter
|
||||
.verification_info(&verification::RequestId::from(request_id))
|
||||
.expect("no verification info found");
|
||||
self.assert_request_completion_common(request_id, &verif_info, step, false);
|
||||
assert_eq!(verif_info.fail_enum.unwrap(), fail_enum.raw() as u64);
|
||||
assert_eq!(verif_info.failure_data.unwrap(), fail_data);
|
||||
}
|
||||
|
||||
pub fn assert_request_completion_common(
|
||||
&self,
|
||||
request_id: RequestId,
|
||||
verif_info: &VerificationStatus,
|
||||
step: Option<u16>,
|
||||
completion_success: bool,
|
||||
) {
|
||||
if let Some(step) = step {
|
||||
assert!(verif_info.step_status.is_some());
|
||||
assert!(verif_info.step_status.unwrap());
|
||||
assert_eq!(step, verif_info.step);
|
||||
}
|
||||
assert_eq!(
|
||||
verif_info.completed.expect("request is not completed"),
|
||||
completion_success
|
||||
);
|
||||
assert!(!self.handler.request_active(request_id));
|
||||
}
|
||||
|
||||
pub fn assert_request_step_failure(&self, step: u16, request_id: RequestId) {
|
||||
let verif_info = self
|
||||
.verif_reporter
|
||||
.verification_info(&verification::RequestId::from(request_id))
|
||||
.expect("no verification info found");
|
||||
assert!(verif_info.step_status.is_some());
|
||||
assert!(!verif_info.step_status.unwrap());
|
||||
assert_eq!(step, verif_info.step);
|
||||
}
|
||||
pub fn add_routed_request(
|
||||
&mut self,
|
||||
request_id: verification::RequestId,
|
||||
target_id: TargetId,
|
||||
action_id: ActionId,
|
||||
token: VerificationToken<TcStateStarted>,
|
||||
timeout: Duration,
|
||||
) {
|
||||
if self.handler.request_active(request_id.into()) {
|
||||
panic!("request already present");
|
||||
}
|
||||
self.handler
|
||||
.add_routed_action_request(request_id, target_id, action_id, token, timeout);
|
||||
if !self.handler.request_active(request_id.into()) {
|
||||
panic!("request should be active now");
|
||||
}
|
||||
}
|
||||
|
||||
delegate! {
|
||||
to self.handler {
|
||||
pub fn request_active(&self, request_id: RequestId) -> bool;
|
||||
|
||||
pub fn handle_action_reply(
|
||||
&mut self,
|
||||
action_reply_with_ids: GenericMessage<ActionReplyPusWithActionId>,
|
||||
time_stamp: &[u8]
|
||||
) -> Result<(), EcssTmtcError>;
|
||||
|
||||
pub fn update_time_from_now(&mut self) -> Result<(), SystemTimeError>;
|
||||
|
||||
pub fn check_for_timeouts(&mut self, time_stamp: &[u8]) -> Result<(), EcssTmtcError>;
|
||||
}
|
||||
to self.verif_reporter {
|
||||
fn add_tc_with_req_id(&mut self, req_id: verification::RequestId) -> VerificationToken<TcStateNone>;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_reply_handler_completion_success() {
|
||||
let mut reply_testbench = Pus8ReplyTestbench::new(true);
|
||||
let sender_id = 0x06;
|
||||
let request_id = 0x02;
|
||||
let target_id = 0x05;
|
||||
let action_id = 0x03;
|
||||
let token = reply_testbench.init_handling_for_request(request_id, action_id);
|
||||
reply_testbench.add_routed_request(
|
||||
request_id.into(),
|
||||
target_id,
|
||||
action_id,
|
||||
token,
|
||||
Duration::from_millis(1),
|
||||
);
|
||||
assert!(reply_testbench.request_active(request_id));
|
||||
let action_reply = GenericMessage::new(
|
||||
request_id,
|
||||
sender_id,
|
||||
ActionReplyPusWithActionId {
|
||||
action_id,
|
||||
variant: ActionReplyPus::Completed,
|
||||
},
|
||||
);
|
||||
reply_testbench
|
||||
.handle_action_reply(action_reply, &[])
|
||||
.expect("reply handling failure");
|
||||
reply_testbench.assert_request_completion_success(None, request_id);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_reply_handler_step_success() {
|
||||
let mut reply_testbench = Pus8ReplyTestbench::new(false);
|
||||
let request_id = 0x02;
|
||||
let target_id = 0x05;
|
||||
let action_id = 0x03;
|
||||
let token = reply_testbench.init_handling_for_request(request_id, action_id);
|
||||
reply_testbench.add_routed_request(
|
||||
request_id.into(),
|
||||
target_id,
|
||||
action_id,
|
||||
token,
|
||||
Duration::from_millis(1),
|
||||
);
|
||||
let action_reply = GenericActionReplyPus::new_action_reply(
|
||||
request_id,
|
||||
action_id,
|
||||
action_id,
|
||||
ActionReplyPus::StepSuccess { step: 1 },
|
||||
);
|
||||
reply_testbench
|
||||
.handle_action_reply(action_reply, &[])
|
||||
.expect("reply handling failure");
|
||||
let action_reply = GenericActionReplyPus::new_action_reply(
|
||||
request_id,
|
||||
action_id,
|
||||
action_id,
|
||||
ActionReplyPus::Completed,
|
||||
);
|
||||
reply_testbench
|
||||
.handle_action_reply(action_reply, &[])
|
||||
.expect("reply handling failure");
|
||||
reply_testbench.assert_request_completion_success(Some(1), request_id);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_reply_handler_completion_failure() {
|
||||
let mut reply_testbench = Pus8ReplyTestbench::new(true);
|
||||
let sender_id = 0x01;
|
||||
let request_id = 0x02;
|
||||
let target_id = 0x05;
|
||||
let action_id = 0x03;
|
||||
let token = reply_testbench.init_handling_for_request(request_id, action_id);
|
||||
reply_testbench.add_routed_request(
|
||||
request_id.into(),
|
||||
target_id,
|
||||
action_id,
|
||||
token,
|
||||
Duration::from_millis(1),
|
||||
);
|
||||
let params_raw = ParamsRaw::U32(params::U32(5));
|
||||
let action_reply = GenericActionReplyPus::new_action_reply(
|
||||
request_id,
|
||||
sender_id,
|
||||
action_id,
|
||||
ActionReplyPus::CompletionFailed {
|
||||
error_code: COMPLETION_ERROR_CODE,
|
||||
params: params_raw.into(),
|
||||
},
|
||||
);
|
||||
reply_testbench
|
||||
.handle_action_reply(action_reply, &[])
|
||||
.expect("reply handling failure");
|
||||
reply_testbench.assert_request_completion_failure(
|
||||
None,
|
||||
request_id,
|
||||
COMPLETION_ERROR_CODE,
|
||||
¶ms_raw.to_vec().unwrap(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_reply_handler_step_failure() {
|
||||
let mut reply_testbench = Pus8ReplyTestbench::new(false);
|
||||
let sender_id = 0x01;
|
||||
let request_id = 0x02;
|
||||
let target_id = 0x05;
|
||||
let action_id = 0x03;
|
||||
let token = reply_testbench.init_handling_for_request(request_id, action_id);
|
||||
reply_testbench.add_routed_request(
|
||||
request_id.into(),
|
||||
target_id,
|
||||
action_id,
|
||||
token,
|
||||
Duration::from_millis(1),
|
||||
);
|
||||
let action_reply = GenericActionReplyPus::new_action_reply(
|
||||
request_id,
|
||||
sender_id,
|
||||
action_id,
|
||||
ActionReplyPus::StepFailed {
|
||||
error_code: COMPLETION_ERROR_CODE_STEP,
|
||||
step: 2,
|
||||
params: ParamsRaw::U32(crate::params::U32(5)).into(),
|
||||
},
|
||||
);
|
||||
reply_testbench
|
||||
.handle_action_reply(action_reply, &[])
|
||||
.expect("reply handling failure");
|
||||
reply_testbench.assert_request_step_failure(2, request_id);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_reply_handler_timeout_handling() {
|
||||
let mut reply_testbench = Pus8ReplyTestbench::new(true);
|
||||
let request_id = 0x02;
|
||||
let target_id = 0x06;
|
||||
let action_id = 0x03;
|
||||
let token = reply_testbench.init_handling_for_request(request_id, action_id);
|
||||
reply_testbench.add_routed_request(
|
||||
request_id.into(),
|
||||
target_id,
|
||||
action_id,
|
||||
token,
|
||||
Duration::from_millis(1),
|
||||
);
|
||||
let timeout_param = Duration::from_millis(1).as_millis() as u64;
|
||||
let timeout_param_raw = timeout_param.to_be_bytes();
|
||||
std::thread::sleep(Duration::from_millis(2));
|
||||
reply_testbench
|
||||
.update_time_from_now()
|
||||
.expect("time update failure");
|
||||
reply_testbench.check_for_timeouts(&[]).unwrap();
|
||||
reply_testbench.assert_request_completion_failure(
|
||||
None,
|
||||
request_id,
|
||||
TIMEOUT_ERROR_CODE,
|
||||
&timeout_param_raw,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_unrequested_reply() {
|
||||
let mut reply_testbench = Pus8ReplyTestbench::new(true);
|
||||
let sender_id = 0x01;
|
||||
let request_id = 0x02;
|
||||
let action_id = 0x03;
|
||||
|
||||
let action_reply = GenericActionReplyPus::new_action_reply(
|
||||
request_id,
|
||||
sender_id,
|
||||
action_id,
|
||||
ActionReplyPus::Completed,
|
||||
);
|
||||
reply_testbench
|
||||
.handle_action_reply(action_reply, &[])
|
||||
.expect("reply handling failure");
|
||||
let reply = reply_testbench.next_unrequested_reply();
|
||||
assert!(reply.is_some());
|
||||
let reply = reply.unwrap();
|
||||
assert_eq!(reply.message.action_id, action_id);
|
||||
assert_eq!(reply.request_id, request_id);
|
||||
assert_eq!(reply.message.variant, ActionReplyPus::Completed);
|
||||
}
|
||||
*/
|
||||
}
|
||||
mod tests {}
|
||||
|
@ -132,7 +132,7 @@ impl EventReportCreator {
|
||||
#[cfg(feature = "alloc")]
|
||||
mod alloc_mod {
|
||||
use super::*;
|
||||
use crate::pus::{EcssTmSenderCore, EcssTmtcError};
|
||||
use crate::pus::{EcssTmSender, EcssTmtcError};
|
||||
use crate::ComponentId;
|
||||
use alloc::vec;
|
||||
use alloc::vec::Vec;
|
||||
@ -194,7 +194,7 @@ mod alloc_mod {
|
||||
|
||||
pub fn event_info(
|
||||
&self,
|
||||
sender: &(impl EcssTmSenderCore + ?Sized),
|
||||
sender: &(impl EcssTmSender + ?Sized),
|
||||
time_stamp: &[u8],
|
||||
event_id: impl EcssEnumeration,
|
||||
params: Option<&[u8]>,
|
||||
@ -211,7 +211,7 @@ mod alloc_mod {
|
||||
|
||||
pub fn event_low_severity(
|
||||
&self,
|
||||
sender: &(impl EcssTmSenderCore + ?Sized),
|
||||
sender: &(impl EcssTmSender + ?Sized),
|
||||
time_stamp: &[u8],
|
||||
event_id: impl EcssEnumeration,
|
||||
params: Option<&[u8]>,
|
||||
@ -228,7 +228,7 @@ mod alloc_mod {
|
||||
|
||||
pub fn event_medium_severity(
|
||||
&self,
|
||||
sender: &(impl EcssTmSenderCore + ?Sized),
|
||||
sender: &(impl EcssTmSender + ?Sized),
|
||||
time_stamp: &[u8],
|
||||
event_id: impl EcssEnumeration,
|
||||
params: Option<&[u8]>,
|
||||
@ -245,7 +245,7 @@ mod alloc_mod {
|
||||
|
||||
pub fn event_high_severity(
|
||||
&self,
|
||||
sender: &(impl EcssTmSenderCore + ?Sized),
|
||||
sender: &(impl EcssTmSender + ?Sized),
|
||||
time_stamp: &[u8],
|
||||
event_id: impl EcssEnumeration,
|
||||
params: Option<&[u8]>,
|
||||
@ -268,7 +268,7 @@ mod tests {
|
||||
use crate::events::{EventU32, Severity};
|
||||
use crate::pus::test_util::TEST_COMPONENT_ID_0;
|
||||
use crate::pus::tests::CommonTmInfo;
|
||||
use crate::pus::{ChannelWithId, EcssTmSenderCore, EcssTmtcError, PusTmVariant};
|
||||
use crate::pus::{ChannelWithId, EcssTmSender, EcssTmtcError, PusTmVariant};
|
||||
use crate::ComponentId;
|
||||
use spacepackets::ecss::PusError;
|
||||
use spacepackets::ByteConversionError;
|
||||
@ -301,7 +301,7 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
impl EcssTmSenderCore for TestSender {
|
||||
impl EcssTmSender for TestSender {
|
||||
fn send_tm(&self, sender_id: ComponentId, tm: PusTmVariant) -> Result<(), EcssTmtcError> {
|
||||
match tm {
|
||||
PusTmVariant::InStore(_) => {
|
||||
|
@ -10,7 +10,7 @@ use hashbrown::HashSet;
|
||||
pub use crate::pus::event::EventReporter;
|
||||
use crate::pus::verification::TcStateToken;
|
||||
#[cfg(feature = "alloc")]
|
||||
use crate::pus::EcssTmSenderCore;
|
||||
use crate::pus::EcssTmSender;
|
||||
use crate::pus::EcssTmtcError;
|
||||
#[cfg(feature = "alloc")]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
|
||||
@ -178,7 +178,7 @@ pub mod alloc_mod {
|
||||
|
||||
pub fn generate_pus_event_tm_generic(
|
||||
&self,
|
||||
sender: &(impl EcssTmSenderCore + ?Sized),
|
||||
sender: &(impl EcssTmSender + ?Sized),
|
||||
time_stamp: &[u8],
|
||||
event: Event,
|
||||
params: Option<&[u8]>,
|
||||
@ -240,7 +240,7 @@ pub mod alloc_mod {
|
||||
|
||||
pub fn generate_pus_event_tm<Severity: HasSeverity>(
|
||||
&self,
|
||||
sender: &(impl EcssTmSenderCore + ?Sized),
|
||||
sender: &(impl EcssTmSender + ?Sized),
|
||||
time_stamp: &[u8],
|
||||
event: EventU32TypedSev<Severity>,
|
||||
aux_data: Option<&[u8]>,
|
||||
@ -257,9 +257,8 @@ pub mod alloc_mod {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::events::SeverityInfo;
|
||||
use crate::pus::PusTmAsVec;
|
||||
use crate::request::UniqueApidTargetId;
|
||||
use crate::{events::SeverityInfo, tmtc::PacketAsVec};
|
||||
use std::sync::mpsc::{self, TryRecvError};
|
||||
|
||||
const INFO_EVENT: EventU32TypedSev<SeverityInfo> =
|
||||
@ -284,7 +283,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_basic() {
|
||||
let event_man = create_basic_man_1();
|
||||
let (event_tx, event_rx) = mpsc::channel::<PusTmAsVec>();
|
||||
let (event_tx, event_rx) = mpsc::channel::<PacketAsVec>();
|
||||
let event_sent = event_man
|
||||
.generate_pus_event_tm(&event_tx, &EMPTY_STAMP, INFO_EVENT, None)
|
||||
.expect("Sending info event failed");
|
||||
@ -297,7 +296,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_disable_event() {
|
||||
let mut event_man = create_basic_man_2();
|
||||
let (event_tx, event_rx) = mpsc::channel::<PusTmAsVec>();
|
||||
let (event_tx, event_rx) = mpsc::channel::<PacketAsVec>();
|
||||
// let mut sender = TmAsVecSenderWithMpsc::new(0, "test", event_tx);
|
||||
let res = event_man.disable_tm_for_event(&LOW_SEV_EVENT);
|
||||
assert!(res.is_ok());
|
||||
@ -320,7 +319,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_reenable_event() {
|
||||
let mut event_man = create_basic_man_1();
|
||||
let (event_tx, event_rx) = mpsc::channel::<PusTmAsVec>();
|
||||
let (event_tx, event_rx) = mpsc::channel::<PacketAsVec>();
|
||||
let mut res = event_man.disable_tm_for_event_with_sev(&INFO_EVENT);
|
||||
assert!(res.is_ok());
|
||||
assert!(res.unwrap());
|
||||
|
@ -9,13 +9,13 @@ use std::sync::mpsc::Sender;
|
||||
|
||||
use super::verification::VerificationReportingProvider;
|
||||
use super::{
|
||||
EcssTcInMemConverter, EcssTcReceiverCore, EcssTmSenderCore, GenericConversionError,
|
||||
EcssTcInMemConverter, EcssTcReceiver, EcssTmSender, GenericConversionError,
|
||||
GenericRoutingError, PusServiceHelper,
|
||||
};
|
||||
|
||||
pub struct PusEventServiceHandler<
|
||||
TcReceiver: EcssTcReceiverCore,
|
||||
TmSender: EcssTmSenderCore,
|
||||
TcReceiver: EcssTcReceiver,
|
||||
TmSender: EcssTmSender,
|
||||
TcInMemConverter: EcssTcInMemConverter,
|
||||
VerificationReporter: VerificationReportingProvider,
|
||||
> {
|
||||
@ -25,8 +25,8 @@ pub struct PusEventServiceHandler<
|
||||
}
|
||||
|
||||
impl<
|
||||
TcReceiver: EcssTcReceiverCore,
|
||||
TmSender: EcssTmSenderCore,
|
||||
TcReceiver: EcssTcReceiver,
|
||||
TmSender: EcssTmSender,
|
||||
TcInMemConverter: EcssTcInMemConverter,
|
||||
VerificationReporter: VerificationReportingProvider,
|
||||
> PusEventServiceHandler<TcReceiver, TmSender, TcInMemConverter, VerificationReporter>
|
||||
@ -167,7 +167,8 @@ mod tests {
|
||||
use crate::pus::verification::{
|
||||
RequestId, VerificationReporter, VerificationReportingProvider,
|
||||
};
|
||||
use crate::pus::{GenericConversionError, MpscTcReceiver, MpscTmInSharedPoolSenderBounded};
|
||||
use crate::pus::{GenericConversionError, MpscTcReceiver};
|
||||
use crate::tmtc::PacketSenderWithSharedPool;
|
||||
use crate::{
|
||||
events::EventU32,
|
||||
pus::{
|
||||
@ -186,7 +187,7 @@ mod tests {
|
||||
common: PusServiceHandlerWithSharedStoreCommon,
|
||||
handler: PusEventServiceHandler<
|
||||
MpscTcReceiver,
|
||||
MpscTmInSharedPoolSenderBounded,
|
||||
PacketSenderWithSharedPool,
|
||||
EcssTcInSharedStoreConverter,
|
||||
VerificationReporter,
|
||||
>,
|
||||
@ -212,9 +213,13 @@ mod tests {
|
||||
.expect("acceptance success failure")
|
||||
}
|
||||
|
||||
fn send_tc(&self, token: &VerificationToken<TcStateAccepted>, tc: &PusTcCreator) {
|
||||
self.common
|
||||
.send_tc(self.handler.service_helper.id(), token, tc);
|
||||
}
|
||||
|
||||
delegate! {
|
||||
to self.common {
|
||||
fn send_tc(&self, token: &VerificationToken<TcStateAccepted>, tc: &PusTcCreator);
|
||||
fn read_next_tm(&mut self) -> PusTmReader<'_>;
|
||||
fn check_no_tm_available(&self) -> bool;
|
||||
fn check_next_verification_tm(&self, subservice: u8, expected_request_id: RequestId);
|
||||
|
@ -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");
|
||||
|
@ -14,7 +14,7 @@ use spacepackets::{ByteConversionError, CcsdsPacket};
|
||||
#[cfg(feature = "std")]
|
||||
use std::error::Error;
|
||||
|
||||
use crate::pool::{PoolProvider, StoreError};
|
||||
use crate::pool::{PoolError, PoolProvider};
|
||||
#[cfg(feature = "alloc")]
|
||||
pub use alloc_mod::*;
|
||||
|
||||
@ -151,7 +151,7 @@ pub enum ScheduleError {
|
||||
},
|
||||
/// Nested time-tagged commands are not allowed.
|
||||
NestedScheduledTc,
|
||||
StoreError(StoreError),
|
||||
StoreError(PoolError),
|
||||
TcDataEmpty,
|
||||
TimestampError(TimestampError),
|
||||
WrongSubservice(u8),
|
||||
@ -206,8 +206,8 @@ impl From<PusError> for ScheduleError {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<StoreError> for ScheduleError {
|
||||
fn from(e: StoreError) -> Self {
|
||||
impl From<PoolError> for ScheduleError {
|
||||
fn from(e: PoolError) -> Self {
|
||||
Self::StoreError(e)
|
||||
}
|
||||
}
|
||||
@ -240,7 +240,7 @@ impl Error for ScheduleError {
|
||||
pub trait PusSchedulerProvider {
|
||||
type TimeProvider: CcsdsTimeProvider + TimeReader;
|
||||
|
||||
fn reset(&mut self, store: &mut (impl PoolProvider + ?Sized)) -> Result<(), StoreError>;
|
||||
fn reset(&mut self, store: &mut (impl PoolProvider + ?Sized)) -> Result<(), PoolError>;
|
||||
|
||||
fn is_enabled(&self) -> bool;
|
||||
|
||||
@ -345,12 +345,9 @@ pub mod alloc_mod {
|
||||
},
|
||||
vec::Vec,
|
||||
};
|
||||
use spacepackets::time::{
|
||||
cds::{self, DaysLen24Bits},
|
||||
UnixTime,
|
||||
};
|
||||
use spacepackets::time::cds::{self, DaysLen24Bits};
|
||||
|
||||
use crate::pool::StoreAddr;
|
||||
use crate::pool::PoolAddr;
|
||||
|
||||
use super::*;
|
||||
|
||||
@ -371,8 +368,8 @@ pub mod alloc_mod {
|
||||
}
|
||||
|
||||
enum DeletionResult {
|
||||
WithoutStoreDeletion(Option<StoreAddr>),
|
||||
WithStoreDeletion(Result<bool, StoreError>),
|
||||
WithoutStoreDeletion(Option<PoolAddr>),
|
||||
WithStoreDeletion(Result<bool, PoolError>),
|
||||
}
|
||||
|
||||
/// This is the core data structure for scheduling PUS telecommands with [alloc] support.
|
||||
@ -528,7 +525,7 @@ pub mod alloc_mod {
|
||||
&mut self,
|
||||
time_window: TimeWindow<TimeProvider>,
|
||||
pool: &mut (impl PoolProvider + ?Sized),
|
||||
) -> Result<u64, (u64, StoreError)> {
|
||||
) -> Result<u64, (u64, PoolError)> {
|
||||
let range = self.retrieve_by_time_filter(time_window);
|
||||
let mut del_packets = 0;
|
||||
let mut res_if_fails = None;
|
||||
@ -558,7 +555,7 @@ pub mod alloc_mod {
|
||||
pub fn delete_all(
|
||||
&mut self,
|
||||
pool: &mut (impl PoolProvider + ?Sized),
|
||||
) -> Result<u64, (u64, StoreError)> {
|
||||
) -> Result<u64, (u64, PoolError)> {
|
||||
self.delete_by_time_filter(TimeWindow::<cds::CdsTime>::new_select_all(), pool)
|
||||
}
|
||||
|
||||
@ -604,7 +601,7 @@ pub mod alloc_mod {
|
||||
/// Please note that this function will stop on the first telecommand with a request ID match.
|
||||
/// In case of duplicate IDs (which should generally not happen), this function needs to be
|
||||
/// called repeatedly.
|
||||
pub fn delete_by_request_id(&mut self, req_id: &RequestId) -> Option<StoreAddr> {
|
||||
pub fn delete_by_request_id(&mut self, req_id: &RequestId) -> Option<PoolAddr> {
|
||||
if let DeletionResult::WithoutStoreDeletion(v) =
|
||||
self.delete_by_request_id_internal_without_store_deletion(req_id)
|
||||
{
|
||||
@ -618,7 +615,7 @@ pub mod alloc_mod {
|
||||
&mut self,
|
||||
req_id: &RequestId,
|
||||
pool: &mut (impl PoolProvider + ?Sized),
|
||||
) -> Result<bool, StoreError> {
|
||||
) -> Result<bool, PoolError> {
|
||||
if let DeletionResult::WithStoreDeletion(v) =
|
||||
self.delete_by_request_id_internal_with_store_deletion(req_id, pool)
|
||||
{
|
||||
@ -696,7 +693,7 @@ pub mod alloc_mod {
|
||||
releaser: R,
|
||||
tc_store: &mut (impl PoolProvider + ?Sized),
|
||||
tc_buf: &mut [u8],
|
||||
) -> Result<u64, (u64, StoreError)> {
|
||||
) -> Result<u64, (u64, PoolError)> {
|
||||
self.release_telecommands_internal(releaser, tc_store, Some(tc_buf))
|
||||
}
|
||||
|
||||
@ -710,7 +707,7 @@ pub mod alloc_mod {
|
||||
&mut self,
|
||||
releaser: R,
|
||||
tc_store: &mut (impl PoolProvider + ?Sized),
|
||||
) -> Result<u64, (u64, StoreError)> {
|
||||
) -> Result<u64, (u64, PoolError)> {
|
||||
self.release_telecommands_internal(releaser, tc_store, None)
|
||||
}
|
||||
|
||||
@ -719,7 +716,7 @@ pub mod alloc_mod {
|
||||
mut releaser: R,
|
||||
tc_store: &mut (impl PoolProvider + ?Sized),
|
||||
mut tc_buf: Option<&mut [u8]>,
|
||||
) -> Result<u64, (u64, StoreError)> {
|
||||
) -> Result<u64, (u64, PoolError)> {
|
||||
let tcs_to_release = self.telecommands_to_release();
|
||||
let mut released_tcs = 0;
|
||||
let mut store_error = Ok(());
|
||||
@ -765,7 +762,7 @@ pub mod alloc_mod {
|
||||
mut releaser: R,
|
||||
tc_store: &(impl PoolProvider + ?Sized),
|
||||
tc_buf: &mut [u8],
|
||||
) -> Result<alloc::vec::Vec<TcInfo>, (alloc::vec::Vec<TcInfo>, StoreError)> {
|
||||
) -> Result<alloc::vec::Vec<TcInfo>, (alloc::vec::Vec<TcInfo>, PoolError)> {
|
||||
let tcs_to_release = self.telecommands_to_release();
|
||||
let mut released_tcs = alloc::vec::Vec::new();
|
||||
for tc in tcs_to_release {
|
||||
@ -796,7 +793,7 @@ pub mod alloc_mod {
|
||||
/// The holding store for the telecommands needs to be passed so all the stored telecommands
|
||||
/// can be deleted to avoid a memory leak. If at last one deletion operation fails, the error
|
||||
/// will be returned but the method will still try to delete all the commands in the schedule.
|
||||
fn reset(&mut self, store: &mut (impl PoolProvider + ?Sized)) -> Result<(), StoreError> {
|
||||
fn reset(&mut self, store: &mut (impl PoolProvider + ?Sized)) -> Result<(), PoolError> {
|
||||
self.enabled = false;
|
||||
let mut deletion_ok = Ok(());
|
||||
for tc_lists in &mut self.tc_map {
|
||||
@ -854,7 +851,7 @@ pub mod alloc_mod {
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::pool::{
|
||||
PoolProvider, StaticMemoryPool, StaticPoolAddr, StaticPoolConfig, StoreAddr, StoreError,
|
||||
PoolAddr, PoolError, PoolProvider, StaticMemoryPool, StaticPoolAddr, StaticPoolConfig,
|
||||
};
|
||||
use alloc::collections::btree_map::Range;
|
||||
use spacepackets::ecss::tc::{PusTcCreator, PusTcReader, PusTcSecondaryHeader};
|
||||
@ -993,7 +990,7 @@ mod tests {
|
||||
.insert_unwrapped_and_stored_tc(
|
||||
UnixTime::new_only_secs(100),
|
||||
TcInfo::new(
|
||||
StoreAddr::from(StaticPoolAddr {
|
||||
PoolAddr::from(StaticPoolAddr {
|
||||
pool_idx: 0,
|
||||
packet_idx: 1,
|
||||
}),
|
||||
@ -1010,7 +1007,7 @@ mod tests {
|
||||
.insert_unwrapped_and_stored_tc(
|
||||
UnixTime::new_only_secs(100),
|
||||
TcInfo::new(
|
||||
StoreAddr::from(StaticPoolAddr {
|
||||
PoolAddr::from(StaticPoolAddr {
|
||||
pool_idx: 0,
|
||||
packet_idx: 2,
|
||||
}),
|
||||
@ -1054,8 +1051,8 @@ mod tests {
|
||||
|
||||
fn common_check(
|
||||
enabled: bool,
|
||||
store_addr: &StoreAddr,
|
||||
expected_store_addrs: Vec<StoreAddr>,
|
||||
store_addr: &PoolAddr,
|
||||
expected_store_addrs: Vec<PoolAddr>,
|
||||
counter: &mut usize,
|
||||
) {
|
||||
assert!(enabled);
|
||||
@ -1064,8 +1061,8 @@ mod tests {
|
||||
}
|
||||
fn common_check_disabled(
|
||||
enabled: bool,
|
||||
store_addr: &StoreAddr,
|
||||
expected_store_addrs: Vec<StoreAddr>,
|
||||
store_addr: &PoolAddr,
|
||||
expected_store_addrs: Vec<PoolAddr>,
|
||||
counter: &mut usize,
|
||||
) {
|
||||
assert!(!enabled);
|
||||
@ -1519,7 +1516,7 @@ mod tests {
|
||||
// TC could not even be read..
|
||||
assert_eq!(err.0, 0);
|
||||
match err.1 {
|
||||
StoreError::DataDoesNotExist(addr) => {
|
||||
PoolError::DataDoesNotExist(addr) => {
|
||||
assert_eq!(tc_info_0.addr(), addr);
|
||||
}
|
||||
_ => panic!("unexpected error {}", err.1),
|
||||
@ -1542,7 +1539,7 @@ mod tests {
|
||||
assert!(reset_res.is_err());
|
||||
let err = reset_res.unwrap_err();
|
||||
match err {
|
||||
StoreError::DataDoesNotExist(addr) => {
|
||||
PoolError::DataDoesNotExist(addr) => {
|
||||
assert_eq!(addr, tc_info_0.addr());
|
||||
}
|
||||
_ => panic!("unexpected error {err}"),
|
||||
@ -1644,7 +1641,7 @@ mod tests {
|
||||
let err = insert_res.unwrap_err();
|
||||
match err {
|
||||
ScheduleError::StoreError(e) => match e {
|
||||
StoreError::StoreFull(_) => {}
|
||||
PoolError::StoreFull(_) => {}
|
||||
_ => panic!("unexpected store error {e}"),
|
||||
},
|
||||
_ => panic!("unexpected error {err}"),
|
||||
|
@ -1,12 +1,12 @@
|
||||
use super::scheduler::PusSchedulerProvider;
|
||||
use super::verification::{VerificationReporter, VerificationReportingProvider};
|
||||
use super::{
|
||||
EcssTcInMemConverter, EcssTcInSharedStoreConverter, EcssTcInVecConverter, EcssTcReceiverCore,
|
||||
EcssTmSenderCore, MpscTcReceiver, MpscTmInSharedPoolSender, MpscTmInSharedPoolSenderBounded,
|
||||
PusServiceHelper, PusTmAsVec,
|
||||
EcssTcInMemConverter, EcssTcInSharedStoreConverter, EcssTcInVecConverter, EcssTcReceiver,
|
||||
EcssTmSender, MpscTcReceiver, PusServiceHelper,
|
||||
};
|
||||
use crate::pool::PoolProvider;
|
||||
use crate::pus::{PusPacketHandlerResult, PusPacketHandlingError};
|
||||
use crate::tmtc::{PacketAsVec, PacketSenderWithSharedPool};
|
||||
use alloc::string::ToString;
|
||||
use spacepackets::ecss::{scheduling, PusPacket};
|
||||
use spacepackets::time::cds::CdsTime;
|
||||
@ -21,8 +21,8 @@ use std::sync::mpsc;
|
||||
/// [Self::scheduler] and [Self::scheduler_mut] function and then use the scheduler API to release
|
||||
/// telecommands when applicable.
|
||||
pub struct PusSchedServiceHandler<
|
||||
TcReceiver: EcssTcReceiverCore,
|
||||
TmSender: EcssTmSenderCore,
|
||||
TcReceiver: EcssTcReceiver,
|
||||
TmSender: EcssTmSender,
|
||||
TcInMemConverter: EcssTcInMemConverter,
|
||||
VerificationReporter: VerificationReportingProvider,
|
||||
PusScheduler: PusSchedulerProvider,
|
||||
@ -33,8 +33,8 @@ pub struct PusSchedServiceHandler<
|
||||
}
|
||||
|
||||
impl<
|
||||
TcReceiver: EcssTcReceiverCore,
|
||||
TmSender: EcssTmSenderCore,
|
||||
TcReceiver: EcssTcReceiver,
|
||||
TmSender: EcssTmSender,
|
||||
TcInMemConverter: EcssTcInMemConverter,
|
||||
VerificationReporter: VerificationReportingProvider,
|
||||
Scheduler: PusSchedulerProvider,
|
||||
@ -212,7 +212,7 @@ impl<
|
||||
/// mpsc queues.
|
||||
pub type PusService11SchedHandlerDynWithMpsc<PusScheduler> = PusSchedServiceHandler<
|
||||
MpscTcReceiver,
|
||||
mpsc::Sender<PusTmAsVec>,
|
||||
mpsc::Sender<PacketAsVec>,
|
||||
EcssTcInVecConverter,
|
||||
VerificationReporter,
|
||||
PusScheduler,
|
||||
@ -221,7 +221,7 @@ pub type PusService11SchedHandlerDynWithMpsc<PusScheduler> = PusSchedServiceHand
|
||||
/// queues.
|
||||
pub type PusService11SchedHandlerDynWithBoundedMpsc<PusScheduler> = PusSchedServiceHandler<
|
||||
MpscTcReceiver,
|
||||
mpsc::SyncSender<PusTmAsVec>,
|
||||
mpsc::SyncSender<PacketAsVec>,
|
||||
EcssTcInVecConverter,
|
||||
VerificationReporter,
|
||||
PusScheduler,
|
||||
@ -230,7 +230,7 @@ pub type PusService11SchedHandlerDynWithBoundedMpsc<PusScheduler> = PusSchedServ
|
||||
/// mpsc queues.
|
||||
pub type PusService11SchedHandlerStaticWithMpsc<PusScheduler> = PusSchedServiceHandler<
|
||||
MpscTcReceiver,
|
||||
MpscTmInSharedPoolSender,
|
||||
PacketSenderWithSharedPool,
|
||||
EcssTcInSharedStoreConverter,
|
||||
VerificationReporter,
|
||||
PusScheduler,
|
||||
@ -239,7 +239,7 @@ pub type PusService11SchedHandlerStaticWithMpsc<PusScheduler> = PusSchedServiceH
|
||||
/// mpsc queues.
|
||||
pub type PusService11SchedHandlerStaticWithBoundedMpsc<PusScheduler> = PusSchedServiceHandler<
|
||||
MpscTcReceiver,
|
||||
MpscTmInSharedPoolSenderBounded,
|
||||
PacketSenderWithSharedPool,
|
||||
EcssTcInSharedStoreConverter,
|
||||
VerificationReporter,
|
||||
PusScheduler,
|
||||
@ -257,10 +257,8 @@ mod tests {
|
||||
verification::{RequestId, TcStateAccepted, VerificationToken},
|
||||
EcssTcInSharedStoreConverter,
|
||||
};
|
||||
use crate::pus::{
|
||||
MpscTcReceiver, MpscTmInSharedPoolSenderBounded, PusPacketHandlerResult,
|
||||
PusPacketHandlingError,
|
||||
};
|
||||
use crate::pus::{MpscTcReceiver, PusPacketHandlerResult, PusPacketHandlingError};
|
||||
use crate::tmtc::PacketSenderWithSharedPool;
|
||||
use alloc::collections::VecDeque;
|
||||
use delegate::delegate;
|
||||
use spacepackets::ecss::scheduling::Subservice;
|
||||
@ -279,7 +277,7 @@ mod tests {
|
||||
common: PusServiceHandlerWithSharedStoreCommon,
|
||||
handler: PusSchedServiceHandler<
|
||||
MpscTcReceiver,
|
||||
MpscTmInSharedPoolSenderBounded,
|
||||
PacketSenderWithSharedPool,
|
||||
EcssTcInSharedStoreConverter,
|
||||
VerificationReporter,
|
||||
TestScheduler,
|
||||
@ -317,9 +315,13 @@ mod tests {
|
||||
.expect("acceptance success failure")
|
||||
}
|
||||
|
||||
fn send_tc(&self, token: &VerificationToken<TcStateAccepted>, tc: &PusTcCreator) {
|
||||
self.common
|
||||
.send_tc(self.handler.service_helper.id(), token, tc);
|
||||
}
|
||||
|
||||
delegate! {
|
||||
to self.common {
|
||||
fn send_tc(&self, token: &VerificationToken<TcStateAccepted>, tc: &PusTcCreator);
|
||||
fn read_next_tm(&mut self) -> PusTmReader<'_>;
|
||||
fn check_no_tm_available(&self) -> bool;
|
||||
fn check_next_verification_tm(&self, subservice: u8, expected_request_id: RequestId);
|
||||
@ -342,7 +344,7 @@ mod tests {
|
||||
fn reset(
|
||||
&mut self,
|
||||
_store: &mut (impl crate::pool::PoolProvider + ?Sized),
|
||||
) -> Result<(), crate::pool::StoreError> {
|
||||
) -> Result<(), crate::pool::PoolError> {
|
||||
self.reset_count += 1;
|
||||
Ok(())
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::pus::{
|
||||
PartialPusHandlingError, PusPacketHandlerResult, PusPacketHandlingError, PusTmAsVec,
|
||||
PusTmInPool, PusTmVariant,
|
||||
PartialPusHandlingError, PusPacketHandlerResult, PusPacketHandlingError, PusTmVariant,
|
||||
};
|
||||
use crate::tmtc::{PacketAsVec, PacketSenderWithSharedPool};
|
||||
use spacepackets::ecss::tm::{PusTmCreator, PusTmSecondaryHeader};
|
||||
use spacepackets::ecss::PusPacket;
|
||||
use spacepackets::SpHeader;
|
||||
@ -9,16 +9,15 @@ use std::sync::mpsc;
|
||||
|
||||
use super::verification::{VerificationReporter, VerificationReportingProvider};
|
||||
use super::{
|
||||
EcssTcInMemConverter, EcssTcInSharedStoreConverter, EcssTcInVecConverter, EcssTcReceiverCore,
|
||||
EcssTmSenderCore, GenericConversionError, MpscTcReceiver, MpscTmInSharedPoolSender,
|
||||
MpscTmInSharedPoolSenderBounded, PusServiceHelper,
|
||||
EcssTcInMemConverter, EcssTcInSharedStoreConverter, EcssTcInVecConverter, EcssTcReceiver,
|
||||
EcssTmSender, GenericConversionError, MpscTcReceiver, PusServiceHelper,
|
||||
};
|
||||
|
||||
/// This is a helper class for [std] environments to handle generic PUS 17 (test service) packets.
|
||||
/// This handler only processes ping requests and generates a ping reply for them accordingly.
|
||||
pub struct PusService17TestHandler<
|
||||
TcReceiver: EcssTcReceiverCore,
|
||||
TmSender: EcssTmSenderCore,
|
||||
TcReceiver: EcssTcReceiver,
|
||||
TmSender: EcssTmSender,
|
||||
TcInMemConverter: EcssTcInMemConverter,
|
||||
VerificationReporter: VerificationReportingProvider,
|
||||
> {
|
||||
@ -27,8 +26,8 @@ pub struct PusService17TestHandler<
|
||||
}
|
||||
|
||||
impl<
|
||||
TcReceiver: EcssTcReceiverCore,
|
||||
TmSender: EcssTmSenderCore,
|
||||
TcReceiver: EcssTcReceiver,
|
||||
TmSender: EcssTmSender,
|
||||
TcInMemConverter: EcssTcInMemConverter,
|
||||
VerificationReporter: VerificationReportingProvider,
|
||||
> PusService17TestHandler<TcReceiver, TmSender, TcInMemConverter, VerificationReporter>
|
||||
@ -127,7 +126,7 @@ impl<
|
||||
/// mpsc queues.
|
||||
pub type PusService17TestHandlerDynWithMpsc = PusService17TestHandler<
|
||||
MpscTcReceiver,
|
||||
mpsc::Sender<PusTmAsVec>,
|
||||
mpsc::Sender<PacketAsVec>,
|
||||
EcssTcInVecConverter,
|
||||
VerificationReporter,
|
||||
>;
|
||||
@ -135,23 +134,15 @@ pub type PusService17TestHandlerDynWithMpsc = PusService17TestHandler<
|
||||
/// queues.
|
||||
pub type PusService17TestHandlerDynWithBoundedMpsc = PusService17TestHandler<
|
||||
MpscTcReceiver,
|
||||
mpsc::SyncSender<PusTmInPool>,
|
||||
mpsc::SyncSender<PacketAsVec>,
|
||||
EcssTcInVecConverter,
|
||||
VerificationReporter,
|
||||
>;
|
||||
/// Helper type definition for a PUS 17 handler with a shared store TMTC memory backend and regular
|
||||
/// mpsc queues.
|
||||
pub type PusService17TestHandlerStaticWithMpsc = PusService17TestHandler<
|
||||
MpscTcReceiver,
|
||||
MpscTmInSharedPoolSender,
|
||||
EcssTcInSharedStoreConverter,
|
||||
VerificationReporter,
|
||||
>;
|
||||
/// Helper type definition for a PUS 17 handler with a shared store TMTC memory backend and bounded
|
||||
/// mpsc queues.
|
||||
pub type PusService17TestHandlerStaticWithBoundedMpsc = PusService17TestHandler<
|
||||
MpscTcReceiver,
|
||||
MpscTmInSharedPoolSenderBounded,
|
||||
PacketSenderWithSharedPool,
|
||||
EcssTcInSharedStoreConverter,
|
||||
VerificationReporter,
|
||||
>;
|
||||
@ -168,9 +159,9 @@ mod tests {
|
||||
use crate::pus::verification::{TcStateAccepted, VerificationToken};
|
||||
use crate::pus::{
|
||||
EcssTcInSharedStoreConverter, EcssTcInVecConverter, GenericConversionError, MpscTcReceiver,
|
||||
MpscTmAsVecSender, MpscTmInSharedPoolSenderBounded, PusPacketHandlerResult,
|
||||
PusPacketHandlingError,
|
||||
MpscTmAsVecSender, PusPacketHandlerResult, PusPacketHandlingError,
|
||||
};
|
||||
use crate::tmtc::PacketSenderWithSharedPool;
|
||||
use crate::ComponentId;
|
||||
use delegate::delegate;
|
||||
use spacepackets::ecss::tc::{PusTcCreator, PusTcSecondaryHeader};
|
||||
@ -185,7 +176,7 @@ mod tests {
|
||||
common: PusServiceHandlerWithSharedStoreCommon,
|
||||
handler: PusService17TestHandler<
|
||||
MpscTcReceiver,
|
||||
MpscTmInSharedPoolSenderBounded,
|
||||
PacketSenderWithSharedPool,
|
||||
EcssTcInSharedStoreConverter,
|
||||
VerificationReporter,
|
||||
>,
|
||||
@ -212,10 +203,14 @@ mod tests {
|
||||
.expect("acceptance success failure")
|
||||
}
|
||||
|
||||
fn send_tc(&self, token: &VerificationToken<TcStateAccepted>, tc: &PusTcCreator) {
|
||||
self.common
|
||||
.send_tc(self.handler.service_helper.id(), token, tc);
|
||||
}
|
||||
|
||||
delegate! {
|
||||
to self.common {
|
||||
fn read_next_tm(&mut self) -> PusTmReader<'_>;
|
||||
fn send_tc(&self, token: &VerificationToken<TcStateAccepted>, tc: &PusTcCreator);
|
||||
fn check_no_tm_available(&self) -> bool;
|
||||
fn check_next_verification_tm(
|
||||
&self,
|
||||
@ -263,9 +258,13 @@ mod tests {
|
||||
.expect("acceptance success failure")
|
||||
}
|
||||
|
||||
fn send_tc(&self, token: &VerificationToken<TcStateAccepted>, tc: &PusTcCreator) {
|
||||
self.common
|
||||
.send_tc(self.handler.service_helper.id(), token, tc);
|
||||
}
|
||||
|
||||
delegate! {
|
||||
to self.common {
|
||||
fn send_tc(&self, token: &VerificationToken<TcStateAccepted>, tc: &PusTcCreator);
|
||||
fn read_next_tm(&mut self) -> PusTmReader<'_>;
|
||||
fn check_no_tm_available(&self) -> bool;
|
||||
fn check_next_verification_tm(
|
||||
|
@ -19,10 +19,9 @@
|
||||
//! use satrs::pus::verification::{
|
||||
//! VerificationReportingProvider, VerificationReporterCfg, VerificationReporter
|
||||
//! };
|
||||
//! use satrs::tmtc::{SharedStaticMemoryPool, PacketSenderWithSharedPool};
|
||||
//! use satrs::seq_count::SeqCountProviderSimple;
|
||||
//! use satrs::request::UniqueApidTargetId;
|
||||
//! use satrs::pus::MpscTmInSharedPoolSender;
|
||||
//! use satrs::tmtc::tm_helper::SharedTmPool;
|
||||
//! use spacepackets::ecss::PusPacket;
|
||||
//! use spacepackets::SpHeader;
|
||||
//! use spacepackets::ecss::tc::{PusTcCreator, PusTcSecondaryHeader};
|
||||
@ -34,10 +33,9 @@
|
||||
//!
|
||||
//! let pool_cfg = StaticPoolConfig::new(vec![(10, 32), (10, 64), (10, 128), (10, 1024)], false);
|
||||
//! let tm_pool = StaticMemoryPool::new(pool_cfg.clone());
|
||||
//! let shared_tm_store = SharedTmPool::new(tm_pool);
|
||||
//! let tm_store = shared_tm_store.clone_backing_pool();
|
||||
//! let (verif_tx, verif_rx) = mpsc::channel();
|
||||
//! let sender = MpscTmInSharedPoolSender::new(shared_tm_store, verif_tx);
|
||||
//! let shared_tm_pool = SharedStaticMemoryPool::new(RwLock::new(tm_pool));
|
||||
//! let (verif_tx, verif_rx) = mpsc::sync_channel(10);
|
||||
//! let sender = PacketSenderWithSharedPool::new_with_shared_packet_pool(verif_tx, &shared_tm_pool);
|
||||
//! let cfg = VerificationReporterCfg::new(TEST_APID, 1, 2, 8).unwrap();
|
||||
//! let mut reporter = VerificationReporter::new(TEST_COMPONENT_ID.id(), &cfg);
|
||||
//!
|
||||
@ -61,7 +59,7 @@
|
||||
//! let tm_in_store = verif_rx.recv_timeout(Duration::from_millis(10)).unwrap();
|
||||
//! let tm_len;
|
||||
//! {
|
||||
//! let mut rg = tm_store.write().expect("Error locking shared pool");
|
||||
//! let mut rg = shared_tm_pool.write().expect("Error locking shared pool");
|
||||
//! let store_guard = rg.read_with_guard(tm_in_store.store_addr);
|
||||
//! tm_len = store_guard.read(&mut tm_buf).expect("Error reading TM slice");
|
||||
//! }
|
||||
@ -81,7 +79,7 @@
|
||||
//! The [integration test](https://egit.irs.uni-stuttgart.de/rust/fsrc-launchpad/src/branch/main/fsrc-core/tests/verification_test.rs)
|
||||
//! for the verification module contains examples how this module could be used in a more complex
|
||||
//! context involving multiple threads
|
||||
use crate::pus::{source_buffer_large_enough, EcssTmSenderCore, EcssTmtcError};
|
||||
use crate::pus::{source_buffer_large_enough, EcssTmSender, EcssTmtcError};
|
||||
use core::fmt::{Debug, Display, Formatter};
|
||||
use core::hash::{Hash, Hasher};
|
||||
use core::marker::PhantomData;
|
||||
@ -425,35 +423,35 @@ pub trait VerificationReportingProvider {
|
||||
|
||||
fn acceptance_success(
|
||||
&self,
|
||||
sender: &(impl EcssTmSenderCore + ?Sized),
|
||||
sender: &(impl EcssTmSender + ?Sized),
|
||||
token: VerificationToken<TcStateNone>,
|
||||
time_stamp: &[u8],
|
||||
) -> Result<VerificationToken<TcStateAccepted>, EcssTmtcError>;
|
||||
|
||||
fn acceptance_failure(
|
||||
&self,
|
||||
sender: &(impl EcssTmSenderCore + ?Sized),
|
||||
sender: &(impl EcssTmSender + ?Sized),
|
||||
token: VerificationToken<TcStateNone>,
|
||||
params: FailParams,
|
||||
) -> Result<(), EcssTmtcError>;
|
||||
|
||||
fn start_success(
|
||||
&self,
|
||||
sender: &(impl EcssTmSenderCore + ?Sized),
|
||||
sender: &(impl EcssTmSender + ?Sized),
|
||||
token: VerificationToken<TcStateAccepted>,
|
||||
time_stamp: &[u8],
|
||||
) -> Result<VerificationToken<TcStateStarted>, EcssTmtcError>;
|
||||
|
||||
fn start_failure(
|
||||
&self,
|
||||
sender: &(impl EcssTmSenderCore + ?Sized),
|
||||
sender: &(impl EcssTmSender + ?Sized),
|
||||
token: VerificationToken<TcStateAccepted>,
|
||||
params: FailParams,
|
||||
) -> Result<(), EcssTmtcError>;
|
||||
|
||||
fn step_success(
|
||||
&self,
|
||||
sender: &(impl EcssTmSenderCore + ?Sized),
|
||||
sender: &(impl EcssTmSender + ?Sized),
|
||||
token: &VerificationToken<TcStateStarted>,
|
||||
time_stamp: &[u8],
|
||||
step: impl EcssEnumeration,
|
||||
@ -461,21 +459,21 @@ pub trait VerificationReportingProvider {
|
||||
|
||||
fn step_failure(
|
||||
&self,
|
||||
sender: &(impl EcssTmSenderCore + ?Sized),
|
||||
sender: &(impl EcssTmSender + ?Sized),
|
||||
token: VerificationToken<TcStateStarted>,
|
||||
params: FailParamsWithStep,
|
||||
) -> Result<(), EcssTmtcError>;
|
||||
|
||||
fn completion_success<TcState: WasAtLeastAccepted + Copy>(
|
||||
&self,
|
||||
sender: &(impl EcssTmSenderCore + ?Sized),
|
||||
sender: &(impl EcssTmSender + ?Sized),
|
||||
token: VerificationToken<TcState>,
|
||||
time_stamp: &[u8],
|
||||
) -> Result<(), EcssTmtcError>;
|
||||
|
||||
fn completion_failure<TcState: WasAtLeastAccepted + Copy>(
|
||||
&self,
|
||||
sender: &(impl EcssTmSenderCore + ?Sized),
|
||||
sender: &(impl EcssTmSender + ?Sized),
|
||||
token: VerificationToken<TcState>,
|
||||
params: FailParams,
|
||||
) -> Result<(), EcssTmtcError>;
|
||||
@ -886,7 +884,7 @@ pub mod alloc_mod {
|
||||
use spacepackets::ecss::PusError;
|
||||
|
||||
use super::*;
|
||||
use crate::{pus::PusTmVariant, ComponentId};
|
||||
use crate::pus::PusTmVariant;
|
||||
use core::cell::RefCell;
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -1027,7 +1025,7 @@ pub mod alloc_mod {
|
||||
/// Package and send a PUS TM\[1, 1\] packet, see 8.1.2.1 of the PUS standard
|
||||
fn acceptance_success(
|
||||
&self,
|
||||
sender: &(impl EcssTmSenderCore + ?Sized),
|
||||
sender: &(impl EcssTmSender + ?Sized),
|
||||
token: VerificationToken<TcStateNone>,
|
||||
time_stamp: &[u8],
|
||||
) -> Result<VerificationToken<TcStateAccepted>, EcssTmtcError> {
|
||||
@ -1044,7 +1042,7 @@ pub mod alloc_mod {
|
||||
/// Package and send a PUS TM\[1, 2\] packet, see 8.1.2.2 of the PUS standard
|
||||
fn acceptance_failure(
|
||||
&self,
|
||||
sender: &(impl EcssTmSenderCore + ?Sized),
|
||||
sender: &(impl EcssTmSender + ?Sized),
|
||||
token: VerificationToken<TcStateNone>,
|
||||
params: FailParams,
|
||||
) -> Result<(), EcssTmtcError> {
|
||||
@ -1063,7 +1061,7 @@ pub mod alloc_mod {
|
||||
/// Requires a token previously acquired by calling [Self::acceptance_success].
|
||||
fn start_success(
|
||||
&self,
|
||||
sender: &(impl EcssTmSenderCore + ?Sized),
|
||||
sender: &(impl EcssTmSender + ?Sized),
|
||||
token: VerificationToken<TcStateAccepted>,
|
||||
time_stamp: &[u8],
|
||||
) -> Result<VerificationToken<TcStateStarted>, EcssTmtcError> {
|
||||
@ -1083,7 +1081,7 @@ pub mod alloc_mod {
|
||||
/// the token because verification handling is done.
|
||||
fn start_failure(
|
||||
&self,
|
||||
sender: &(impl EcssTmSenderCore + ?Sized),
|
||||
sender: &(impl EcssTmSender + ?Sized),
|
||||
token: VerificationToken<TcStateAccepted>,
|
||||
params: FailParams,
|
||||
) -> Result<(), EcssTmtcError> {
|
||||
@ -1102,7 +1100,7 @@ pub mod alloc_mod {
|
||||
/// Requires a token previously acquired by calling [Self::start_success].
|
||||
fn step_success(
|
||||
&self,
|
||||
sender: &(impl EcssTmSenderCore + ?Sized),
|
||||
sender: &(impl EcssTmSender + ?Sized),
|
||||
token: &VerificationToken<TcStateStarted>,
|
||||
time_stamp: &[u8],
|
||||
step: impl EcssEnumeration,
|
||||
@ -1123,7 +1121,7 @@ pub mod alloc_mod {
|
||||
/// token because verification handling is done.
|
||||
fn step_failure(
|
||||
&self,
|
||||
sender: &(impl EcssTmSenderCore + ?Sized),
|
||||
sender: &(impl EcssTmSender + ?Sized),
|
||||
token: VerificationToken<TcStateStarted>,
|
||||
params: FailParamsWithStep,
|
||||
) -> Result<(), EcssTmtcError> {
|
||||
@ -1144,7 +1142,7 @@ pub mod alloc_mod {
|
||||
fn completion_success<TcState: WasAtLeastAccepted + Copy>(
|
||||
&self,
|
||||
// sender_id: ComponentId,
|
||||
sender: &(impl EcssTmSenderCore + ?Sized),
|
||||
sender: &(impl EcssTmSender + ?Sized),
|
||||
token: VerificationToken<TcState>,
|
||||
time_stamp: &[u8],
|
||||
) -> Result<(), EcssTmtcError> {
|
||||
@ -1164,7 +1162,7 @@ pub mod alloc_mod {
|
||||
/// token because verification handling is done.
|
||||
fn completion_failure<TcState: WasAtLeastAccepted + Copy>(
|
||||
&self,
|
||||
sender: &(impl EcssTmSenderCore + ?Sized),
|
||||
sender: &(impl EcssTmSender + ?Sized),
|
||||
token: VerificationToken<TcState>,
|
||||
params: FailParams,
|
||||
) -> Result<(), EcssTmtcError> {
|
||||
@ -1269,7 +1267,7 @@ pub mod test_util {
|
||||
|
||||
fn acceptance_success(
|
||||
&self,
|
||||
_sender: &(impl EcssTmSenderCore + ?Sized),
|
||||
_sender: &(impl EcssTmSender + ?Sized),
|
||||
token: VerificationToken<TcStateNone>,
|
||||
time_stamp: &[u8],
|
||||
) -> Result<VerificationToken<TcStateAccepted>, EcssTmtcError> {
|
||||
@ -1288,7 +1286,7 @@ pub mod test_util {
|
||||
|
||||
fn acceptance_failure(
|
||||
&self,
|
||||
_sender: &(impl EcssTmSenderCore + ?Sized),
|
||||
_sender: &(impl EcssTmSender + ?Sized),
|
||||
token: VerificationToken<TcStateNone>,
|
||||
params: FailParams,
|
||||
) -> Result<(), EcssTmtcError> {
|
||||
@ -1306,7 +1304,7 @@ pub mod test_util {
|
||||
|
||||
fn start_success(
|
||||
&self,
|
||||
_sender: &(impl EcssTmSenderCore + ?Sized),
|
||||
_sender: &(impl EcssTmSender + ?Sized),
|
||||
token: VerificationToken<TcStateAccepted>,
|
||||
time_stamp: &[u8],
|
||||
) -> Result<VerificationToken<TcStateStarted>, EcssTmtcError> {
|
||||
@ -1325,7 +1323,7 @@ pub mod test_util {
|
||||
|
||||
fn start_failure(
|
||||
&self,
|
||||
_sender: &(impl EcssTmSenderCore + ?Sized),
|
||||
_sender: &(impl EcssTmSender + ?Sized),
|
||||
token: VerificationToken<super::TcStateAccepted>,
|
||||
params: FailParams,
|
||||
) -> Result<(), EcssTmtcError> {
|
||||
@ -1343,7 +1341,7 @@ pub mod test_util {
|
||||
|
||||
fn step_success(
|
||||
&self,
|
||||
_sender: &(impl EcssTmSenderCore + ?Sized),
|
||||
_sender: &(impl EcssTmSender + ?Sized),
|
||||
token: &VerificationToken<TcStateStarted>,
|
||||
time_stamp: &[u8],
|
||||
step: impl EcssEnumeration,
|
||||
@ -1363,7 +1361,7 @@ pub mod test_util {
|
||||
|
||||
fn step_failure(
|
||||
&self,
|
||||
_sender: &(impl EcssTmSenderCore + ?Sized),
|
||||
_sender: &(impl EcssTmSender + ?Sized),
|
||||
token: VerificationToken<TcStateStarted>,
|
||||
params: FailParamsWithStep,
|
||||
) -> Result<(), EcssTmtcError> {
|
||||
@ -1381,7 +1379,7 @@ pub mod test_util {
|
||||
|
||||
fn completion_success<TcState: super::WasAtLeastAccepted + Copy>(
|
||||
&self,
|
||||
_sender: &(impl EcssTmSenderCore + ?Sized),
|
||||
_sender: &(impl EcssTmSender + ?Sized),
|
||||
token: VerificationToken<TcState>,
|
||||
time_stamp: &[u8],
|
||||
) -> Result<(), EcssTmtcError> {
|
||||
@ -1397,7 +1395,7 @@ pub mod test_util {
|
||||
|
||||
fn completion_failure<TcState: WasAtLeastAccepted + Copy>(
|
||||
&self,
|
||||
_sender: &(impl EcssTmSenderCore + ?Sized),
|
||||
_sender: &(impl EcssTmSender + ?Sized),
|
||||
token: VerificationToken<TcState>,
|
||||
params: FailParams,
|
||||
) -> Result<(), EcssTmtcError> {
|
||||
@ -1636,17 +1634,17 @@ pub mod test_util {
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod tests {
|
||||
use crate::pool::{StaticMemoryPool, StaticPoolConfig};
|
||||
use crate::pool::{SharedStaticMemoryPool, StaticMemoryPool, StaticPoolConfig};
|
||||
use crate::pus::test_util::{TEST_APID, TEST_COMPONENT_ID_0};
|
||||
use crate::pus::tests::CommonTmInfo;
|
||||
use crate::pus::verification::{
|
||||
EcssTmSenderCore, EcssTmtcError, FailParams, FailParamsWithStep, RequestId, TcStateNone,
|
||||
EcssTmSender, EcssTmtcError, FailParams, FailParamsWithStep, RequestId, TcStateNone,
|
||||
VerificationReporter, VerificationReporterCfg, VerificationToken,
|
||||
};
|
||||
use crate::pus::{ChannelWithId, MpscTmInSharedPoolSender, PusTmVariant};
|
||||
use crate::pus::{ChannelWithId, PusTmVariant};
|
||||
use crate::request::MessageMetadata;
|
||||
use crate::seq_count::{CcsdsSimpleSeqCountProvider, SequenceCountProviderCore};
|
||||
use crate::tmtc::tm_helper::SharedTmPool;
|
||||
use crate::tmtc::{PacketSenderWithSharedPool, SharedPacketPool};
|
||||
use crate::ComponentId;
|
||||
use alloc::format;
|
||||
use spacepackets::ecss::tc::{PusTcCreator, PusTcReader, PusTcSecondaryHeader};
|
||||
@ -1658,7 +1656,7 @@ pub mod tests {
|
||||
use spacepackets::{ByteConversionError, SpHeader};
|
||||
use std::cell::RefCell;
|
||||
use std::collections::VecDeque;
|
||||
use std::sync::mpsc;
|
||||
use std::sync::{mpsc, RwLock};
|
||||
use std::vec;
|
||||
use std::vec::Vec;
|
||||
|
||||
@ -1694,7 +1692,7 @@ pub mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
impl EcssTmSenderCore for TestSender {
|
||||
impl EcssTmSender for TestSender {
|
||||
fn send_tm(&self, sender_id: ComponentId, tm: PusTmVariant) -> Result<(), EcssTmtcError> {
|
||||
match tm {
|
||||
PusTmVariant::InStore(_) => {
|
||||
@ -2128,9 +2126,10 @@ pub mod tests {
|
||||
#[test]
|
||||
fn test_mpsc_verif_send() {
|
||||
let pool = StaticMemoryPool::new(StaticPoolConfig::new(vec![(8, 8)], false));
|
||||
let shared_tm_store = SharedTmPool::new(pool);
|
||||
let (tx, _) = mpsc::channel();
|
||||
let mpsc_verif_sender = MpscTmInSharedPoolSender::new(shared_tm_store, tx);
|
||||
let shared_tm_store =
|
||||
SharedPacketPool::new(&SharedStaticMemoryPool::new(RwLock::new(pool)));
|
||||
let (tx, _) = mpsc::sync_channel(10);
|
||||
let mpsc_verif_sender = PacketSenderWithSharedPool::new(tx, shared_tm_store);
|
||||
is_send(&mpsc_verif_sender);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user