Larger update
- ComponentId is u32 now - Simplified TCP servers
This commit is contained in:
@@ -484,6 +484,7 @@ mod tests {
|
|||||||
sync::{mpsc, Arc},
|
sync::{mpsc, Arc},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use arbitrary_int::u21;
|
||||||
use satrs::{
|
use satrs::{
|
||||||
mode::{ModeReply, ModeRequest},
|
mode::{ModeReply, ModeRequest},
|
||||||
mode_tree::ModeParent,
|
mode_tree::ModeParent,
|
||||||
@@ -574,7 +575,7 @@ mod tests {
|
|||||||
let (request_tx, request_rx) = mpsc::sync_channel(5);
|
let (request_tx, request_rx) = mpsc::sync_channel(5);
|
||||||
let (reply_tx_to_pus, reply_rx_to_pus) = mpsc::sync_channel(5);
|
let (reply_tx_to_pus, reply_rx_to_pus) = mpsc::sync_channel(5);
|
||||||
let (reply_tx_to_parent, reply_rx_to_parent) = mpsc::sync_channel(5);
|
let (reply_tx_to_parent, reply_rx_to_parent) = mpsc::sync_channel(5);
|
||||||
let id = UniqueApidTargetId::new(Apid::Acs.raw_value(), 1);
|
let id = UniqueApidTargetId::new(Apid::Acs.raw_value(), u21::new(1));
|
||||||
let mode_node = ModeRequestHandlerMpscBounded::new(id.into(), request_rx);
|
let mode_node = ModeRequestHandlerMpscBounded::new(id.into(), request_rx);
|
||||||
let (composite_request_tx, composite_request_rx) = mpsc::channel();
|
let (composite_request_tx, composite_request_rx) = mpsc::channel();
|
||||||
let (hk_reply_tx, hk_reply_rx) = mpsc::sync_channel(10);
|
let (hk_reply_tx, hk_reply_rx) = mpsc::sync_channel(10);
|
||||||
|
|||||||
@@ -506,6 +506,7 @@ impl<ComInterface: SerialInterface> ModeChild for PcduHandler<ComInterface> {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use std::sync::mpsc;
|
use std::sync::mpsc;
|
||||||
|
|
||||||
|
use arbitrary_int::u21;
|
||||||
use satrs::{
|
use satrs::{
|
||||||
mode::ModeRequest, power::SwitchStateBinary, request::GenericMessage, tmtc::PacketAsVec,
|
mode::ModeRequest, power::SwitchStateBinary, request::GenericMessage, tmtc::PacketAsVec,
|
||||||
};
|
};
|
||||||
@@ -572,7 +573,7 @@ mod tests {
|
|||||||
let (switch_request_tx, switch_reqest_rx) = mpsc::channel();
|
let (switch_request_tx, switch_reqest_rx) = mpsc::channel();
|
||||||
let shared_switch_map = Arc::new(Mutex::new(SwitchSet::default()));
|
let shared_switch_map = Arc::new(Mutex::new(SwitchSet::default()));
|
||||||
let mut handler = PcduHandler::new(
|
let mut handler = PcduHandler::new(
|
||||||
UniqueApidTargetId::new(Apid::Eps.raw_value(), 0),
|
UniqueApidTargetId::new(Apid::Eps.raw_value(), u21::new(0)),
|
||||||
"TEST_PCDU",
|
"TEST_PCDU",
|
||||||
mode_node,
|
mode_node,
|
||||||
composite_request_rx,
|
composite_request_rx,
|
||||||
|
|||||||
@@ -218,6 +218,7 @@ impl<TmSender: EcssTmSender> EventHandler<TmSender> {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use arbitrary_int::u21;
|
||||||
use satrs::{
|
use satrs::{
|
||||||
events_legacy::EventU32,
|
events_legacy::EventU32,
|
||||||
pus::verification::VerificationReporterConfig,
|
pus::verification::VerificationReporterConfig,
|
||||||
@@ -227,7 +228,7 @@ mod tests {
|
|||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
const TEST_CREATOR_ID: UniqueApidTargetId = UniqueApidTargetId::new(u11::new(1), 2);
|
const TEST_CREATOR_ID: UniqueApidTargetId = UniqueApidTargetId::new(u11::new(1), u21::new(2));
|
||||||
const TEST_EVENT: EventU32 = EventU32::new(satrs::events_legacy::Severity::Info, 1, 1);
|
const TEST_EVENT: EventU32 = EventU32::new(satrs::events_legacy::Severity::Info, 1, 1);
|
||||||
|
|
||||||
pub struct EventManagementTestbench {
|
pub struct EventManagementTestbench {
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use arbitrary_int::traits::Integer as _;
|
||||||
use derive_new::new;
|
use derive_new::new;
|
||||||
use satrs::hk::UniqueId;
|
use satrs::hk::UniqueId;
|
||||||
use satrs::request::UniqueApidTargetId;
|
use satrs::request::UniqueApidTargetId;
|
||||||
@@ -29,7 +30,7 @@ impl HkUniqueId {
|
|||||||
expected: 8,
|
expected: 8,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
buf[0..4].copy_from_slice(&self.target_id.unique_id.to_be_bytes());
|
buf[0..4].copy_from_slice(&self.target_id.unique_id.as_u32().to_be_bytes());
|
||||||
buf[4..8].copy_from_slice(&self.set_id.to_be_bytes());
|
buf[4..8].copy_from_slice(&self.set_id.to_be_bytes());
|
||||||
|
|
||||||
Ok(8)
|
Ok(8)
|
||||||
@@ -55,7 +56,7 @@ impl PusHkHelper {
|
|||||||
) -> Result<PusTmCreator<'a, 'b>, ByteConversionError> {
|
) -> Result<PusTmCreator<'a, 'b>, ByteConversionError> {
|
||||||
let sec_header =
|
let sec_header =
|
||||||
PusTmSecondaryHeader::new(3, hk::Subservice::TmHkPacket as u8, 0, 0, timestamp);
|
PusTmSecondaryHeader::new(3, hk::Subservice::TmHkPacket as u8, 0, 0, timestamp);
|
||||||
buf[0..4].copy_from_slice(&self.component_id.unique_id.to_be_bytes());
|
buf[0..4].copy_from_slice(&self.component_id.unique_id.as_u32().to_be_bytes());
|
||||||
buf[4..8].copy_from_slice(&set_id.to_be_bytes());
|
buf[4..8].copy_from_slice(&set_id.to_be_bytes());
|
||||||
let (_, second_half) = buf.split_at_mut(8);
|
let (_, second_half) = buf.split_at_mut(8);
|
||||||
let hk_data_len = hk_data_writer(second_half)?;
|
let hk_data_len = hk_data_writer(second_half)?;
|
||||||
|
|||||||
@@ -14,7 +14,8 @@ pub enum Apid {
|
|||||||
|
|
||||||
pub mod acs {
|
pub mod acs {
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
|
#[bitbybit::bitenum(u21, exhaustive = false)]
|
||||||
pub enum Id {
|
pub enum Id {
|
||||||
Subsystem = 1,
|
Subsystem = 1,
|
||||||
Assembly = 2,
|
Assembly = 2,
|
||||||
@@ -23,30 +24,32 @@ pub mod acs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub const SUBSYSTEM: super::UniqueApidTargetId =
|
pub const SUBSYSTEM: super::UniqueApidTargetId =
|
||||||
super::UniqueApidTargetId::new(super::Apid::Acs.raw_value(), Id::Subsystem as u32);
|
super::UniqueApidTargetId::new(super::Apid::Acs.raw_value(), Id::Subsystem.raw_value());
|
||||||
pub const ASSEMBLY: super::UniqueApidTargetId =
|
pub const ASSEMBLY: super::UniqueApidTargetId =
|
||||||
super::UniqueApidTargetId::new(super::Apid::Acs.raw_value(), Id::Assembly as u32);
|
super::UniqueApidTargetId::new(super::Apid::Acs.raw_value(), Id::Assembly.raw_value());
|
||||||
pub const MGM0: super::UniqueApidTargetId =
|
pub const MGM0: super::UniqueApidTargetId =
|
||||||
super::UniqueApidTargetId::new(super::Apid::Acs.raw_value(), Id::Mgm0 as u32);
|
super::UniqueApidTargetId::new(super::Apid::Acs.raw_value(), Id::Mgm0.raw_value());
|
||||||
pub const MGM1: super::UniqueApidTargetId =
|
pub const MGM1: super::UniqueApidTargetId =
|
||||||
super::UniqueApidTargetId::new(super::Apid::Acs.raw_value(), Id::Mgm1 as u32);
|
super::UniqueApidTargetId::new(super::Apid::Acs.raw_value(), Id::Mgm1.raw_value());
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod eps {
|
pub mod eps {
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
|
#[bitbybit::bitenum(u21, exhaustive = false)]
|
||||||
pub enum Id {
|
pub enum Id {
|
||||||
Pcdu = 0,
|
Pcdu = 0,
|
||||||
Subsystem = 1,
|
Subsystem = 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const PCDU: super::UniqueApidTargetId =
|
pub const PCDU: super::UniqueApidTargetId =
|
||||||
super::UniqueApidTargetId::new(super::Apid::Eps.raw_value(), Id::Pcdu as u32);
|
super::UniqueApidTargetId::new(super::Apid::Eps.raw_value(), Id::Pcdu.raw_value());
|
||||||
pub const SUBSYSTEM: super::UniqueApidTargetId =
|
pub const SUBSYSTEM: super::UniqueApidTargetId =
|
||||||
super::UniqueApidTargetId::new(super::Apid::Eps.raw_value(), Id::Subsystem as u32);
|
super::UniqueApidTargetId::new(super::Apid::Eps.raw_value(), Id::Subsystem.raw_value());
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod generic_pus {
|
pub mod generic_pus {
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
|
#[bitbybit::bitenum(u21, exhaustive = false)]
|
||||||
pub enum Id {
|
pub enum Id {
|
||||||
PusEventManagement = 0,
|
PusEventManagement = 0,
|
||||||
PusRouting = 1,
|
PusRouting = 1,
|
||||||
@@ -58,39 +61,49 @@ pub mod generic_pus {
|
|||||||
|
|
||||||
pub const PUS_EVENT_MANAGEMENT: super::UniqueApidTargetId = super::UniqueApidTargetId::new(
|
pub const PUS_EVENT_MANAGEMENT: super::UniqueApidTargetId = super::UniqueApidTargetId::new(
|
||||||
super::Apid::GenericPus.raw_value(),
|
super::Apid::GenericPus.raw_value(),
|
||||||
Id::PusEventManagement as u32,
|
Id::PusEventManagement.raw_value(),
|
||||||
|
);
|
||||||
|
pub const PUS_ROUTING: super::UniqueApidTargetId = super::UniqueApidTargetId::new(
|
||||||
|
super::Apid::GenericPus.raw_value(),
|
||||||
|
Id::PusRouting.raw_value(),
|
||||||
|
);
|
||||||
|
pub const PUS_TEST: super::UniqueApidTargetId = super::UniqueApidTargetId::new(
|
||||||
|
super::Apid::GenericPus.raw_value(),
|
||||||
|
Id::PusTest.raw_value(),
|
||||||
|
);
|
||||||
|
pub const PUS_ACTION: super::UniqueApidTargetId = super::UniqueApidTargetId::new(
|
||||||
|
super::Apid::GenericPus.raw_value(),
|
||||||
|
Id::PusAction.raw_value(),
|
||||||
|
);
|
||||||
|
pub const PUS_MODE: super::UniqueApidTargetId = super::UniqueApidTargetId::new(
|
||||||
|
super::Apid::GenericPus.raw_value(),
|
||||||
|
Id::PusMode.raw_value(),
|
||||||
);
|
);
|
||||||
pub const PUS_ROUTING: super::UniqueApidTargetId =
|
|
||||||
super::UniqueApidTargetId::new(super::Apid::GenericPus.raw_value(), Id::PusRouting as u32);
|
|
||||||
pub const PUS_TEST: super::UniqueApidTargetId =
|
|
||||||
super::UniqueApidTargetId::new(super::Apid::GenericPus.raw_value(), Id::PusTest as u32);
|
|
||||||
pub const PUS_ACTION: super::UniqueApidTargetId =
|
|
||||||
super::UniqueApidTargetId::new(super::Apid::GenericPus.raw_value(), Id::PusAction as u32);
|
|
||||||
pub const PUS_MODE: super::UniqueApidTargetId =
|
|
||||||
super::UniqueApidTargetId::new(super::Apid::GenericPus.raw_value(), Id::PusMode as u32);
|
|
||||||
pub const PUS_HK: super::UniqueApidTargetId =
|
pub const PUS_HK: super::UniqueApidTargetId =
|
||||||
super::UniqueApidTargetId::new(super::Apid::GenericPus.raw_value(), Id::PusHk as u32);
|
super::UniqueApidTargetId::new(super::Apid::GenericPus.raw_value(), Id::PusHk.raw_value());
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod sched {
|
pub mod sched {
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
|
#[bitbybit::bitenum(u21, exhaustive = false)]
|
||||||
pub enum Id {
|
pub enum Id {
|
||||||
PusSched = 0,
|
PusSched = 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const PUS_SCHED: super::UniqueApidTargetId =
|
pub const PUS_SCHED: super::UniqueApidTargetId =
|
||||||
super::UniqueApidTargetId::new(super::Apid::Sched.raw_value(), Id::PusSched as u32);
|
super::UniqueApidTargetId::new(super::Apid::Sched.raw_value(), Id::PusSched.raw_value());
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod tmtc {
|
pub mod tmtc {
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
|
#[bitbybit::bitenum(u21, exhaustive = false)]
|
||||||
pub enum Id {
|
pub enum Id {
|
||||||
UdpServer = 0,
|
UdpServer = 0,
|
||||||
TcpServer = 1,
|
TcpServer = 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const UDP_SERVER: super::UniqueApidTargetId =
|
pub const UDP_SERVER: super::UniqueApidTargetId =
|
||||||
super::UniqueApidTargetId::new(super::Apid::Tmtc.raw_value(), Id::UdpServer as u32);
|
super::UniqueApidTargetId::new(super::Apid::Tmtc.raw_value(), Id::UdpServer.raw_value());
|
||||||
pub const TCP_SERVER: super::UniqueApidTargetId =
|
pub const TCP_SERVER: super::UniqueApidTargetId =
|
||||||
super::UniqueApidTargetId::new(super::Apid::Tmtc.raw_value(), Id::TcpServer as u32);
|
super::UniqueApidTargetId::new(super::Apid::Tmtc.raw_value(), Id::TcpServer.raw_value());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ use std::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use log::{info, warn};
|
use log::{info, warn};
|
||||||
use satrs::tmtc::StoreAndSendError;
|
use satrs::hal::std::tcp_spacepackets_server::CcsdsPacketParser;
|
||||||
use satrs::{
|
use satrs::{
|
||||||
encoding::ccsds::{SpValidity, SpacePacketValidator},
|
encoding::ccsds::{SpValidity, SpacePacketValidator},
|
||||||
hal::std::tcp_server::{HandledConnectionHandler, ServerConfig, TcpSpacepacketsServer},
|
hal::std::tcp_server::{HandledConnectionHandler, ServerConfig, TcpSpacepacketsServer},
|
||||||
@@ -103,16 +103,14 @@ impl PacketSource for SyncTcpTmSource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type TcpServer<ReceivesTc, SendError> = TcpSpacepacketsServer<
|
pub type TcpServer<ReceivesTc> = TcpSpacepacketsServer<
|
||||||
SyncTcpTmSource,
|
SyncTcpTmSource,
|
||||||
ReceivesTc,
|
ReceivesTc,
|
||||||
SimplePacketValidator,
|
SimplePacketValidator,
|
||||||
ConnectionFinishedHandler,
|
ConnectionFinishedHandler,
|
||||||
(),
|
|
||||||
SendError,
|
|
||||||
>;
|
>;
|
||||||
|
|
||||||
pub struct TcpTask(pub TcpServer<TmTcSender, StoreAndSendError>);
|
pub struct TcpTask(pub TcpServer<TmTcSender>);
|
||||||
|
|
||||||
impl TcpTask {
|
impl TcpTask {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
@@ -124,8 +122,7 @@ impl TcpTask {
|
|||||||
Ok(Self(TcpSpacepacketsServer::new(
|
Ok(Self(TcpSpacepacketsServer::new(
|
||||||
cfg,
|
cfg,
|
||||||
tm_source,
|
tm_source,
|
||||||
tc_sender,
|
CcsdsPacketParser::new(cfg.id, 2048, tc_sender, SimplePacketValidator { valid_ids }),
|
||||||
SimplePacketValidator { valid_ids },
|
|
||||||
ConnectionFinishedHandler::default(),
|
ConnectionFinishedHandler::default(),
|
||||||
None,
|
None,
|
||||||
)?))
|
)?))
|
||||||
|
|||||||
@@ -5,7 +5,8 @@ use std::sync::mpsc;
|
|||||||
use log::{info, warn};
|
use log::{info, warn};
|
||||||
use satrs::hal::std::udp_server::{ReceiveResult, UdpTcServer};
|
use satrs::hal::std::udp_server::{ReceiveResult, UdpTcServer};
|
||||||
use satrs::pus::HandlingStatus;
|
use satrs::pus::HandlingStatus;
|
||||||
use satrs::tmtc::{PacketAsVec, StoreAndSendError};
|
use satrs::queue::GenericSendError;
|
||||||
|
use satrs::tmtc::PacketAsVec;
|
||||||
|
|
||||||
use satrs::pool::{PoolProviderWithGuards, SharedStaticMemoryPool};
|
use satrs::pool::{PoolProviderWithGuards, SharedStaticMemoryPool};
|
||||||
use satrs::tmtc::PacketInPool;
|
use satrs::tmtc::PacketInPool;
|
||||||
@@ -68,7 +69,7 @@ impl UdpTmHandler for DynamicUdpTmHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct UdpTmtcServer<TmHandler: UdpTmHandler> {
|
pub struct UdpTmtcServer<TmHandler: UdpTmHandler> {
|
||||||
pub udp_tc_server: UdpTcServer<TmTcSender, StoreAndSendError>,
|
pub udp_tc_server: UdpTcServer<TmTcSender, GenericSendError>,
|
||||||
pub tm_handler: TmHandler,
|
pub tm_handler: TmHandler,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -270,6 +270,7 @@ impl TargetedPusService for ActionServiceWrapper {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use arbitrary_int::traits::Integer as _;
|
||||||
use satrs::pus::test_util::{
|
use satrs::pus::test_util::{
|
||||||
TEST_APID, TEST_COMPONENT_ID_0, TEST_COMPONENT_ID_1, TEST_UNIQUE_ID_0, TEST_UNIQUE_ID_1,
|
TEST_APID, TEST_COMPONENT_ID_0, TEST_COMPONENT_ID_1, TEST_UNIQUE_ID_0, TEST_UNIQUE_ID_1,
|
||||||
};
|
};
|
||||||
@@ -452,7 +453,7 @@ mod tests {
|
|||||||
let sec_header = PusTcSecondaryHeader::new_simple(8, 128);
|
let sec_header = PusTcSecondaryHeader::new_simple(8, 128);
|
||||||
let action_id = 5_u32;
|
let action_id = 5_u32;
|
||||||
let mut app_data: [u8; 8] = [0; 8];
|
let mut app_data: [u8; 8] = [0; 8];
|
||||||
app_data[0..4].copy_from_slice(&TEST_UNIQUE_ID_1.to_be_bytes());
|
app_data[0..4].copy_from_slice(&TEST_UNIQUE_ID_1.as_u32().to_be_bytes());
|
||||||
app_data[4..8].copy_from_slice(&action_id.to_be_bytes());
|
app_data[4..8].copy_from_slice(&action_id.to_be_bytes());
|
||||||
let pus8_packet =
|
let pus8_packet =
|
||||||
PusTcCreator::new(sp_header, sec_header, &app_data, CreatorConfig::default());
|
PusTcCreator::new(sp_header, sec_header, &app_data, CreatorConfig::default());
|
||||||
@@ -521,7 +522,7 @@ mod tests {
|
|||||||
let action_id = 5_u32;
|
let action_id = 5_u32;
|
||||||
let mut app_data: [u8; 8] = [0; 8];
|
let mut app_data: [u8; 8] = [0; 8];
|
||||||
// Invalid ID, routing should fail.
|
// Invalid ID, routing should fail.
|
||||||
app_data[0..4].copy_from_slice(&TEST_UNIQUE_ID_0.to_be_bytes());
|
app_data[0..4].copy_from_slice(&TEST_UNIQUE_ID_0.as_u32().to_be_bytes());
|
||||||
app_data[4..8].copy_from_slice(&action_id.to_be_bytes());
|
app_data[4..8].copy_from_slice(&action_id.to_be_bytes());
|
||||||
let pus8_packet = PusTcCreator::new(
|
let pus8_packet = PusTcCreator::new(
|
||||||
SpHeader::new_from_apid(TEST_APID),
|
SpHeader::new_from_apid(TEST_APID),
|
||||||
@@ -557,7 +558,7 @@ mod tests {
|
|||||||
let action_id = 5_u32;
|
let action_id = 5_u32;
|
||||||
let mut app_data: [u8; 16] = [0; 16];
|
let mut app_data: [u8; 16] = [0; 16];
|
||||||
// Invalid ID, routing should fail.
|
// Invalid ID, routing should fail.
|
||||||
app_data[0..4].copy_from_slice(&TEST_UNIQUE_ID_0.to_be_bytes());
|
app_data[0..4].copy_from_slice(&TEST_UNIQUE_ID_0.as_u32().to_be_bytes());
|
||||||
app_data[4..8].copy_from_slice(&action_id.to_be_bytes());
|
app_data[4..8].copy_from_slice(&action_id.to_be_bytes());
|
||||||
for i in 0..8 {
|
for i in 0..8 {
|
||||||
app_data[i + 8] = i as u8;
|
app_data[i + 8] = i as u8;
|
||||||
@@ -696,7 +697,7 @@ mod tests {
|
|||||||
ReplyHandlerTestbench::new(TEST_COMPONENT_ID_0.id(), ActionReplyHandler::default());
|
ReplyHandlerTestbench::new(TEST_COMPONENT_ID_0.id(), ActionReplyHandler::default());
|
||||||
let action_reply = ActionReplyPus::new(5_u32, ActionReplyVariant::Completed);
|
let action_reply = ActionReplyPus::new(5_u32, ActionReplyVariant::Completed);
|
||||||
let unrequested_reply =
|
let unrequested_reply =
|
||||||
GenericMessage::new(MessageMetadata::new(10_u32, 15_u64), action_reply);
|
GenericMessage::new(MessageMetadata::new(10_u32, 15_u32), action_reply);
|
||||||
// Right now this function does not do a lot. We simply check that it does not panic or do
|
// Right now this function does not do a lot. We simply check that it does not panic or do
|
||||||
// weird stuff.
|
// weird stuff.
|
||||||
let result = testbench.handle_unrequested_reply(&unrequested_reply);
|
let result = testbench.handle_unrequested_reply(&unrequested_reply);
|
||||||
|
|||||||
@@ -303,7 +303,7 @@ impl TargetedPusService for HkServiceWrapper {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use arbitrary_int::traits::Integer as _;
|
use arbitrary_int::traits::Integer as _;
|
||||||
use arbitrary_int::u14;
|
use arbitrary_int::{u14, u21};
|
||||||
use satrs::pus::test_util::{
|
use satrs::pus::test_util::{
|
||||||
TEST_COMPONENT_ID_0, TEST_COMPONENT_ID_1, TEST_UNIQUE_ID_0, TEST_UNIQUE_ID_1,
|
TEST_COMPONENT_ID_0, TEST_COMPONENT_ID_1, TEST_UNIQUE_ID_0, TEST_UNIQUE_ID_1,
|
||||||
};
|
};
|
||||||
@@ -335,7 +335,7 @@ mod tests {
|
|||||||
let target_id = TEST_UNIQUE_ID_0;
|
let target_id = TEST_UNIQUE_ID_0;
|
||||||
let unique_id = 5_u32;
|
let unique_id = 5_u32;
|
||||||
let mut app_data: [u8; 8] = [0; 8];
|
let mut app_data: [u8; 8] = [0; 8];
|
||||||
app_data[0..4].copy_from_slice(&target_id.to_be_bytes());
|
app_data[0..4].copy_from_slice(&target_id.as_u32().to_be_bytes());
|
||||||
app_data[4..8].copy_from_slice(&unique_id.to_be_bytes());
|
app_data[4..8].copy_from_slice(&unique_id.to_be_bytes());
|
||||||
|
|
||||||
let hk_req = PusTcCreator::new_simple(
|
let hk_req = PusTcCreator::new_simple(
|
||||||
@@ -365,7 +365,7 @@ mod tests {
|
|||||||
let target_id = TEST_UNIQUE_ID_0;
|
let target_id = TEST_UNIQUE_ID_0;
|
||||||
let unique_id = 5_u32;
|
let unique_id = 5_u32;
|
||||||
let mut app_data: [u8; 8] = [0; 8];
|
let mut app_data: [u8; 8] = [0; 8];
|
||||||
app_data[0..4].copy_from_slice(&target_id.to_be_bytes());
|
app_data[0..4].copy_from_slice(&target_id.as_u32().to_be_bytes());
|
||||||
app_data[4..8].copy_from_slice(&unique_id.to_be_bytes());
|
app_data[4..8].copy_from_slice(&unique_id.to_be_bytes());
|
||||||
let mut generic_check = |tc: &PusTcCreator| {
|
let mut generic_check = |tc: &PusTcCreator| {
|
||||||
let accepted_token = hk_bench.add_tc(tc);
|
let accepted_token = hk_bench.add_tc(tc);
|
||||||
@@ -404,7 +404,7 @@ mod tests {
|
|||||||
let target_id = TEST_UNIQUE_ID_0;
|
let target_id = TEST_UNIQUE_ID_0;
|
||||||
let unique_id = 5_u32;
|
let unique_id = 5_u32;
|
||||||
let mut app_data: [u8; 8] = [0; 8];
|
let mut app_data: [u8; 8] = [0; 8];
|
||||||
app_data[0..4].copy_from_slice(&target_id.to_be_bytes());
|
app_data[0..4].copy_from_slice(&target_id.as_u32().to_be_bytes());
|
||||||
app_data[4..8].copy_from_slice(&unique_id.to_be_bytes());
|
app_data[4..8].copy_from_slice(&unique_id.to_be_bytes());
|
||||||
let mut generic_check = |tc: &PusTcCreator| {
|
let mut generic_check = |tc: &PusTcCreator| {
|
||||||
let accepted_token = hk_bench.add_tc(tc);
|
let accepted_token = hk_bench.add_tc(tc);
|
||||||
@@ -444,7 +444,7 @@ mod tests {
|
|||||||
let unique_id = 5_u32;
|
let unique_id = 5_u32;
|
||||||
let mut app_data: [u8; 12] = [0; 12];
|
let mut app_data: [u8; 12] = [0; 12];
|
||||||
let collection_interval_factor = 5_u32;
|
let collection_interval_factor = 5_u32;
|
||||||
app_data[0..4].copy_from_slice(&target_id.to_be_bytes());
|
app_data[0..4].copy_from_slice(&target_id.as_u32().to_be_bytes());
|
||||||
app_data[4..8].copy_from_slice(&unique_id.to_be_bytes());
|
app_data[4..8].copy_from_slice(&unique_id.to_be_bytes());
|
||||||
app_data[8..12].copy_from_slice(&collection_interval_factor.to_be_bytes());
|
app_data[8..12].copy_from_slice(&collection_interval_factor.to_be_bytes());
|
||||||
|
|
||||||
@@ -482,8 +482,8 @@ mod tests {
|
|||||||
fn hk_reply_handler() {
|
fn hk_reply_handler() {
|
||||||
let mut reply_testbench =
|
let mut reply_testbench =
|
||||||
ReplyHandlerTestbench::new(TEST_COMPONENT_ID_0.id(), HkReplyHandler::default());
|
ReplyHandlerTestbench::new(TEST_COMPONENT_ID_0.id(), HkReplyHandler::default());
|
||||||
let sender_id = 2_u64;
|
let sender_id = 2_u32;
|
||||||
let apid_target_id = 3_u32;
|
let apid_target_id = u21::new(3);
|
||||||
let unique_id = 5_u32;
|
let unique_id = 5_u32;
|
||||||
let (req_id, active_req) = reply_testbench.add_tc(TEST_APID, apid_target_id, &[]);
|
let (req_id, active_req) = reply_testbench.add_tc(TEST_APID, apid_target_id, &[]);
|
||||||
let reply = GenericMessage::new(
|
let reply = GenericMessage::new(
|
||||||
@@ -504,7 +504,7 @@ mod tests {
|
|||||||
ReplyHandlerTestbench::new(TEST_COMPONENT_ID_1.id(), HkReplyHandler::default());
|
ReplyHandlerTestbench::new(TEST_COMPONENT_ID_1.id(), HkReplyHandler::default());
|
||||||
let action_reply = HkReply::new(5_u32, HkReplyVariant::Ack);
|
let action_reply = HkReply::new(5_u32, HkReplyVariant::Ack);
|
||||||
let unrequested_reply =
|
let unrequested_reply =
|
||||||
GenericMessage::new(MessageMetadata::new(10_u32, 15_u64), action_reply);
|
GenericMessage::new(MessageMetadata::new(10_u32, 15_u32), action_reply);
|
||||||
// Right now this function does not do a lot. We simply check that it does not panic or do
|
// Right now this function does not do a lot. We simply check that it does not panic or do
|
||||||
// weird stuff.
|
// weird stuff.
|
||||||
let result = testbench.handle_unrequested_reply(&unrequested_reply);
|
let result = testbench.handle_unrequested_reply(&unrequested_reply);
|
||||||
|
|||||||
@@ -531,7 +531,7 @@ pub fn generic_pus_request_timeout_handler(
|
|||||||
pub(crate) mod tests {
|
pub(crate) mod tests {
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use arbitrary_int::u11;
|
use arbitrary_int::{u11, u21};
|
||||||
use satrs::pus::test_util::TEST_COMPONENT_ID_0;
|
use satrs::pus::test_util::TEST_COMPONENT_ID_0;
|
||||||
use satrs::pus::{MpscTmAsVecSender, PusTmVariant};
|
use satrs::pus::{MpscTmAsVecSender, PusTmVariant};
|
||||||
use satrs::request::RequestId;
|
use satrs::request::RequestId;
|
||||||
@@ -593,7 +593,7 @@ pub(crate) mod tests {
|
|||||||
pub fn add_tc(
|
pub fn add_tc(
|
||||||
&mut self,
|
&mut self,
|
||||||
apid: u11,
|
apid: u11,
|
||||||
apid_target: u32,
|
apid_target: u21,
|
||||||
time_stamp: &[u8],
|
time_stamp: &[u8],
|
||||||
) -> (verification::RequestId, ActivePusRequestStd) {
|
) -> (verification::RequestId, ActivePusRequestStd) {
|
||||||
let sp_header = SpHeader::new_from_apid(apid);
|
let sp_header = SpHeader::new_from_apid(apid);
|
||||||
@@ -722,7 +722,7 @@ pub(crate) mod tests {
|
|||||||
token: VerificationToken<TcStateAccepted>,
|
token: VerificationToken<TcStateAccepted>,
|
||||||
time_stamp: &[u8],
|
time_stamp: &[u8],
|
||||||
expected_apid: u11,
|
expected_apid: u11,
|
||||||
expected_apid_target: u32,
|
expected_apid_target: u21,
|
||||||
) -> Result<(ActiveRequestInfo, Request), Converter::Error> {
|
) -> Result<(ActiveRequestInfo, Request), Converter::Error> {
|
||||||
if self.current_packet.is_none() {
|
if self.current_packet.is_none() {
|
||||||
return Err(GenericConversionError::InvalidAppData(
|
return Err(GenericConversionError::InvalidAppData(
|
||||||
|
|||||||
@@ -328,7 +328,7 @@ mod tests {
|
|||||||
let sp_header = SpHeader::new_for_unseg_tc(TEST_APID, u14::ZERO, 0);
|
let sp_header = SpHeader::new_for_unseg_tc(TEST_APID, u14::ZERO, 0);
|
||||||
let sec_header = PusTcSecondaryHeader::new_simple(200, Subservice::TcReadMode as u8);
|
let sec_header = PusTcSecondaryHeader::new_simple(200, Subservice::TcReadMode as u8);
|
||||||
let mut app_data: [u8; 4] = [0; 4];
|
let mut app_data: [u8; 4] = [0; 4];
|
||||||
app_data[0..4].copy_from_slice(&TEST_UNIQUE_ID_0.to_be_bytes());
|
app_data[0..4].copy_from_slice(&TEST_UNIQUE_ID_0.as_u32().to_be_bytes());
|
||||||
let tc = PusTcCreator::new(sp_header, sec_header, &app_data, CreatorConfig::default());
|
let tc = PusTcCreator::new(sp_header, sec_header, &app_data, CreatorConfig::default());
|
||||||
let token = testbench.add_tc(&tc);
|
let token = testbench.add_tc(&tc);
|
||||||
let (_active_req, req) = testbench
|
let (_active_req, req) = testbench
|
||||||
@@ -345,7 +345,7 @@ mod tests {
|
|||||||
let sec_header = PusTcSecondaryHeader::new_simple(200, Subservice::TcSetMode as u8);
|
let sec_header = PusTcSecondaryHeader::new_simple(200, Subservice::TcSetMode as u8);
|
||||||
let mut app_data: [u8; 4 + ModeAndSubmode::RAW_LEN] = [0; 4 + ModeAndSubmode::RAW_LEN];
|
let mut app_data: [u8; 4 + ModeAndSubmode::RAW_LEN] = [0; 4 + ModeAndSubmode::RAW_LEN];
|
||||||
let mode_and_submode = ModeAndSubmode::new(2, 1);
|
let mode_and_submode = ModeAndSubmode::new(2, 1);
|
||||||
app_data[0..4].copy_from_slice(&TEST_UNIQUE_ID_0.to_be_bytes());
|
app_data[0..4].copy_from_slice(&TEST_UNIQUE_ID_0.as_u32().to_be_bytes());
|
||||||
mode_and_submode
|
mode_and_submode
|
||||||
.write_to_be_bytes(&mut app_data[4..])
|
.write_to_be_bytes(&mut app_data[4..])
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@@ -370,7 +370,7 @@ mod tests {
|
|||||||
let sp_header = SpHeader::new_for_unseg_tc(TEST_APID, u14::ZERO, 0);
|
let sp_header = SpHeader::new_for_unseg_tc(TEST_APID, u14::ZERO, 0);
|
||||||
let sec_header = PusTcSecondaryHeader::new_simple(200, Subservice::TcAnnounceMode as u8);
|
let sec_header = PusTcSecondaryHeader::new_simple(200, Subservice::TcAnnounceMode as u8);
|
||||||
let mut app_data: [u8; 4] = [0; 4];
|
let mut app_data: [u8; 4] = [0; 4];
|
||||||
app_data[0..4].copy_from_slice(&TEST_UNIQUE_ID_0.to_be_bytes());
|
app_data[0..4].copy_from_slice(&TEST_UNIQUE_ID_0.as_u32().to_be_bytes());
|
||||||
let tc = PusTcCreator::new(sp_header, sec_header, &app_data, CreatorConfig::default());
|
let tc = PusTcCreator::new(sp_header, sec_header, &app_data, CreatorConfig::default());
|
||||||
let token = testbench.add_tc(&tc);
|
let token = testbench.add_tc(&tc);
|
||||||
let (_active_req, req) = testbench
|
let (_active_req, req) = testbench
|
||||||
@@ -387,7 +387,7 @@ mod tests {
|
|||||||
let sec_header =
|
let sec_header =
|
||||||
PusTcSecondaryHeader::new_simple(200, Subservice::TcAnnounceModeRecursive as u8);
|
PusTcSecondaryHeader::new_simple(200, Subservice::TcAnnounceModeRecursive as u8);
|
||||||
let mut app_data: [u8; 4] = [0; 4];
|
let mut app_data: [u8; 4] = [0; 4];
|
||||||
app_data[0..4].copy_from_slice(&TEST_UNIQUE_ID_0.to_be_bytes());
|
app_data[0..4].copy_from_slice(&TEST_UNIQUE_ID_0.as_u32().to_be_bytes());
|
||||||
let tc = PusTcCreator::new(sp_header, sec_header, &app_data, CreatorConfig::default());
|
let tc = PusTcCreator::new(sp_header, sec_header, &app_data, CreatorConfig::default());
|
||||||
let token = testbench.add_tc(&tc);
|
let token = testbench.add_tc(&tc);
|
||||||
let (_active_req, req) = testbench
|
let (_active_req, req) = testbench
|
||||||
@@ -404,7 +404,7 @@ mod tests {
|
|||||||
);
|
);
|
||||||
let mode_reply = ModeReply::ModeReply(ModeAndSubmode::new(5, 1));
|
let mode_reply = ModeReply::ModeReply(ModeAndSubmode::new(5, 1));
|
||||||
let unrequested_reply =
|
let unrequested_reply =
|
||||||
GenericMessage::new(MessageMetadata::new(10_u32, 15_u64), mode_reply);
|
GenericMessage::new(MessageMetadata::new(10_u32, 15_u32), mode_reply);
|
||||||
// Right now this function does not do a lot. We simply check that it does not panic or do
|
// Right now this function does not do a lot. We simply check that it does not panic or do
|
||||||
// weird stuff.
|
// weird stuff.
|
||||||
let result = testbench.handle_unrequested_reply(&unrequested_reply);
|
let result = testbench.handle_unrequested_reply(&unrequested_reply);
|
||||||
|
|||||||
@@ -66,7 +66,8 @@ impl GenericRequestRouter {
|
|||||||
let apid_target_id = UniqueApidTargetId::from(id);
|
let apid_target_id = UniqueApidTargetId::from(id);
|
||||||
warn!("Target APID for request: {}", apid_target_id.apid);
|
warn!("Target APID for request: {}", apid_target_id.apid);
|
||||||
warn!("Target Unique ID for request: {}", apid_target_id.unique_id);
|
warn!("Target Unique ID for request: {}", apid_target_id.unique_id);
|
||||||
let mut fail_data: [u8; 8] = [0; 8];
|
let mut fail_data: [u8; core::mem::size_of::<ComponentId>()] =
|
||||||
|
[0; core::mem::size_of::<ComponentId>()];
|
||||||
fail_data.copy_from_slice(&id.to_be_bytes());
|
fail_data.copy_from_slice(&id.to_be_bytes());
|
||||||
verif_reporter
|
verif_reporter
|
||||||
.completion_failure(
|
.completion_failure(
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ use satrs::{
|
|||||||
pus::EcssTmSender,
|
pus::EcssTmSender,
|
||||||
queue::GenericSendError,
|
queue::GenericSendError,
|
||||||
spacepackets::ecss::WritablePusPacket,
|
spacepackets::ecss::WritablePusPacket,
|
||||||
tmtc::{PacketAsVec, PacketSenderRaw, PacketSenderWithSharedPool, StoreAndSendError},
|
tmtc::{PacketAsVec, PacketHandler, PacketSenderWithSharedPool},
|
||||||
ComponentId,
|
ComponentId,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -48,26 +48,33 @@ impl EcssTmSender for TmTcSender {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PacketSenderRaw for TmTcSender {
|
impl PacketHandler for TmTcSender {
|
||||||
type Error = StoreAndSendError;
|
type Error = GenericSendError;
|
||||||
|
|
||||||
fn send_packet(&self, sender_id: ComponentId, packet: &[u8]) -> Result<(), Self::Error> {
|
fn handle_packet(&self, sender_id: ComponentId, packet: &[u8]) -> Result<(), Self::Error> {
|
||||||
match self {
|
match self {
|
||||||
TmTcSender::Static(packet_sender_with_shared_pool) => {
|
TmTcSender::Static(packet_sender_with_shared_pool) => {
|
||||||
packet_sender_with_shared_pool.send_packet(sender_id, packet)
|
if let Err(e) = packet_sender_with_shared_pool.handle_packet(sender_id, packet) {
|
||||||
|
log::error!("Error sending packet via Static TM/TC sender: {:?}", e);
|
||||||
}
|
}
|
||||||
TmTcSender::Heap(sync_sender) => sync_sender
|
|
||||||
.send_packet(sender_id, packet)
|
|
||||||
.map_err(StoreAndSendError::Send),
|
|
||||||
TmTcSender::Mock(sender) => sender.send_packet(sender_id, packet),
|
|
||||||
}
|
}
|
||||||
|
TmTcSender::Heap(sync_sender) => {
|
||||||
|
if let Err(e) = sync_sender.handle_packet(sender_id, packet) {
|
||||||
|
log::error!("Error sending packet via Heap TM/TC sender: {:?}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TmTcSender::Mock(sender) => {
|
||||||
|
sender.handle_packet(sender_id, packet).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PacketSenderRaw for MockSender {
|
impl PacketHandler for MockSender {
|
||||||
type Error = StoreAndSendError;
|
type Error = GenericSendError;
|
||||||
|
|
||||||
fn send_packet(&self, sender_id: ComponentId, tc_raw: &[u8]) -> Result<(), Self::Error> {
|
fn handle_packet(&self, sender_id: ComponentId, tc_raw: &[u8]) -> Result<(), Self::Error> {
|
||||||
let mut mut_queue = self.0.borrow_mut();
|
let mut mut_queue = self.0.borrow_mut();
|
||||||
mut_queue.push_back(PacketAsVec::new(sender_id, tc_raw.to_vec()));
|
mut_queue.push_back(PacketAsVec::new(sender_id, tc_raw.to_vec()));
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -12,16 +12,8 @@ license = "Apache-2.0"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
spacepackets = { version = ">=0.14, <=0.16", default-features = false }
|
spacepackets = { version = ">=0.14, <=0.16", default-features = false }
|
||||||
|
serde = { version = "1", default-features = false, optional = true }
|
||||||
[dependencies.serde]
|
defmt = {version = "1", optional = true }
|
||||||
version = "1"
|
|
||||||
default-features = false
|
|
||||||
optional = true
|
|
||||||
|
|
||||||
[dependencies.defmt]
|
|
||||||
version = "1"
|
|
||||||
optional = true
|
|
||||||
|
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
serde = ["dep:serde", "spacepackets/serde"]
|
serde = ["dep:serde", "spacepackets/serde"]
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
|
|
||||||
- Bump `sat-rs` edition to 2024.
|
- Bump `sat-rs` edition to 2024.
|
||||||
- Bumped `spacepackets` to v0.16
|
- Bumped `spacepackets` to v0.16
|
||||||
|
- `ComponentId` is u32 now
|
||||||
|
- Simplified TCP servers
|
||||||
|
|
||||||
## Changed
|
## Changed
|
||||||
|
|
||||||
|
|||||||
@@ -16,14 +16,14 @@ categories = ["aerospace", "aerospace::space-protocols", "no-std", "hardware-sup
|
|||||||
satrs-shared = { version = "0.2", path = "../satrs-shared" }
|
satrs-shared = { version = "0.2", path = "../satrs-shared" }
|
||||||
spacepackets = { version = "0.16", default-features = false }
|
spacepackets = { version = "0.16", default-features = false }
|
||||||
|
|
||||||
delegate = ">0.7, <=0.13"
|
delegate = "0.13"
|
||||||
paste = "1"
|
paste = "1"
|
||||||
derive-new = ">=0.6, <=0.7"
|
derive-new = "0.7"
|
||||||
num_enum = { version = ">0.5, <=0.7", default-features = false }
|
num_enum = { version = "0.7", default-features = false }
|
||||||
cobs = { version = "0.4", default-features = false }
|
cobs = { version = "0.5", default-features = false, features = ["alloc"] }
|
||||||
thiserror = { version = "2", default-features = false }
|
thiserror = { version = "2", default-features = false }
|
||||||
|
|
||||||
hashbrown = { version = ">=0.14, <=0.15", optional = true }
|
hashbrown = { version = "0.16", optional = true }
|
||||||
static_cell = { version = "2" }
|
static_cell = { version = "2" }
|
||||||
heapless = { version = "0.9", optional = true }
|
heapless = { version = "0.9", optional = true }
|
||||||
dyn-clone = { version = "1", optional = true }
|
dyn-clone = { version = "1", optional = true }
|
||||||
|
|||||||
@@ -296,18 +296,18 @@ mod tests {
|
|||||||
fn test_mode_announce() {
|
fn test_mode_announce() {
|
||||||
let mut assy_helper = DevManagerCommandingHelper::new(TransparentDevManagerHook::default());
|
let mut assy_helper = DevManagerCommandingHelper::new(TransparentDevManagerHook::default());
|
||||||
let mode_req_sender = ModeReqSenderMock::default();
|
let mode_req_sender = ModeReqSenderMock::default();
|
||||||
assy_helper.add_mode_child(ExampleId::Id1 as u64, UNKNOWN_MODE);
|
assy_helper.add_mode_child(ExampleId::Id1 as ComponentId, UNKNOWN_MODE);
|
||||||
assy_helper.add_mode_child(ExampleId::Id2 as u64, UNKNOWN_MODE);
|
assy_helper.add_mode_child(ExampleId::Id2 as ComponentId, UNKNOWN_MODE);
|
||||||
assy_helper
|
assy_helper
|
||||||
.send_announce_mode_cmd_to_children(1, &mode_req_sender, false)
|
.send_announce_mode_cmd_to_children(1, &mode_req_sender, false)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(mode_req_sender.requests.borrow().len(), 2);
|
assert_eq!(mode_req_sender.requests.borrow().len(), 2);
|
||||||
let mut req = mode_req_sender.requests.borrow_mut().pop_front().unwrap();
|
let mut req = mode_req_sender.requests.borrow_mut().pop_front().unwrap();
|
||||||
assert_eq!(req.target_id, ExampleId::Id1 as u64);
|
assert_eq!(req.target_id, ExampleId::Id1 as ComponentId);
|
||||||
assert_eq!(req.request_id, 1);
|
assert_eq!(req.request_id, 1);
|
||||||
assert_eq!(req.request, ModeRequest::AnnounceMode);
|
assert_eq!(req.request, ModeRequest::AnnounceMode);
|
||||||
req = mode_req_sender.requests.borrow_mut().pop_front().unwrap();
|
req = mode_req_sender.requests.borrow_mut().pop_front().unwrap();
|
||||||
assert_eq!(req.target_id, ExampleId::Id2 as u64);
|
assert_eq!(req.target_id, ExampleId::Id2 as ComponentId);
|
||||||
assert_eq!(req.request_id, 1);
|
assert_eq!(req.request_id, 1);
|
||||||
assert_eq!(req.request, ModeRequest::AnnounceMode);
|
assert_eq!(req.request, ModeRequest::AnnounceMode);
|
||||||
}
|
}
|
||||||
@@ -316,18 +316,18 @@ mod tests {
|
|||||||
fn test_mode_announce_recursive() {
|
fn test_mode_announce_recursive() {
|
||||||
let mut assy_helper = DevManagerCommandingHelper::new(TransparentDevManagerHook::default());
|
let mut assy_helper = DevManagerCommandingHelper::new(TransparentDevManagerHook::default());
|
||||||
let mode_req_sender = ModeReqSenderMock::default();
|
let mode_req_sender = ModeReqSenderMock::default();
|
||||||
assy_helper.add_mode_child(ExampleId::Id1 as u64, UNKNOWN_MODE);
|
assy_helper.add_mode_child(ExampleId::Id1 as ComponentId, UNKNOWN_MODE);
|
||||||
assy_helper.add_mode_child(ExampleId::Id2 as u64, UNKNOWN_MODE);
|
assy_helper.add_mode_child(ExampleId::Id2 as ComponentId, UNKNOWN_MODE);
|
||||||
assy_helper
|
assy_helper
|
||||||
.send_announce_mode_cmd_to_children(1, &mode_req_sender, true)
|
.send_announce_mode_cmd_to_children(1, &mode_req_sender, true)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(mode_req_sender.requests.borrow().len(), 2);
|
assert_eq!(mode_req_sender.requests.borrow().len(), 2);
|
||||||
let mut req = mode_req_sender.requests.borrow_mut().pop_front().unwrap();
|
let mut req = mode_req_sender.requests.borrow_mut().pop_front().unwrap();
|
||||||
assert_eq!(req.target_id, ExampleId::Id1 as u64);
|
assert_eq!(req.target_id, ExampleId::Id1 as ComponentId);
|
||||||
assert_eq!(req.request_id, 1);
|
assert_eq!(req.request_id, 1);
|
||||||
assert_eq!(req.request, ModeRequest::AnnounceModeRecursive);
|
assert_eq!(req.request, ModeRequest::AnnounceModeRecursive);
|
||||||
req = mode_req_sender.requests.borrow_mut().pop_front().unwrap();
|
req = mode_req_sender.requests.borrow_mut().pop_front().unwrap();
|
||||||
assert_eq!(req.target_id, ExampleId::Id2 as u64);
|
assert_eq!(req.target_id, ExampleId::Id2 as ComponentId);
|
||||||
assert_eq!(req.request_id, 1);
|
assert_eq!(req.request_id, 1);
|
||||||
assert_eq!(req.request, ModeRequest::AnnounceModeRecursive);
|
assert_eq!(req.request, ModeRequest::AnnounceModeRecursive);
|
||||||
}
|
}
|
||||||
@@ -337,12 +337,12 @@ mod tests {
|
|||||||
let mut dev_mgmt_helper =
|
let mut dev_mgmt_helper =
|
||||||
DevManagerCommandingHelper::new(TransparentDevManagerHook::default());
|
DevManagerCommandingHelper::new(TransparentDevManagerHook::default());
|
||||||
let mode_req_sender = ModeReqSenderMock::default();
|
let mode_req_sender = ModeReqSenderMock::default();
|
||||||
dev_mgmt_helper.add_mode_child(ExampleId::Id1 as u64, UNKNOWN_MODE);
|
dev_mgmt_helper.add_mode_child(ExampleId::Id1 as ComponentId, UNKNOWN_MODE);
|
||||||
let expected_mode = ModeAndSubmode::new(ExampleMode::Mode1 as u32, 0);
|
let expected_mode = ModeAndSubmode::new(ExampleMode::Mode1 as u32, 0);
|
||||||
dev_mgmt_helper
|
dev_mgmt_helper
|
||||||
.send_mode_cmd_to_one_child(
|
.send_mode_cmd_to_one_child(
|
||||||
1,
|
1,
|
||||||
ExampleId::Id1 as u64,
|
ExampleId::Id1 as ComponentId,
|
||||||
expected_mode,
|
expected_mode,
|
||||||
false,
|
false,
|
||||||
&mode_req_sender,
|
&mode_req_sender,
|
||||||
@@ -350,7 +350,7 @@ mod tests {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(mode_req_sender.requests.borrow().len(), 1);
|
assert_eq!(mode_req_sender.requests.borrow().len(), 1);
|
||||||
let req = mode_req_sender.requests.borrow_mut().pop_front().unwrap();
|
let req = mode_req_sender.requests.borrow_mut().pop_front().unwrap();
|
||||||
assert_eq!(req.target_id, ExampleId::Id1 as u64);
|
assert_eq!(req.target_id, ExampleId::Id1 as ComponentId);
|
||||||
assert_eq!(req.request_id, 1);
|
assert_eq!(req.request_id, 1);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
req.request,
|
req.request,
|
||||||
@@ -368,7 +368,7 @@ mod tests {
|
|||||||
assert_eq!(ctx.active_request_id, 1);
|
assert_eq!(ctx.active_request_id, 1);
|
||||||
}
|
}
|
||||||
let reply = GenericMessage::new(
|
let reply = GenericMessage::new(
|
||||||
MessageMetadata::new(1, ExampleId::Id1 as u64),
|
MessageMetadata::new(1, ExampleId::Id1 as ComponentId),
|
||||||
ModeReply::ModeReply(expected_mode),
|
ModeReply::ModeReply(expected_mode),
|
||||||
);
|
);
|
||||||
if let DevManagerHelperResult::ModeCommandingDone(ActiveModeCommandContext {
|
if let DevManagerHelperResult::ModeCommandingDone(ActiveModeCommandContext {
|
||||||
@@ -387,15 +387,15 @@ mod tests {
|
|||||||
let mut dev_mgmt_helper =
|
let mut dev_mgmt_helper =
|
||||||
DevManagerCommandingHelper::new(TransparentDevManagerHook::default());
|
DevManagerCommandingHelper::new(TransparentDevManagerHook::default());
|
||||||
let mode_req_sender = ModeReqSenderMock::default();
|
let mode_req_sender = ModeReqSenderMock::default();
|
||||||
dev_mgmt_helper.add_mode_child(ExampleId::Id1 as u64, UNKNOWN_MODE);
|
dev_mgmt_helper.add_mode_child(ExampleId::Id1 as ComponentId, UNKNOWN_MODE);
|
||||||
dev_mgmt_helper.add_mode_child(ExampleId::Id2 as u64, UNKNOWN_MODE);
|
dev_mgmt_helper.add_mode_child(ExampleId::Id2 as ComponentId, UNKNOWN_MODE);
|
||||||
let expected_mode = ModeAndSubmode::new(ExampleMode::Mode2 as u32, 0);
|
let expected_mode = ModeAndSubmode::new(ExampleMode::Mode2 as u32, 0);
|
||||||
dev_mgmt_helper
|
dev_mgmt_helper
|
||||||
.send_mode_cmd_to_all_children(1, expected_mode, false, &mode_req_sender)
|
.send_mode_cmd_to_all_children(1, expected_mode, false, &mode_req_sender)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(mode_req_sender.requests.borrow().len(), 2);
|
assert_eq!(mode_req_sender.requests.borrow().len(), 2);
|
||||||
let req = mode_req_sender.requests.borrow_mut().pop_front().unwrap();
|
let req = mode_req_sender.requests.borrow_mut().pop_front().unwrap();
|
||||||
assert_eq!(req.target_id, ExampleId::Id1 as u64);
|
assert_eq!(req.target_id, ExampleId::Id1 as ComponentId);
|
||||||
assert_eq!(req.request_id, 1);
|
assert_eq!(req.request_id, 1);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
req.request,
|
req.request,
|
||||||
@@ -405,7 +405,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
let req = mode_req_sender.requests.borrow_mut().pop_front().unwrap();
|
let req = mode_req_sender.requests.borrow_mut().pop_front().unwrap();
|
||||||
assert_eq!(req.target_id, ExampleId::Id2 as u64);
|
assert_eq!(req.target_id, ExampleId::Id2 as ComponentId);
|
||||||
assert_eq!(req.request_id, 1);
|
assert_eq!(req.request_id, 1);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
req.request,
|
req.request,
|
||||||
@@ -424,7 +424,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let reply = GenericMessage::new(
|
let reply = GenericMessage::new(
|
||||||
MessageMetadata::new(1, ExampleId::Id1 as u64),
|
MessageMetadata::new(1, ExampleId::Id1 as ComponentId),
|
||||||
ModeReply::ModeReply(expected_mode),
|
ModeReply::ModeReply(expected_mode),
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@@ -432,7 +432,7 @@ mod tests {
|
|||||||
DevManagerHelperResult::Busy
|
DevManagerHelperResult::Busy
|
||||||
);
|
);
|
||||||
let reply = GenericMessage::new(
|
let reply = GenericMessage::new(
|
||||||
MessageMetadata::new(1, ExampleId::Id2 as u64),
|
MessageMetadata::new(1, ExampleId::Id2 as ComponentId),
|
||||||
ModeReply::ModeReply(expected_mode),
|
ModeReply::ModeReply(expected_mode),
|
||||||
);
|
);
|
||||||
if let DevManagerHelperResult::ModeCommandingDone(ActiveModeCommandContext {
|
if let DevManagerHelperResult::ModeCommandingDone(ActiveModeCommandContext {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use spacepackets::SpHeader;
|
use spacepackets::SpHeader;
|
||||||
|
|
||||||
use crate::{ComponentId, tmtc::PacketSenderRaw};
|
use crate::{ComponentId, tmtc::PacketHandler};
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
pub enum SpValidity {
|
pub enum SpValidity {
|
||||||
@@ -24,13 +24,17 @@ pub trait SpacePacketValidator {
|
|||||||
#[derive(Default, Debug, PartialEq, Eq)]
|
#[derive(Default, Debug, PartialEq, Eq)]
|
||||||
pub struct ParseResult {
|
pub struct ParseResult {
|
||||||
pub packets_found: u32,
|
pub packets_found: u32,
|
||||||
/// If an incomplete space packet was found, its start index is indicated by this value.
|
pub parsed_bytes: usize,
|
||||||
pub incomplete_tail_start: Option<usize>,
|
// If an incomplete space packet was found, its start index is indicated by this value.
|
||||||
|
//pub incomplete_packet_start: Option<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This function parses a given buffer for tightly packed CCSDS space packets. It uses the
|
/// This function parses a given buffer for tightly packed CCSDS space packets.
|
||||||
/// [spacepackets::SpHeader] of the CCSDS packets and a user provided [SpacePacketValidator]
|
///
|
||||||
/// to check whether a received space packet is relevant for processing.
|
/// Please note that it is recommended to use a proper data link layer instead to have proper
|
||||||
|
/// packet framing and to allow more reliable recovery from packet loss.
|
||||||
|
/// It uses the [spacepackets::SpHeader] of the CCSDS packets and a user provided
|
||||||
|
/// [SpacePacketValidator] to check whether a received space packet is relevant for processing.
|
||||||
///
|
///
|
||||||
/// This function is also able to deal with broken tail packets at the end as long a the parser
|
/// This function is also able to deal with broken tail packets at the end as long a the parser
|
||||||
/// can read the full 7 bytes which constitue a space packet header plus one byte minimal size.
|
/// can read the full 7 bytes which constitue a space packet header plus one byte minimal size.
|
||||||
@@ -41,17 +45,18 @@ pub struct ParseResult {
|
|||||||
/// [SpacePacketValidator]:
|
/// [SpacePacketValidator]:
|
||||||
///
|
///
|
||||||
/// 1. [SpValidity::Valid]: The parser will forward all packets to the given `packet_sender` and
|
/// 1. [SpValidity::Valid]: The parser will forward all packets to the given `packet_sender` and
|
||||||
/// return the number of packets found.If the [PacketSenderRaw::send_packet] calls fails, the
|
/// return the number of packets found.If the [PacketHandler::handle_packet] calls fails, the
|
||||||
/// error will be returned.
|
/// error will be returned.
|
||||||
/// 2. [SpValidity::Invalid]: The parser assumes that the synchronization is lost and tries to
|
/// 2. [SpValidity::Invalid]: The parser assumes that the synchronization is lost and tries to
|
||||||
/// find the start of a new space packet header by scanning all the following bytes.
|
/// find the start of a new space packet header by scanning all the following bytes.
|
||||||
/// 3. [SpValidity::Skip]: The parser skips the packet using the packet length determined from the
|
/// 3. [SpValidity::Skip]: The parser skips the packet using the packet length determined from the
|
||||||
/// space packet header.
|
/// space packet header.
|
||||||
|
///
|
||||||
pub fn parse_buffer_for_ccsds_space_packets<SendError>(
|
pub fn parse_buffer_for_ccsds_space_packets<SendError>(
|
||||||
buf: &[u8],
|
buf: &[u8],
|
||||||
packet_validator: &(impl SpacePacketValidator + ?Sized),
|
packet_validator: &(impl SpacePacketValidator + ?Sized),
|
||||||
sender_id: ComponentId,
|
sender_id: ComponentId,
|
||||||
packet_sender: &(impl PacketSenderRaw<Error = SendError> + ?Sized),
|
packet_sender: &(impl PacketHandler<Error = SendError> + ?Sized),
|
||||||
) -> Result<ParseResult, SendError> {
|
) -> Result<ParseResult, SendError> {
|
||||||
let mut parse_result = ParseResult::default();
|
let mut parse_result = ParseResult::default();
|
||||||
let mut current_idx = 0;
|
let mut current_idx = 0;
|
||||||
@@ -66,11 +71,12 @@ pub fn parse_buffer_for_ccsds_space_packets<SendError>(
|
|||||||
let packet_size = sp_header.packet_len();
|
let packet_size = sp_header.packet_len();
|
||||||
if (current_idx + packet_size) <= buf_len {
|
if (current_idx + packet_size) <= buf_len {
|
||||||
packet_sender
|
packet_sender
|
||||||
.send_packet(sender_id, &buf[current_idx..current_idx + packet_size])?;
|
.handle_packet(sender_id, &buf[current_idx..current_idx + packet_size])?;
|
||||||
parse_result.packets_found += 1;
|
parse_result.packets_found += 1;
|
||||||
} else {
|
} else {
|
||||||
// Move packet to start of buffer if applicable.
|
// Move packet to start of buffer if applicable.
|
||||||
parse_result.incomplete_tail_start = Some(current_idx);
|
//parse_result.incomplete_packet_start = Some(current_idx);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
current_idx += packet_size;
|
current_idx += packet_size;
|
||||||
continue;
|
continue;
|
||||||
@@ -84,6 +90,7 @@ pub fn parse_buffer_for_ccsds_space_packets<SendError>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
parse_result.parsed_bytes = current_idx;
|
||||||
Ok(parse_result)
|
Ok(parse_result)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -254,8 +261,7 @@ mod tests {
|
|||||||
assert!(parse_result.is_ok());
|
assert!(parse_result.is_ok());
|
||||||
let parse_result = parse_result.unwrap();
|
let parse_result = parse_result.unwrap();
|
||||||
assert_eq!(parse_result.packets_found, 1);
|
assert_eq!(parse_result.packets_found, 1);
|
||||||
assert!(parse_result.incomplete_tail_start.is_some());
|
let incomplete_tail_idx = parse_result.parsed_bytes;
|
||||||
let incomplete_tail_idx = parse_result.incomplete_tail_start.unwrap();
|
|
||||||
assert_eq!(incomplete_tail_idx, packet_len_ping);
|
assert_eq!(incomplete_tail_idx, packet_len_ping);
|
||||||
|
|
||||||
let queue = tc_cacher.tc_queue.borrow();
|
let queue = tc_cacher.tc_queue.borrow();
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use crate::{ComponentId, tmtc::PacketSenderRaw};
|
use crate::{ComponentId, tmtc::PacketHandler};
|
||||||
use cobs::{decode_in_place, encode, max_encoding_length};
|
use cobs::{decode_in_place, encode_including_sentinels, max_encoding_length};
|
||||||
|
|
||||||
/// This function encodes the given packet with COBS and also wraps the encoded packet with
|
/// This function encodes the given packet with COBS and also wraps the encoded packet with
|
||||||
/// the sentinel value 0. It can be used repeatedly on the same encoded buffer by expecting
|
/// the sentinel value 0. It can be used repeatedly on the same encoded buffer by expecting
|
||||||
@@ -37,15 +37,16 @@ pub fn encode_packet_with_cobs(
|
|||||||
if *current_idx + max_encoding_len + 2 > encoded_buf.len() {
|
if *current_idx + max_encoding_len + 2 > encoded_buf.len() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
encoded_buf[*current_idx] = 0;
|
*current_idx += encode_including_sentinels(packet, &mut encoded_buf[*current_idx..]);
|
||||||
*current_idx += 1;
|
|
||||||
*current_idx += encode(packet, &mut encoded_buf[*current_idx..]);
|
|
||||||
encoded_buf[*current_idx] = 0;
|
|
||||||
*current_idx += 1;
|
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This function parses a given buffer for COBS encoded packets. The packet structure is
|
/// This function parses a given buffer for COBS encoded packets.
|
||||||
|
///
|
||||||
|
/// Please note that, it is recommended to use [cobs::CobsDecoderOwned] or [cobs::CobsDecoder]
|
||||||
|
/// instead.
|
||||||
|
///
|
||||||
|
/// The packet structure is
|
||||||
/// expected to be like this, assuming a sentinel value of 0 as the packet delimiter:
|
/// expected to be like this, assuming a sentinel value of 0 as the packet delimiter:
|
||||||
///
|
///
|
||||||
/// 0 | ... Encoded Packet Data ... | 0 | 0 | ... Encoded Packet Data ... | 0
|
/// 0 | ... Encoded Packet Data ... | 0 | 0 | ... Encoded Packet Data ... | 0
|
||||||
@@ -58,7 +59,7 @@ pub fn encode_packet_with_cobs(
|
|||||||
pub fn parse_buffer_for_cobs_encoded_packets<SendError>(
|
pub fn parse_buffer_for_cobs_encoded_packets<SendError>(
|
||||||
buf: &mut [u8],
|
buf: &mut [u8],
|
||||||
sender_id: ComponentId,
|
sender_id: ComponentId,
|
||||||
packet_sender: &(impl PacketSenderRaw<Error = SendError> + ?Sized),
|
packet_sender: &(impl PacketHandler<Error = SendError> + ?Sized),
|
||||||
next_write_idx: &mut usize,
|
next_write_idx: &mut usize,
|
||||||
) -> Result<u32, SendError> {
|
) -> Result<u32, SendError> {
|
||||||
let mut start_index_packet = 0;
|
let mut start_index_packet = 0;
|
||||||
@@ -79,7 +80,7 @@ pub fn parse_buffer_for_cobs_encoded_packets<SendError>(
|
|||||||
let decode_result = decode_in_place(&mut buf[start_index_packet..i]);
|
let decode_result = decode_in_place(&mut buf[start_index_packet..i]);
|
||||||
if let Ok(packet_len) = decode_result {
|
if let Ok(packet_len) = decode_result {
|
||||||
packets_found += 1;
|
packets_found += 1;
|
||||||
packet_sender.send_packet(
|
packet_sender.handle_packet(
|
||||||
sender_id,
|
sender_id,
|
||||||
&buf[start_index_packet..start_index_packet + packet_len],
|
&buf[start_index_packet..start_index_packet + packet_len],
|
||||||
)?;
|
)?;
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ pub(crate) mod tests {
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ComponentId,
|
ComponentId,
|
||||||
tmtc::{PacketAsVec, PacketSenderRaw},
|
tmtc::{PacketAsVec, PacketHandler},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::cobs::encode_packet_with_cobs;
|
use super::cobs::encode_packet_with_cobs;
|
||||||
@@ -25,10 +25,10 @@ pub(crate) mod tests {
|
|||||||
pub(crate) tc_queue: RefCell<VecDeque<PacketAsVec>>,
|
pub(crate) tc_queue: RefCell<VecDeque<PacketAsVec>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PacketSenderRaw for TcCacher {
|
impl PacketHandler for TcCacher {
|
||||||
type Error = ();
|
type Error = ();
|
||||||
|
|
||||||
fn send_packet(&self, sender_id: ComponentId, tc_raw: &[u8]) -> Result<(), Self::Error> {
|
fn handle_packet(&self, sender_id: ComponentId, tc_raw: &[u8]) -> Result<(), Self::Error> {
|
||||||
let mut mut_queue = self.tc_queue.borrow_mut();
|
let mut mut_queue = self.tc_queue.borrow_mut();
|
||||||
mut_queue.push_back(PacketAsVec::new(sender_id, tc_raw.to_vec()));
|
mut_queue.push_back(PacketAsVec::new(sender_id, tc_raw.to_vec()));
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -2,5 +2,5 @@
|
|||||||
pub mod tcp_server;
|
pub mod tcp_server;
|
||||||
pub mod udp_server;
|
pub mod udp_server;
|
||||||
|
|
||||||
mod tcp_cobs_server;
|
pub mod tcp_cobs_server;
|
||||||
mod tcp_spacepackets_server;
|
pub mod tcp_spacepackets_server;
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
use alloc::sync::Arc;
|
use alloc::sync::Arc;
|
||||||
use alloc::vec;
|
use alloc::vec;
|
||||||
|
use cobs::CobsDecoderOwned;
|
||||||
|
use cobs::DecodeError;
|
||||||
use cobs::encode;
|
use cobs::encode;
|
||||||
use core::sync::atomic::AtomicBool;
|
use core::sync::atomic::AtomicBool;
|
||||||
use core::time::Duration;
|
use core::time::Duration;
|
||||||
@@ -9,40 +11,58 @@ use std::io::Write;
|
|||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
use std::vec::Vec;
|
use std::vec::Vec;
|
||||||
|
|
||||||
use crate::encoding::parse_buffer_for_cobs_encoded_packets;
|
use crate::queue::GenericSendError;
|
||||||
use crate::tmtc::PacketSenderRaw;
|
use crate::tmtc::PacketHandler;
|
||||||
use crate::tmtc::PacketSource;
|
use crate::tmtc::PacketSource;
|
||||||
|
|
||||||
use crate::ComponentId;
|
use crate::ComponentId;
|
||||||
use crate::hal::std::tcp_server::{
|
use crate::hal::std::tcp_server::{
|
||||||
ConnectionResult, ServerConfig, TcpTcParser, TcpTmSender, TcpTmtcError, TcpTmtcGenericServer,
|
ConnectionResult, ServerConfig, TcpTcParser, TcpTmSender, TcpTmtcGenericServer,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::tcp_server::HandledConnectionHandler;
|
use super::tcp_server::HandledConnectionHandler;
|
||||||
use super::tcp_server::HandledConnectionInfo;
|
use super::tcp_server::HandledConnectionInfo;
|
||||||
|
|
||||||
/// Concrete [TcpTcParser] implementation for the [TcpTmtcInCobsServer].
|
/// Concrete [TcpTcParser] implementation for the [TcpTmtcInCobsServer].
|
||||||
#[derive(Default)]
|
pub struct CobsTcParser<PacketHandlerInstance: PacketHandler> {
|
||||||
pub struct CobsTcParser {}
|
|
||||||
|
|
||||||
impl<TmError, TcError: 'static> TcpTcParser<TmError, TcError> for CobsTcParser {
|
|
||||||
fn handle_tc_parsing(
|
|
||||||
&mut self,
|
|
||||||
tc_buffer: &mut [u8],
|
|
||||||
sender_id: ComponentId,
|
sender_id: ComponentId,
|
||||||
tc_sender: &(impl PacketSenderRaw<Error = TcError> + ?Sized),
|
owned_decoder: CobsDecoderOwned,
|
||||||
conn_result: &mut HandledConnectionInfo,
|
packet_handler: PacketHandlerInstance,
|
||||||
current_write_idx: usize,
|
last_decode_error: Option<DecodeError>,
|
||||||
next_write_idx: &mut usize,
|
}
|
||||||
) -> Result<(), TcpTmtcError<TmError, TcError>> {
|
|
||||||
conn_result.num_received_tcs += parse_buffer_for_cobs_encoded_packets(
|
impl<PacketHandlerInstance: PacketHandler> CobsTcParser<PacketHandlerInstance> {
|
||||||
&mut tc_buffer[..current_write_idx],
|
pub fn new(
|
||||||
|
sender_id: ComponentId,
|
||||||
|
decoder_buf_size: usize,
|
||||||
|
packet_handler: PacketHandlerInstance,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
sender_id,
|
sender_id,
|
||||||
tc_sender,
|
owned_decoder: CobsDecoderOwned::new(decoder_buf_size),
|
||||||
next_write_idx,
|
packet_handler,
|
||||||
)
|
last_decode_error: None,
|
||||||
.map_err(|e| TcpTmtcError::TcError(e))?;
|
}
|
||||||
Ok(())
|
}
|
||||||
|
}
|
||||||
|
impl<PacketHandlerInstance: PacketHandler> TcpTcParser for CobsTcParser<PacketHandlerInstance> {
|
||||||
|
fn reset(&mut self) {
|
||||||
|
self.owned_decoder.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn push(&mut self, data: &[u8], conn_result: &mut HandledConnectionInfo) {
|
||||||
|
for byte in data {
|
||||||
|
match self.owned_decoder.feed(*byte) {
|
||||||
|
Ok(Some(packet_len)) => {
|
||||||
|
self.packet_handler
|
||||||
|
.handle_packet(self.sender_id, &self.owned_decoder.dest()[..packet_len])
|
||||||
|
.ok();
|
||||||
|
conn_result.num_received_tcs += 1;
|
||||||
|
}
|
||||||
|
Ok(None) => (),
|
||||||
|
Err(e) => self.last_decode_error = Some(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,22 +81,18 @@ impl CobsTmSender {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<TmError, TcError> TcpTmSender<TmError, TcError> for CobsTmSender {
|
impl TcpTmSender for CobsTmSender {
|
||||||
fn handle_tm_sending(
|
fn handle_tm_sending(
|
||||||
&mut self,
|
&mut self,
|
||||||
tm_buffer: &mut [u8],
|
tm_buffer: &mut [u8],
|
||||||
tm_source: &mut (impl PacketSource<Error = TmError> + ?Sized),
|
tm_source: &mut (impl PacketSource<Error = ()> + ?Sized),
|
||||||
conn_result: &mut HandledConnectionInfo,
|
conn_result: &mut HandledConnectionInfo,
|
||||||
stream: &mut TcpStream,
|
stream: &mut TcpStream,
|
||||||
) -> Result<bool, TcpTmtcError<TmError, TcError>> {
|
) -> Result<bool, std::io::Error> {
|
||||||
let mut tm_was_sent = false;
|
let mut tm_was_sent = false;
|
||||||
loop {
|
// Write TM until TM source is exhausted or there is an unexpected error. For now, there
|
||||||
// Write TM until TM source is exhausted. For now, there is no limit for the amount
|
// is no limit for the amount of TM written this way.
|
||||||
// of TM written this way.
|
while let Ok(read_tm_len) = tm_source.retrieve_packet(tm_buffer) {
|
||||||
let read_tm_len = tm_source
|
|
||||||
.retrieve_packet(tm_buffer)
|
|
||||||
.map_err(|e| TcpTmtcError::TmError(e))?;
|
|
||||||
|
|
||||||
if read_tm_len == 0 {
|
if read_tm_len == 0 {
|
||||||
return Ok(tm_was_sent);
|
return Ok(tm_was_sent);
|
||||||
}
|
}
|
||||||
@@ -95,6 +111,7 @@ impl<TmError, TcError> TcpTmSender<TmError, TcError> for CobsTmSender {
|
|||||||
current_idx += 1;
|
current_idx += 1;
|
||||||
stream.write_all(&self.tm_encoding_buffer[..current_idx])?;
|
stream.write_all(&self.tm_encoding_buffer[..current_idx])?;
|
||||||
}
|
}
|
||||||
|
Ok(tm_was_sent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,8 +125,8 @@ impl<TmError, TcError> TcpTmSender<TmError, TcError> for CobsTmSender {
|
|||||||
///
|
///
|
||||||
/// Using a framing protocol like COBS imposes minimal restrictions on the type of TMTC data
|
/// Using a framing protocol like COBS imposes minimal restrictions on the type of TMTC data
|
||||||
/// exchanged while also allowing packets with flexible size and a reliable way to reconstruct full
|
/// exchanged while also allowing packets with flexible size and a reliable way to reconstruct full
|
||||||
/// packets even from a data stream which is split up. The server wil use the
|
/// packets even from a data stream which is split up. The server wil use the streaming
|
||||||
/// [parse_buffer_for_cobs_encoded_packets] function to parse for packets and pass them to a
|
/// [CobsDecoderOwned] decoder to parse for packets and pass them to a
|
||||||
/// generic TC receiver. The user can use [crate::encoding::encode_packet_with_cobs] to encode
|
/// generic TC receiver. The user can use [crate::encoding::encode_packet_with_cobs] to encode
|
||||||
/// telecommands sent to the server.
|
/// telecommands sent to the server.
|
||||||
///
|
///
|
||||||
@@ -118,30 +135,19 @@ impl<TmError, TcError> TcpTmSender<TmError, TcError> for CobsTmSender {
|
|||||||
/// The [TCP integration tests](https://egit.irs.uni-stuttgart.de/rust/sat-rs/src/branch/main/satrs/tests/tcp_servers.rs)
|
/// The [TCP integration tests](https://egit.irs.uni-stuttgart.de/rust/sat-rs/src/branch/main/satrs/tests/tcp_servers.rs)
|
||||||
/// test also serves as the example application for this module.
|
/// test also serves as the example application for this module.
|
||||||
pub struct TcpTmtcInCobsServer<
|
pub struct TcpTmtcInCobsServer<
|
||||||
TmSource: PacketSource<Error = TmError>,
|
TmSource: PacketSource<Error = ()>,
|
||||||
TcSender: PacketSenderRaw<Error = SendError>,
|
TcHandler: PacketHandler<Error = GenericSendError>,
|
||||||
HandledConnection: HandledConnectionHandler,
|
HandledConnection: HandledConnectionHandler,
|
||||||
TmError,
|
|
||||||
SendError: 'static,
|
|
||||||
> {
|
> {
|
||||||
pub generic_server: TcpTmtcGenericServer<
|
pub generic_server:
|
||||||
TmSource,
|
TcpTmtcGenericServer<TmSource, CobsTmSender, CobsTcParser<TcHandler>, HandledConnection>,
|
||||||
TcSender,
|
|
||||||
CobsTmSender,
|
|
||||||
CobsTcParser,
|
|
||||||
HandledConnection,
|
|
||||||
TmError,
|
|
||||||
SendError,
|
|
||||||
>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<
|
impl<
|
||||||
TmSource: PacketSource<Error = TmError>,
|
TmSource: PacketSource<Error = ()>,
|
||||||
TcReceiver: PacketSenderRaw<Error = TcError>,
|
TcHandler: PacketHandler<Error = GenericSendError>,
|
||||||
HandledConnection: HandledConnectionHandler,
|
HandledConnection: HandledConnectionHandler,
|
||||||
TmError: 'static,
|
> TcpTmtcInCobsServer<TmSource, TcHandler, HandledConnection>
|
||||||
TcError: 'static,
|
|
||||||
> TcpTmtcInCobsServer<TmSource, TcReceiver, HandledConnection, TmError, TcError>
|
|
||||||
{
|
{
|
||||||
/// Create a new TCP TMTC server which exchanges TMTC packets encoded with
|
/// Create a new TCP TMTC server which exchanges TMTC packets encoded with
|
||||||
/// [COBS protocol](https://en.wikipedia.org/wiki/Consistent_Overhead_Byte_Stuffing).
|
/// [COBS protocol](https://en.wikipedia.org/wiki/Consistent_Overhead_Byte_Stuffing).
|
||||||
@@ -156,17 +162,16 @@ impl<
|
|||||||
pub fn new(
|
pub fn new(
|
||||||
cfg: ServerConfig,
|
cfg: ServerConfig,
|
||||||
tm_source: TmSource,
|
tm_source: TmSource,
|
||||||
tc_receiver: TcReceiver,
|
cobs_tc_parser: CobsTcParser<TcHandler>,
|
||||||
handled_connection: HandledConnection,
|
handled_connection: HandledConnection,
|
||||||
stop_signal: Option<Arc<AtomicBool>>,
|
stop_signal: Option<Arc<AtomicBool>>,
|
||||||
) -> Result<Self, std::io::Error> {
|
) -> Result<Self, std::io::Error> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
generic_server: TcpTmtcGenericServer::new(
|
generic_server: TcpTmtcGenericServer::new(
|
||||||
cfg,
|
cfg,
|
||||||
CobsTcParser::default(),
|
cobs_tc_parser,
|
||||||
CobsTmSender::new(cfg.tm_buffer_size),
|
CobsTmSender::new(cfg.tm_buffer_size),
|
||||||
tm_source,
|
tm_source,
|
||||||
tc_receiver,
|
|
||||||
handled_connection,
|
handled_connection,
|
||||||
stop_signal,
|
stop_signal,
|
||||||
)?,
|
)?,
|
||||||
@@ -185,7 +190,7 @@ impl<
|
|||||||
pub fn handle_all_connections(
|
pub fn handle_all_connections(
|
||||||
&mut self,
|
&mut self,
|
||||||
poll_duration: Option<Duration>,
|
poll_duration: Option<Duration>,
|
||||||
) -> Result<ConnectionResult, TcpTmtcError<TmError, TcError>>;
|
) -> Result<ConnectionResult, std::io::Error>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -212,7 +217,6 @@ mod tests {
|
|||||||
ConnectionResult, ServerConfig,
|
ConnectionResult, ServerConfig,
|
||||||
tests::{ConnectionFinishedHandler, SyncTmSource},
|
tests::{ConnectionFinishedHandler, SyncTmSource},
|
||||||
},
|
},
|
||||||
queue::GenericSendError,
|
|
||||||
tmtc::PacketAsVec,
|
tmtc::PacketAsVec,
|
||||||
};
|
};
|
||||||
use alloc::sync::Arc;
|
use alloc::sync::Arc;
|
||||||
@@ -243,17 +247,12 @@ mod tests {
|
|||||||
tc_sender: mpsc::Sender<PacketAsVec>,
|
tc_sender: mpsc::Sender<PacketAsVec>,
|
||||||
tm_source: SyncTmSource,
|
tm_source: SyncTmSource,
|
||||||
stop_signal: Option<Arc<AtomicBool>>,
|
stop_signal: Option<Arc<AtomicBool>>,
|
||||||
) -> TcpTmtcInCobsServer<
|
) -> TcpTmtcInCobsServer<SyncTmSource, mpsc::Sender<PacketAsVec>, ConnectionFinishedHandler>
|
||||||
SyncTmSource,
|
{
|
||||||
mpsc::Sender<PacketAsVec>,
|
|
||||||
ConnectionFinishedHandler,
|
|
||||||
(),
|
|
||||||
GenericSendError,
|
|
||||||
> {
|
|
||||||
TcpTmtcInCobsServer::new(
|
TcpTmtcInCobsServer::new(
|
||||||
ServerConfig::new(TCP_SERVER_ID, *addr, Duration::from_millis(2), 1024, 1024),
|
ServerConfig::new(TCP_SERVER_ID, *addr, Duration::from_millis(2), 1024, 1024),
|
||||||
tm_source,
|
tm_source,
|
||||||
tc_sender,
|
super::CobsTcParser::new(TCP_SERVER_ID, 1024, tc_sender),
|
||||||
ConnectionFinishedHandler::default(),
|
ConnectionFinishedHandler::default(),
|
||||||
stop_signal,
|
stop_signal,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ use std::net::SocketAddr;
|
|||||||
use std::thread;
|
use std::thread;
|
||||||
|
|
||||||
use crate::ComponentId;
|
use crate::ComponentId;
|
||||||
use crate::tmtc::{PacketSenderRaw, PacketSource};
|
use crate::tmtc::PacketSource;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
// Re-export the TMTC in COBS server.
|
// Re-export the TMTC in COBS server.
|
||||||
@@ -73,11 +73,9 @@ impl ServerConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
pub enum TcpTmtcError<TmError, TcError> {
|
pub enum TcpTmError<TmError> {
|
||||||
#[error("TM retrieval error: {0}")]
|
#[error("TM retrieval error: {0}")]
|
||||||
TmError(TmError),
|
TmError(TmError),
|
||||||
#[error("TC retrieval error: {0}")]
|
|
||||||
TcError(TcError),
|
|
||||||
#[error("io error: {0}")]
|
#[error("io error: {0}")]
|
||||||
Io(#[from] std::io::Error),
|
Io(#[from] std::io::Error),
|
||||||
}
|
}
|
||||||
@@ -116,32 +114,29 @@ pub trait HandledConnectionHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Generic parser abstraction for an object which can parse for telecommands given a raw
|
/// Generic parser abstraction for an object which can parse for telecommands given a raw
|
||||||
/// bytestream received from a TCP socket and send them using a generic [PacketSenderRaw]
|
/// bytestream received from a TCP socket and extract packets from them. This allows different
|
||||||
/// implementation. This allows different encoding schemes for telecommands.
|
/// encoding schemes for telecommands.
|
||||||
pub trait TcpTcParser<TmError, SendError> {
|
pub trait TcpTcParser {
|
||||||
fn handle_tc_parsing(
|
/// Reset the state of the parser.
|
||||||
&mut self,
|
fn reset(&mut self);
|
||||||
tc_buffer: &mut [u8],
|
|
||||||
sender_id: ComponentId,
|
/// Pushes received data into the parser.
|
||||||
tc_sender: &(impl PacketSenderRaw<Error = SendError> + ?Sized),
|
fn push(&mut self, tc_data: &[u8], conn_result: &mut HandledConnectionInfo);
|
||||||
conn_result: &mut HandledConnectionInfo,
|
|
||||||
current_write_idx: usize,
|
|
||||||
next_write_idx: &mut usize,
|
|
||||||
) -> Result<(), TcpTmtcError<TmError, SendError>>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generic sender abstraction for an object which can pull telemetry from a given TM source
|
/// Generic sender abstraction for an object which can pull telemetry from a given TM source
|
||||||
/// using a [PacketSource] and then send them back to a client using a given [TcpStream].
|
/// using a [PacketSource] and then send them back to a client using a given [TcpStream].
|
||||||
/// The concrete implementation can also perform any encoding steps which are necessary before
|
/// The concrete implementation can also perform any encoding steps which are necessary before
|
||||||
/// sending back the data to a client.
|
/// sending back the data to a client.
|
||||||
pub trait TcpTmSender<TmError, TcError> {
|
pub trait TcpTmSender {
|
||||||
|
/// Returns whether any packets were sent back to the client.
|
||||||
fn handle_tm_sending(
|
fn handle_tm_sending(
|
||||||
&mut self,
|
&mut self,
|
||||||
tm_buffer: &mut [u8],
|
tm_buffer: &mut [u8],
|
||||||
tm_source: &mut (impl PacketSource<Error = TmError> + ?Sized),
|
tm_source: &mut (impl PacketSource<Error = ()> + ?Sized),
|
||||||
conn_result: &mut HandledConnectionInfo,
|
conn_result: &mut HandledConnectionInfo,
|
||||||
stream: &mut TcpStream,
|
stream: &mut TcpStream,
|
||||||
) -> Result<bool, TcpTmtcError<TmError, TcError>>;
|
) -> Result<bool, std::io::Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// TCP TMTC server implementation for exchange of generic TMTC packets in a generic way which
|
/// TCP TMTC server implementation for exchange of generic TMTC packets in a generic way which
|
||||||
@@ -151,7 +146,8 @@ pub trait TcpTmSender<TmError, TcError> {
|
|||||||
/// through the following 4 core abstractions:
|
/// through the following 4 core abstractions:
|
||||||
///
|
///
|
||||||
/// 1. [TcpTcParser] to parse for telecommands from the raw bytestream received from a client.
|
/// 1. [TcpTcParser] to parse for telecommands from the raw bytestream received from a client.
|
||||||
/// 2. Parsed telecommands will be sent using the [PacketSenderRaw] object.
|
/// 2. Parsed telecommands will be handled by the [TcpTcParser] object as well. For example, this
|
||||||
|
/// parser can contain a message queue handle to send the packets somewhere.
|
||||||
/// 3. [TcpTmSender] to send telemetry pulled from a TM source back to the client.
|
/// 3. [TcpTmSender] to send telemetry pulled from a TM source back to the client.
|
||||||
/// 4. [PacketSource] as a generic TM source used by the [TcpTmSender].
|
/// 4. [PacketSource] as a generic TM source used by the [TcpTmSender].
|
||||||
///
|
///
|
||||||
@@ -163,13 +159,10 @@ pub trait TcpTmSender<TmError, TcError> {
|
|||||||
/// 1. [TcpTmtcInCobsServer] to exchange TMTC wrapped inside the COBS framing protocol.
|
/// 1. [TcpTmtcInCobsServer] to exchange TMTC wrapped inside the COBS framing protocol.
|
||||||
/// 2. [TcpSpacepacketsServer] to exchange space packets via TCP.
|
/// 2. [TcpSpacepacketsServer] to exchange space packets via TCP.
|
||||||
pub struct TcpTmtcGenericServer<
|
pub struct TcpTmtcGenericServer<
|
||||||
TmSource: PacketSource<Error = TmError>,
|
TmSource: PacketSource<Error = ()>,
|
||||||
TcSender: PacketSenderRaw<Error = TcSendError>,
|
TmSender: TcpTmSender,
|
||||||
TmSender: TcpTmSender<TmError, TcSendError>,
|
TcParser: TcpTcParser,
|
||||||
TcParser: TcpTcParser<TmError, TcSendError>,
|
|
||||||
HandledConnection: HandledConnectionHandler,
|
HandledConnection: HandledConnectionHandler,
|
||||||
TmError,
|
|
||||||
TcSendError,
|
|
||||||
> {
|
> {
|
||||||
pub id: ComponentId,
|
pub id: ComponentId,
|
||||||
pub finished_handler: HandledConnection,
|
pub finished_handler: HandledConnection,
|
||||||
@@ -177,7 +170,6 @@ pub struct TcpTmtcGenericServer<
|
|||||||
pub(crate) inner_loop_delay: Duration,
|
pub(crate) inner_loop_delay: Duration,
|
||||||
pub(crate) tm_source: TmSource,
|
pub(crate) tm_source: TmSource,
|
||||||
pub(crate) tm_buffer: Vec<u8>,
|
pub(crate) tm_buffer: Vec<u8>,
|
||||||
pub(crate) tc_sender: TcSender,
|
|
||||||
pub(crate) tc_buffer: Vec<u8>,
|
pub(crate) tc_buffer: Vec<u8>,
|
||||||
poll: Poll,
|
poll: Poll,
|
||||||
events: Events,
|
events: Events,
|
||||||
@@ -187,23 +179,11 @@ pub struct TcpTmtcGenericServer<
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<
|
impl<
|
||||||
TmSource: PacketSource<Error = TmError>,
|
TmSource: PacketSource<Error = ()>,
|
||||||
TcSender: PacketSenderRaw<Error = TcSendError>,
|
TmSender: TcpTmSender,
|
||||||
TmSender: TcpTmSender<TmError, TcSendError>,
|
TcParser: TcpTcParser,
|
||||||
TcParser: TcpTcParser<TmError, TcSendError>,
|
|
||||||
HandledConnection: HandledConnectionHandler,
|
HandledConnection: HandledConnectionHandler,
|
||||||
TmError: 'static,
|
> TcpTmtcGenericServer<TmSource, TmSender, TcParser, HandledConnection>
|
||||||
TcSendError: 'static,
|
|
||||||
>
|
|
||||||
TcpTmtcGenericServer<
|
|
||||||
TmSource,
|
|
||||||
TcSender,
|
|
||||||
TmSender,
|
|
||||||
TcParser,
|
|
||||||
HandledConnection,
|
|
||||||
TmError,
|
|
||||||
TcSendError,
|
|
||||||
>
|
|
||||||
{
|
{
|
||||||
/// Create a new generic TMTC server instance.
|
/// Create a new generic TMTC server instance.
|
||||||
///
|
///
|
||||||
@@ -223,7 +203,6 @@ impl<
|
|||||||
tc_parser: TcParser,
|
tc_parser: TcParser,
|
||||||
tm_sender: TmSender,
|
tm_sender: TmSender,
|
||||||
tm_source: TmSource,
|
tm_source: TmSource,
|
||||||
tc_receiver: TcSender,
|
|
||||||
finished_handler: HandledConnection,
|
finished_handler: HandledConnection,
|
||||||
stop_signal: Option<Arc<AtomicBool>>,
|
stop_signal: Option<Arc<AtomicBool>>,
|
||||||
) -> Result<Self, std::io::Error> {
|
) -> Result<Self, std::io::Error> {
|
||||||
@@ -263,7 +242,6 @@ impl<
|
|||||||
inner_loop_delay: cfg.inner_loop_delay,
|
inner_loop_delay: cfg.inner_loop_delay,
|
||||||
tm_source,
|
tm_source,
|
||||||
tm_buffer: vec![0; cfg.tm_buffer_size],
|
tm_buffer: vec![0; cfg.tm_buffer_size],
|
||||||
tc_sender: tc_receiver,
|
|
||||||
tc_buffer: vec![0; cfg.tc_buffer_size],
|
tc_buffer: vec![0; cfg.tc_buffer_size],
|
||||||
stop_signal,
|
stop_signal,
|
||||||
finished_handler,
|
finished_handler,
|
||||||
@@ -297,7 +275,7 @@ impl<
|
|||||||
pub fn handle_all_connections(
|
pub fn handle_all_connections(
|
||||||
&mut self,
|
&mut self,
|
||||||
poll_timeout: Option<Duration>,
|
poll_timeout: Option<Duration>,
|
||||||
) -> Result<ConnectionResult, TcpTmtcError<TmError, TcSendError>> {
|
) -> Result<ConnectionResult, std::io::Error> {
|
||||||
let mut handled_connections = 0;
|
let mut handled_connections = 0;
|
||||||
// Poll Mio for events.
|
// Poll Mio for events.
|
||||||
self.poll.poll(&mut self.events, poll_timeout)?;
|
self.poll.poll(&mut self.events, poll_timeout)?;
|
||||||
@@ -327,7 +305,7 @@ impl<
|
|||||||
Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => break,
|
Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => break,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
self.reregister_poll_interest()?;
|
self.reregister_poll_interest()?;
|
||||||
return Err(TcpTmtcError::Io(err));
|
return Err(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -350,58 +328,24 @@ impl<
|
|||||||
&mut self,
|
&mut self,
|
||||||
mut stream: TcpStream,
|
mut stream: TcpStream,
|
||||||
addr: SocketAddr,
|
addr: SocketAddr,
|
||||||
) -> Result<(), TcpTmtcError<TmError, TcSendError>> {
|
) -> Result<(), std::io::Error> {
|
||||||
let mut current_write_idx;
|
self.tc_handler.reset();
|
||||||
let mut next_write_idx = 0;
|
|
||||||
let mut connection_result = HandledConnectionInfo::new(addr);
|
let mut connection_result = HandledConnectionInfo::new(addr);
|
||||||
current_write_idx = next_write_idx;
|
|
||||||
loop {
|
loop {
|
||||||
let read_result = stream.read(&mut self.tc_buffer[current_write_idx..]);
|
let read_result = stream.read(&mut self.tc_buffer);
|
||||||
match read_result {
|
match read_result {
|
||||||
Ok(0) => {
|
Ok(0) => {
|
||||||
// Connection closed by client. If any TC was read, parse for complete packets.
|
// Connection closed by client.
|
||||||
// After that, break the outer loop.
|
|
||||||
if current_write_idx > 0 {
|
|
||||||
self.tc_handler.handle_tc_parsing(
|
|
||||||
&mut self.tc_buffer,
|
|
||||||
self.id,
|
|
||||||
&self.tc_sender,
|
|
||||||
&mut connection_result,
|
|
||||||
current_write_idx,
|
|
||||||
&mut next_write_idx,
|
|
||||||
)?;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Ok(read_len) => {
|
Ok(read_len) => {
|
||||||
current_write_idx += read_len;
|
self.tc_handler
|
||||||
// TC buffer is full, we must parse for complete packets now.
|
.push(&self.tc_buffer[0..read_len], &mut connection_result);
|
||||||
if current_write_idx == self.tc_buffer.capacity() {
|
|
||||||
self.tc_handler.handle_tc_parsing(
|
|
||||||
&mut self.tc_buffer,
|
|
||||||
self.id,
|
|
||||||
&self.tc_sender,
|
|
||||||
&mut connection_result,
|
|
||||||
current_write_idx,
|
|
||||||
&mut next_write_idx,
|
|
||||||
)?;
|
|
||||||
current_write_idx = next_write_idx;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Err(e) => match e.kind() {
|
Err(e) => match e.kind() {
|
||||||
// As per [TcpStream::set_read_timeout] documentation, this should work for
|
// As per [TcpStream::set_read_timeout] documentation, this should work for
|
||||||
// both UNIX and Windows.
|
// both UNIX and Windows.
|
||||||
std::io::ErrorKind::WouldBlock | std::io::ErrorKind::TimedOut => {
|
std::io::ErrorKind::WouldBlock | std::io::ErrorKind::TimedOut => {
|
||||||
self.tc_handler.handle_tc_parsing(
|
|
||||||
&mut self.tc_buffer,
|
|
||||||
self.id,
|
|
||||||
&self.tc_sender,
|
|
||||||
&mut connection_result,
|
|
||||||
current_write_idx,
|
|
||||||
&mut next_write_idx,
|
|
||||||
)?;
|
|
||||||
current_write_idx = next_write_idx;
|
|
||||||
|
|
||||||
if !self.tm_handler.handle_tm_sending(
|
if !self.tm_handler.handle_tm_sending(
|
||||||
&mut self.tm_buffer,
|
&mut self.tm_buffer,
|
||||||
&mut self.tm_source,
|
&mut self.tm_source,
|
||||||
@@ -426,7 +370,7 @@ impl<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
return Err(TcpTmtcError::Io(e));
|
return Err(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -502,8 +446,11 @@ pub(crate) mod tests {
|
|||||||
.connection_info
|
.connection_info
|
||||||
.pop_back()
|
.pop_back()
|
||||||
.expect("no connection info available");
|
.expect("no connection info available");
|
||||||
assert_eq!(last_conn_result.num_received_tcs, num_tcs);
|
assert_eq!(
|
||||||
assert_eq!(last_conn_result.num_sent_tms, num_tms);
|
last_conn_result.num_received_tcs, num_tcs,
|
||||||
|
"received tcs mismatch"
|
||||||
|
);
|
||||||
|
assert_eq!(last_conn_result.num_sent_tms, num_tms, "sent tms missmatch");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn check_no_connections_left(&self) {
|
pub fn check_no_connections_left(&self) {
|
||||||
|
|||||||
@@ -7,39 +7,104 @@ use std::{io::Write, net::SocketAddr};
|
|||||||
use crate::{
|
use crate::{
|
||||||
ComponentId,
|
ComponentId,
|
||||||
encoding::{ccsds::SpacePacketValidator, parse_buffer_for_ccsds_space_packets},
|
encoding::{ccsds::SpacePacketValidator, parse_buffer_for_ccsds_space_packets},
|
||||||
tmtc::{PacketSenderRaw, PacketSource},
|
queue::GenericSendError,
|
||||||
|
tmtc::{PacketHandler, PacketSource},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::tcp_server::{
|
use super::tcp_server::{
|
||||||
ConnectionResult, HandledConnectionHandler, HandledConnectionInfo, ServerConfig, TcpTcParser,
|
ConnectionResult, HandledConnectionHandler, HandledConnectionInfo, ServerConfig, TcpTcParser,
|
||||||
TcpTmSender, TcpTmtcError, TcpTmtcGenericServer,
|
TcpTmSender, TcpTmtcGenericServer,
|
||||||
};
|
};
|
||||||
|
|
||||||
impl<T: SpacePacketValidator, TmError, TcError: 'static> TcpTcParser<TmError, TcError> for T {
|
pub struct CcsdsPacketParser<
|
||||||
fn handle_tc_parsing(
|
PacketValidator: SpacePacketValidator,
|
||||||
&mut self,
|
PacketHandlerInstance: PacketHandler,
|
||||||
tc_buffer: &mut [u8],
|
> {
|
||||||
sender_id: ComponentId,
|
sender_id: ComponentId,
|
||||||
tc_sender: &(impl PacketSenderRaw<Error = TcError> + ?Sized),
|
parsing_buffer: alloc::vec::Vec<u8>,
|
||||||
conn_result: &mut HandledConnectionInfo,
|
validator: PacketValidator,
|
||||||
current_write_idx: usize,
|
packet_handler: PacketHandlerInstance,
|
||||||
next_write_idx: &mut usize,
|
current_write_index: usize,
|
||||||
) -> Result<(), TcpTmtcError<TmError, TcError>> {
|
}
|
||||||
// Reader vec full, need to parse for packets.
|
|
||||||
let parse_result = parse_buffer_for_ccsds_space_packets(
|
impl<PacketValidator: SpacePacketValidator, PacketHandlerInstance: PacketHandler>
|
||||||
&tc_buffer[..current_write_idx],
|
CcsdsPacketParser<PacketValidator, PacketHandlerInstance>
|
||||||
self,
|
{
|
||||||
|
pub fn new(
|
||||||
|
sender_id: ComponentId,
|
||||||
|
parsing_buf_size: usize,
|
||||||
|
packet_handler: PacketHandlerInstance,
|
||||||
|
validator: PacketValidator,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
sender_id,
|
sender_id,
|
||||||
tc_sender,
|
parsing_buffer: alloc::vec![0; parsing_buf_size],
|
||||||
)
|
validator,
|
||||||
.map_err(|e| TcpTmtcError::TcError(e))?;
|
packet_handler,
|
||||||
if let Some(broken_tail_start) = parse_result.incomplete_tail_start {
|
current_write_index: 0,
|
||||||
// Copy broken tail to front of buffer.
|
}
|
||||||
tc_buffer.copy_within(broken_tail_start..current_write_idx, 0);
|
}
|
||||||
*next_write_idx = current_write_idx - broken_tail_start;
|
|
||||||
|
fn write_to_buffer(&mut self, data: &[u8]) -> usize {
|
||||||
|
let available = self.parsing_buffer.len() - self.current_write_index;
|
||||||
|
let to_write = core::cmp::min(data.len(), available);
|
||||||
|
|
||||||
|
self.parsing_buffer[self.current_write_index..self.current_write_index + to_write]
|
||||||
|
.copy_from_slice(&data[..to_write]);
|
||||||
|
self.current_write_index += to_write;
|
||||||
|
|
||||||
|
to_write
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_and_handle_packets(&mut self) -> u32 {
|
||||||
|
match parse_buffer_for_ccsds_space_packets(
|
||||||
|
&self.parsing_buffer[..self.current_write_index],
|
||||||
|
&self.validator,
|
||||||
|
self.sender_id,
|
||||||
|
&self.packet_handler,
|
||||||
|
) {
|
||||||
|
Ok(parse_result) => {
|
||||||
|
self.parsing_buffer
|
||||||
|
.copy_within(parse_result.parsed_bytes..self.current_write_index, 0);
|
||||||
|
self.current_write_index -= parse_result.parsed_bytes;
|
||||||
|
parse_result.packets_found
|
||||||
|
}
|
||||||
|
Err(_) => 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn drop_first_half_of_buffer(&mut self) {
|
||||||
|
let mid = self.parsing_buffer.len() / 2;
|
||||||
|
self.parsing_buffer.copy_within(mid.., 0);
|
||||||
|
self.current_write_index -= mid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<PacketValidator: SpacePacketValidator, PacketHandlerInstance: PacketHandler> TcpTcParser
|
||||||
|
for CcsdsPacketParser<PacketValidator, PacketHandlerInstance>
|
||||||
|
{
|
||||||
|
fn reset(&mut self) {
|
||||||
|
self.current_write_index = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn push(&mut self, mut tc_buffer: &[u8], conn_result: &mut HandledConnectionInfo) {
|
||||||
|
while !tc_buffer.is_empty() {
|
||||||
|
// Write as much as possible to buffer
|
||||||
|
let written = self.write_to_buffer(tc_buffer);
|
||||||
|
tc_buffer = &tc_buffer[written..];
|
||||||
|
|
||||||
|
// Parse for complete packets
|
||||||
|
let packets_found = self.parse_and_handle_packets();
|
||||||
|
conn_result.num_received_tcs += packets_found;
|
||||||
|
|
||||||
|
if tc_buffer.is_empty() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle buffer overflow
|
||||||
|
if self.current_write_index == self.parsing_buffer.len() {
|
||||||
|
self.drop_first_half_of_buffer();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
conn_result.num_received_tcs += parse_result.packets_found;
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,21 +112,18 @@ impl<T: SpacePacketValidator, TmError, TcError: 'static> TcpTcParser<TmError, Tc
|
|||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct SpacepacketsTmSender {}
|
pub struct SpacepacketsTmSender {}
|
||||||
|
|
||||||
impl<TmError, TcError> TcpTmSender<TmError, TcError> for SpacepacketsTmSender {
|
impl TcpTmSender for SpacepacketsTmSender {
|
||||||
fn handle_tm_sending(
|
fn handle_tm_sending(
|
||||||
&mut self,
|
&mut self,
|
||||||
tm_buffer: &mut [u8],
|
tm_buffer: &mut [u8],
|
||||||
tm_source: &mut (impl PacketSource<Error = TmError> + ?Sized),
|
tm_source: &mut (impl PacketSource<Error = ()> + ?Sized),
|
||||||
conn_result: &mut HandledConnectionInfo,
|
conn_result: &mut HandledConnectionInfo,
|
||||||
stream: &mut TcpStream,
|
stream: &mut TcpStream,
|
||||||
) -> Result<bool, TcpTmtcError<TmError, TcError>> {
|
) -> Result<bool, std::io::Error> {
|
||||||
let mut tm_was_sent = false;
|
let mut tm_was_sent = false;
|
||||||
loop {
|
while let Ok(read_tm_len) = tm_source.retrieve_packet(tm_buffer) {
|
||||||
// Write TM until TM source is exhausted. For now, there is no limit for the amount
|
// Write TM until TM source is exhausted. For now, there is no limit for the amount
|
||||||
// of TM written this way.
|
// of TM written this way.
|
||||||
let read_tm_len = tm_source
|
|
||||||
.retrieve_packet(tm_buffer)
|
|
||||||
.map_err(|e| TcpTmtcError::TmError(e))?;
|
|
||||||
|
|
||||||
if read_tm_len == 0 {
|
if read_tm_len == 0 {
|
||||||
return Ok(tm_was_sent);
|
return Ok(tm_was_sent);
|
||||||
@@ -71,6 +133,7 @@ impl<TmError, TcError> TcpTmSender<TmError, TcError> for SpacepacketsTmSender {
|
|||||||
|
|
||||||
stream.write_all(&tm_buffer[..read_tm_len])?;
|
stream.write_all(&tm_buffer[..read_tm_len])?;
|
||||||
}
|
}
|
||||||
|
Ok(tm_was_sent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,32 +151,25 @@ impl<TmError, TcError> TcpTmSender<TmError, TcError> for SpacepacketsTmSender {
|
|||||||
/// The [TCP server integration tests](https://egit.irs.uni-stuttgart.de/rust/sat-rs/src/branch/main/satrs/tests/tcp_servers.rs)
|
/// The [TCP server integration tests](https://egit.irs.uni-stuttgart.de/rust/sat-rs/src/branch/main/satrs/tests/tcp_servers.rs)
|
||||||
/// also serves as the example application for this module.
|
/// also serves as the example application for this module.
|
||||||
pub struct TcpSpacepacketsServer<
|
pub struct TcpSpacepacketsServer<
|
||||||
TmSource: PacketSource<Error = TmError>,
|
TmSource: PacketSource<Error = ()>,
|
||||||
TcSender: PacketSenderRaw<Error = SendError>,
|
TcSender: PacketHandler<Error = GenericSendError>,
|
||||||
Validator: SpacePacketValidator,
|
Validator: SpacePacketValidator,
|
||||||
HandledConnection: HandledConnectionHandler,
|
HandledConnection: HandledConnectionHandler,
|
||||||
TmError,
|
|
||||||
SendError: 'static,
|
|
||||||
> {
|
> {
|
||||||
pub generic_server: TcpTmtcGenericServer<
|
pub generic_server: TcpTmtcGenericServer<
|
||||||
TmSource,
|
TmSource,
|
||||||
TcSender,
|
|
||||||
SpacepacketsTmSender,
|
SpacepacketsTmSender,
|
||||||
Validator,
|
CcsdsPacketParser<Validator, TcSender>,
|
||||||
HandledConnection,
|
HandledConnection,
|
||||||
TmError,
|
|
||||||
SendError,
|
|
||||||
>,
|
>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<
|
impl<
|
||||||
TmSource: PacketSource<Error = TmError>,
|
TmSource: PacketSource<Error = ()>,
|
||||||
TcSender: PacketSenderRaw<Error = TcError>,
|
TcSender: PacketHandler<Error = GenericSendError>,
|
||||||
Validator: SpacePacketValidator,
|
Validator: SpacePacketValidator,
|
||||||
HandledConnection: HandledConnectionHandler,
|
HandledConnection: HandledConnectionHandler,
|
||||||
TmError: 'static,
|
> TcpSpacepacketsServer<TmSource, TcSender, Validator, HandledConnection>
|
||||||
TcError: 'static,
|
|
||||||
> TcpSpacepacketsServer<TmSource, TcSender, Validator, HandledConnection, TmError, TcError>
|
|
||||||
{
|
{
|
||||||
///
|
///
|
||||||
/// ## Parameter
|
/// ## Parameter
|
||||||
@@ -122,7 +178,7 @@ impl<
|
|||||||
/// * `tm_source` - Generic TM source used by the server to pull telemetry packets which are
|
/// * `tm_source` - Generic TM source used by the server to pull telemetry packets which are
|
||||||
/// then sent back to the client.
|
/// then sent back to the client.
|
||||||
/// * `tc_sender` - Any received telecommands which were decoded successfully will be
|
/// * `tc_sender` - Any received telecommands which were decoded successfully will be
|
||||||
/// forwarded using this [PacketSenderRaw].
|
/// forwarded using this [PacketHandler].
|
||||||
/// * `validator` - Used to determine the space packets relevant for further processing and
|
/// * `validator` - Used to determine the space packets relevant for further processing and
|
||||||
/// to detect broken space packets.
|
/// to detect broken space packets.
|
||||||
/// * `handled_connection_hook` - Called to notify the user about a succesfully handled
|
/// * `handled_connection_hook` - Called to notify the user about a succesfully handled
|
||||||
@@ -132,18 +188,16 @@ impl<
|
|||||||
pub fn new(
|
pub fn new(
|
||||||
cfg: ServerConfig,
|
cfg: ServerConfig,
|
||||||
tm_source: TmSource,
|
tm_source: TmSource,
|
||||||
tc_sender: TcSender,
|
tc_parser: CcsdsPacketParser<Validator, TcSender>,
|
||||||
validator: Validator,
|
|
||||||
handled_connection_hook: HandledConnection,
|
handled_connection_hook: HandledConnection,
|
||||||
stop_signal: Option<Arc<AtomicBool>>,
|
stop_signal: Option<Arc<AtomicBool>>,
|
||||||
) -> Result<Self, std::io::Error> {
|
) -> Result<Self, std::io::Error> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
generic_server: TcpTmtcGenericServer::new(
|
generic_server: TcpTmtcGenericServer::new(
|
||||||
cfg,
|
cfg,
|
||||||
validator,
|
tc_parser,
|
||||||
SpacepacketsTmSender::default(),
|
SpacepacketsTmSender::default(),
|
||||||
tm_source,
|
tm_source,
|
||||||
tc_sender,
|
|
||||||
handled_connection_hook,
|
handled_connection_hook,
|
||||||
stop_signal,
|
stop_signal,
|
||||||
)?,
|
)?,
|
||||||
@@ -162,7 +216,7 @@ impl<
|
|||||||
pub fn handle_all_connections(
|
pub fn handle_all_connections(
|
||||||
&mut self,
|
&mut self,
|
||||||
poll_timeout: Option<Duration>
|
poll_timeout: Option<Duration>
|
||||||
) -> Result<ConnectionResult, TcpTmtcError<TmError, TcError>>;
|
) -> Result<ConnectionResult, std::io::Error>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -197,7 +251,6 @@ mod tests {
|
|||||||
ConnectionResult, ServerConfig,
|
ConnectionResult, ServerConfig,
|
||||||
tests::{ConnectionFinishedHandler, SyncTmSource},
|
tests::{ConnectionFinishedHandler, SyncTmSource},
|
||||||
},
|
},
|
||||||
queue::GenericSendError,
|
|
||||||
tmtc::PacketAsVec,
|
tmtc::PacketAsVec,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -224,23 +277,19 @@ mod tests {
|
|||||||
|
|
||||||
fn generic_tmtc_server(
|
fn generic_tmtc_server(
|
||||||
addr: &SocketAddr,
|
addr: &SocketAddr,
|
||||||
tc_sender: mpsc::Sender<PacketAsVec>,
|
tc_parser: super::CcsdsPacketParser<SimpleValidator, mpsc::Sender<PacketAsVec>>,
|
||||||
tm_source: SyncTmSource,
|
tm_source: SyncTmSource,
|
||||||
validator: SimpleValidator,
|
|
||||||
stop_signal: Option<Arc<AtomicBool>>,
|
stop_signal: Option<Arc<AtomicBool>>,
|
||||||
) -> TcpSpacepacketsServer<
|
) -> TcpSpacepacketsServer<
|
||||||
SyncTmSource,
|
SyncTmSource,
|
||||||
mpsc::Sender<PacketAsVec>,
|
mpsc::Sender<PacketAsVec>,
|
||||||
SimpleValidator,
|
SimpleValidator,
|
||||||
ConnectionFinishedHandler,
|
ConnectionFinishedHandler,
|
||||||
(),
|
|
||||||
GenericSendError,
|
|
||||||
> {
|
> {
|
||||||
TcpSpacepacketsServer::new(
|
TcpSpacepacketsServer::new(
|
||||||
ServerConfig::new(TCP_SERVER_ID, *addr, Duration::from_millis(2), 1024, 1024),
|
ServerConfig::new(TCP_SERVER_ID, *addr, Duration::from_millis(2), 1024, 1024),
|
||||||
tm_source,
|
tm_source,
|
||||||
tc_sender,
|
tc_parser,
|
||||||
validator,
|
|
||||||
ConnectionFinishedHandler::default(),
|
ConnectionFinishedHandler::default(),
|
||||||
stop_signal,
|
stop_signal,
|
||||||
)
|
)
|
||||||
@@ -256,9 +305,8 @@ mod tests {
|
|||||||
validator.0.insert(TEST_PACKET_ID_0);
|
validator.0.insert(TEST_PACKET_ID_0);
|
||||||
let mut tcp_server = generic_tmtc_server(
|
let mut tcp_server = generic_tmtc_server(
|
||||||
&auto_port_addr,
|
&auto_port_addr,
|
||||||
tc_sender.clone(),
|
super::CcsdsPacketParser::new(TCP_SERVER_ID, 1024, tc_sender.clone(), validator),
|
||||||
tm_source,
|
tm_source,
|
||||||
validator,
|
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
let dest_addr = tcp_server
|
let dest_addr = tcp_server
|
||||||
@@ -347,9 +395,8 @@ mod tests {
|
|||||||
validator.0.insert(TEST_PACKET_ID_1);
|
validator.0.insert(TEST_PACKET_ID_1);
|
||||||
let mut tcp_server = generic_tmtc_server(
|
let mut tcp_server = generic_tmtc_server(
|
||||||
&auto_port_addr,
|
&auto_port_addr,
|
||||||
tc_sender.clone(),
|
super::CcsdsPacketParser::new(TCP_SERVER_ID, 1024, tc_sender.clone(), validator),
|
||||||
tm_source,
|
tm_source,
|
||||||
validator,
|
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
let dest_addr = tcp_server
|
let dest_addr = tcp_server
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
//! Generic UDP TC server.
|
//! Generic UDP TC server.
|
||||||
use crate::ComponentId;
|
use crate::ComponentId;
|
||||||
use crate::tmtc::PacketSenderRaw;
|
use crate::tmtc::PacketHandler;
|
||||||
use core::fmt::Debug;
|
use core::fmt::Debug;
|
||||||
use std::io::{self, ErrorKind};
|
use std::io::{self, ErrorKind};
|
||||||
use std::net::{SocketAddr, ToSocketAddrs, UdpSocket};
|
use std::net::{SocketAddr, ToSocketAddrs, UdpSocket};
|
||||||
@@ -12,7 +12,7 @@ use std::vec::Vec;
|
|||||||
///
|
///
|
||||||
/// It caches all received telecomands into a vector. The maximum expected telecommand size should
|
/// It caches all received telecomands into a vector. The maximum expected telecommand size should
|
||||||
/// be declared upfront. This avoids dynamic allocation during run-time. The user can specify a TC
|
/// be declared upfront. This avoids dynamic allocation during run-time. The user can specify a TC
|
||||||
/// sender in form of a special trait object which implements [PacketSenderRaw]. For example, this
|
/// sender in form of a special trait object which implements [PacketHandler]. For example, this
|
||||||
/// can be used to send the telecommands to a centralized TC source component for further
|
/// can be used to send the telecommands to a centralized TC source component for further
|
||||||
/// processing and routing.
|
/// processing and routing.
|
||||||
///
|
///
|
||||||
@@ -24,7 +24,7 @@ use std::vec::Vec;
|
|||||||
/// use spacepackets::ecss::WritablePusPacket;
|
/// use spacepackets::ecss::WritablePusPacket;
|
||||||
/// use satrs::hal::std::udp_server::UdpTcServer;
|
/// use satrs::hal::std::udp_server::UdpTcServer;
|
||||||
/// use satrs::ComponentId;
|
/// use satrs::ComponentId;
|
||||||
/// use satrs::tmtc::PacketSenderRaw;
|
/// use satrs::tmtc::PacketHandler;
|
||||||
/// use spacepackets::SpHeader;
|
/// use spacepackets::SpHeader;
|
||||||
/// use spacepackets::ecss::tc::{PusTcCreator, CreatorConfig};
|
/// use spacepackets::ecss::tc::{PusTcCreator, CreatorConfig};
|
||||||
/// use arbitrary_int::u11;
|
/// use arbitrary_int::u11;
|
||||||
@@ -60,7 +60,7 @@ use std::vec::Vec;
|
|||||||
/// [example code](https://egit.irs.uni-stuttgart.de/rust/sat-rs/src/branch/main/satrs-example/src/tmtc.rs#L67)
|
/// [example code](https://egit.irs.uni-stuttgart.de/rust/sat-rs/src/branch/main/satrs-example/src/tmtc.rs#L67)
|
||||||
/// on how to use this TC server. It uses the server to receive PUS telecommands on a specific port
|
/// on how to use this TC server. It uses the server to receive PUS telecommands on a specific port
|
||||||
/// and then forwards them to a generic CCSDS packet receiver.
|
/// and then forwards them to a generic CCSDS packet receiver.
|
||||||
pub struct UdpTcServer<TcSender: PacketSenderRaw<Error = SendError>, SendError> {
|
pub struct UdpTcServer<TcSender: PacketHandler<Error = SendError>, SendError> {
|
||||||
pub id: ComponentId,
|
pub id: ComponentId,
|
||||||
pub socket: UdpSocket,
|
pub socket: UdpSocket,
|
||||||
recv_buf: Vec<u8>,
|
recv_buf: Vec<u8>,
|
||||||
@@ -78,7 +78,7 @@ pub enum ReceiveResult<SendError: Debug + 'static> {
|
|||||||
Send(SendError),
|
Send(SendError),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<TcSender: PacketSenderRaw<Error = SendError>, SendError: Debug + 'static>
|
impl<TcSender: PacketHandler<Error = SendError>, SendError: Debug + 'static>
|
||||||
UdpTcServer<TcSender, SendError>
|
UdpTcServer<TcSender, SendError>
|
||||||
{
|
{
|
||||||
pub fn new<A: ToSocketAddrs>(
|
pub fn new<A: ToSocketAddrs>(
|
||||||
@@ -112,7 +112,7 @@ impl<TcSender: PacketSenderRaw<Error = SendError>, SendError: Debug + 'static>
|
|||||||
let (num_bytes, from) = res;
|
let (num_bytes, from) = res;
|
||||||
self.sender_addr = Some(from);
|
self.sender_addr = Some(from);
|
||||||
self.tc_sender
|
self.tc_sender
|
||||||
.send_packet(self.id, &self.recv_buf[0..num_bytes])
|
.handle_packet(self.id, &self.recv_buf[0..num_bytes])
|
||||||
.map_err(ReceiveResult::Send)?;
|
.map_err(ReceiveResult::Send)?;
|
||||||
Ok(res)
|
Ok(res)
|
||||||
}
|
}
|
||||||
@@ -127,7 +127,7 @@ mod tests {
|
|||||||
use crate::ComponentId;
|
use crate::ComponentId;
|
||||||
use crate::hal::std::udp_server::{ReceiveResult, UdpTcServer};
|
use crate::hal::std::udp_server::{ReceiveResult, UdpTcServer};
|
||||||
use crate::queue::GenericSendError;
|
use crate::queue::GenericSendError;
|
||||||
use crate::tmtc::PacketSenderRaw;
|
use crate::tmtc::PacketHandler;
|
||||||
use arbitrary_int::u11;
|
use arbitrary_int::u11;
|
||||||
use core::cell::RefCell;
|
use core::cell::RefCell;
|
||||||
use spacepackets::SpHeader;
|
use spacepackets::SpHeader;
|
||||||
@@ -146,10 +146,10 @@ mod tests {
|
|||||||
pub sent_cmds: RefCell<VecDeque<Vec<u8>>>,
|
pub sent_cmds: RefCell<VecDeque<Vec<u8>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PacketSenderRaw for PingReceiver {
|
impl PacketHandler for PingReceiver {
|
||||||
type Error = GenericSendError;
|
type Error = GenericSendError;
|
||||||
|
|
||||||
fn send_packet(&self, sender_id: ComponentId, tc_raw: &[u8]) -> Result<(), Self::Error> {
|
fn handle_packet(&self, sender_id: ComponentId, tc_raw: &[u8]) -> Result<(), Self::Error> {
|
||||||
assert_eq!(sender_id, UDP_SERVER_ID);
|
assert_eq!(sender_id, UDP_SERVER_ID);
|
||||||
let mut sent_data = Vec::new();
|
let mut sent_data = Vec::new();
|
||||||
sent_data.extend_from_slice(tc_raw);
|
sent_data.extend_from_slice(tc_raw);
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ pub use spacepackets;
|
|||||||
use spacepackets::PacketId;
|
use spacepackets::PacketId;
|
||||||
|
|
||||||
/// Generic component ID type.
|
/// Generic component ID type.
|
||||||
pub type ComponentId = u64;
|
pub type ComponentId = u32;
|
||||||
|
|
||||||
pub trait ValidatorU16Id {
|
pub trait ValidatorU16Id {
|
||||||
fn validate(&self, id: u16) -> bool;
|
fn validate(&self, id: u16) -> bool;
|
||||||
|
|||||||
@@ -311,7 +311,7 @@ pub mod alloc_mod {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use alloc::string::{String, ToString};
|
use alloc::string::{String, ToString};
|
||||||
use alloc::vec;
|
use alloc::vec;
|
||||||
use arbitrary_int::u11;
|
use arbitrary_int::{u11, u21};
|
||||||
use spacepackets::ecss::PusPacket;
|
use spacepackets::ecss::PusPacket;
|
||||||
use spacepackets::ecss::event::Subservice;
|
use spacepackets::ecss::event::Subservice;
|
||||||
use spacepackets::ecss::tm::PusTmReader;
|
use spacepackets::ecss::tm::PusTmReader;
|
||||||
@@ -325,7 +325,7 @@ mod tests {
|
|||||||
const LOW_SEV_EVENT: EventU32 = EventU32::new(Severity::Low, 1, 5);
|
const LOW_SEV_EVENT: EventU32 = EventU32::new(Severity::Low, 1, 5);
|
||||||
const EMPTY_STAMP: [u8; 7] = [0; 7];
|
const EMPTY_STAMP: [u8; 7] = [0; 7];
|
||||||
const TEST_APID: u11 = u11::new(0x02);
|
const TEST_APID: u11 = u11::new(0x02);
|
||||||
const TEST_ID: UniqueApidTargetId = UniqueApidTargetId::new(TEST_APID, 0x05);
|
const TEST_ID: UniqueApidTargetId = UniqueApidTargetId::new(TEST_APID, u21::new(0x05));
|
||||||
|
|
||||||
fn create_basic_man_1() -> DefaultPusEventU32TmCreator {
|
fn create_basic_man_1() -> DefaultPusEventU32TmCreator {
|
||||||
let reporter = EventReporter::new(TEST_ID.raw(), TEST_APID, 0, 128);
|
let reporter = EventReporter::new(TEST_ID.raw(), TEST_APID, 0, 128);
|
||||||
|
|||||||
@@ -1258,7 +1258,7 @@ pub(crate) fn source_buffer_large_enough(
|
|||||||
|
|
||||||
#[cfg(any(feature = "test_util", test))]
|
#[cfg(any(feature = "test_util", test))]
|
||||||
pub mod test_util {
|
pub mod test_util {
|
||||||
use arbitrary_int::u11;
|
use arbitrary_int::{u11, u21};
|
||||||
use spacepackets::ecss::{tc::PusTcCreator, tm::PusTmReader};
|
use spacepackets::ecss::{tc::PusTcCreator, tm::PusTmReader};
|
||||||
|
|
||||||
use crate::request::UniqueApidTargetId;
|
use crate::request::UniqueApidTargetId;
|
||||||
@@ -1269,8 +1269,8 @@ pub mod test_util {
|
|||||||
};
|
};
|
||||||
|
|
||||||
pub const TEST_APID: u11 = u11::new(0x101);
|
pub const TEST_APID: u11 = u11::new(0x101);
|
||||||
pub const TEST_UNIQUE_ID_0: u32 = 0x05;
|
pub const TEST_UNIQUE_ID_0: u21 = u21::new(0x05);
|
||||||
pub const TEST_UNIQUE_ID_1: u32 = 0x06;
|
pub const TEST_UNIQUE_ID_1: u21 = u21::new(0x06);
|
||||||
|
|
||||||
pub const TEST_COMPONENT_ID_0: UniqueApidTargetId =
|
pub const TEST_COMPONENT_ID_0: UniqueApidTargetId =
|
||||||
UniqueApidTargetId::new(TEST_APID, TEST_UNIQUE_ID_0);
|
UniqueApidTargetId::new(TEST_APID, TEST_UNIQUE_ID_0);
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ mod tests {
|
|||||||
use std::sync::mpsc;
|
use std::sync::mpsc;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
ComponentId,
|
||||||
mode::{
|
mode::{
|
||||||
ModeAndSubmode, ModeReply, ModeReplySender, ModeRequest, ModeRequestSender,
|
ModeAndSubmode, ModeReply, ModeReplySender, ModeRequest, ModeRequestSender,
|
||||||
ModeRequestorAndHandlerMpsc, ModeRequestorOneChildMpsc,
|
ModeRequestorAndHandlerMpsc, ModeRequestorOneChildMpsc,
|
||||||
@@ -44,9 +45,9 @@ mod tests {
|
|||||||
request::{GenericMessage, MessageMetadata},
|
request::{GenericMessage, MessageMetadata},
|
||||||
};
|
};
|
||||||
|
|
||||||
const TEST_COMPONENT_ID_0: u64 = 5;
|
const TEST_COMPONENT_ID_0: ComponentId = 5;
|
||||||
const TEST_COMPONENT_ID_1: u64 = 6;
|
const TEST_COMPONENT_ID_1: ComponentId = 6;
|
||||||
const TEST_COMPONENT_ID_2: u64 = 7;
|
const TEST_COMPONENT_ID_2: ComponentId = 7;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_simple_mode_requestor() {
|
fn test_simple_mode_requestor() {
|
||||||
|
|||||||
@@ -25,11 +25,11 @@
|
|||||||
//! use spacepackets::SpHeader;
|
//! use spacepackets::SpHeader;
|
||||||
//! use spacepackets::ecss::tc::{PusTcCreator, PusTcSecondaryHeader, CreatorConfig};
|
//! use spacepackets::ecss::tc::{PusTcCreator, PusTcSecondaryHeader, CreatorConfig};
|
||||||
//! use spacepackets::ecss::tm::PusTmReader;
|
//! use spacepackets::ecss::tm::PusTmReader;
|
||||||
//! use arbitrary_int::u11;
|
//! use arbitrary_int::{u11, u21};
|
||||||
//!
|
//!
|
||||||
//! const EMPTY_STAMP: [u8; 7] = [0; 7];
|
//! const EMPTY_STAMP: [u8; 7] = [0; 7];
|
||||||
//! const TEST_APID: u11 = u11::new(0x02);
|
//! const TEST_APID: u11 = u11::new(0x02);
|
||||||
//! const TEST_COMPONENT_ID: UniqueApidTargetId = UniqueApidTargetId::new(TEST_APID, 0x05);
|
//! const TEST_COMPONENT_ID: UniqueApidTargetId = UniqueApidTargetId::new(TEST_APID, u21::new(0x05));
|
||||||
//!
|
//!
|
||||||
//! let pool_cfg = StaticPoolConfig::new_from_subpool_cfg_tuples(
|
//! let pool_cfg = StaticPoolConfig::new_from_subpool_cfg_tuples(
|
||||||
//! vec![(10, 32), (10, 64), (10, 128), (10, 1024)], false
|
//! vec![(10, 32), (10, 64), (10, 128), (10, 1024)], false
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use arbitrary_int::u11;
|
use arbitrary_int::{prelude::*, u11, u21};
|
||||||
use core::{fmt, marker::PhantomData};
|
use core::{fmt, marker::PhantomData};
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@@ -29,11 +29,11 @@ pub type Apid = u11;
|
|||||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||||
pub struct UniqueApidTargetId {
|
pub struct UniqueApidTargetId {
|
||||||
pub apid: Apid,
|
pub apid: Apid,
|
||||||
pub unique_id: u32,
|
pub unique_id: u21,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UniqueApidTargetId {
|
impl UniqueApidTargetId {
|
||||||
pub const fn new(apid: Apid, target: u32) -> Self {
|
pub const fn new(apid: Apid, target: u21) -> Self {
|
||||||
Self {
|
Self {
|
||||||
apid,
|
apid,
|
||||||
unique_id: target,
|
unique_id: target,
|
||||||
@@ -41,7 +41,7 @@ impl UniqueApidTargetId {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn raw(&self) -> ComponentId {
|
pub fn raw(&self) -> ComponentId {
|
||||||
((self.apid.value() as u64) << 32) | (self.unique_id as u64)
|
((self.apid.value() as u32) << 21) | (self.unique_id.value())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn id(&self) -> ComponentId {
|
pub fn id(&self) -> ComponentId {
|
||||||
@@ -61,21 +61,21 @@ impl UniqueApidTargetId {
|
|||||||
}
|
}
|
||||||
Ok(Self::new(
|
Ok(Self::new(
|
||||||
tc.apid(),
|
tc.apid(),
|
||||||
u32::from_be_bytes(tc.user_data()[0..4].try_into().unwrap()),
|
u21::new(u32::from_be_bytes(tc.user_data()[0..4].try_into().unwrap())),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<u64> for UniqueApidTargetId {
|
impl From<ComponentId> for UniqueApidTargetId {
|
||||||
fn from(raw: u64) -> Self {
|
fn from(raw: ComponentId) -> Self {
|
||||||
Self {
|
Self {
|
||||||
apid: u11::new((raw >> 32) as u16),
|
apid: u11::new((raw >> 21) as u16),
|
||||||
unique_id: raw as u32,
|
unique_id: u21::new(raw & u21::MAX.value()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<UniqueApidTargetId> for u64 {
|
impl From<UniqueApidTargetId> for ComponentId {
|
||||||
fn from(target_and_apid_id: UniqueApidTargetId) -> Self {
|
fn from(target_and_apid_id: UniqueApidTargetId) -> Self {
|
||||||
target_and_apid_id.raw()
|
target_and_apid_id.raw()
|
||||||
}
|
}
|
||||||
@@ -497,7 +497,7 @@ mod tests {
|
|||||||
use std::sync::mpsc;
|
use std::sync::mpsc;
|
||||||
|
|
||||||
use alloc::string::ToString;
|
use alloc::string::ToString;
|
||||||
use arbitrary_int::{u11, u14};
|
use arbitrary_int::{u11, u14, u21};
|
||||||
use spacepackets::{
|
use spacepackets::{
|
||||||
ByteConversionError, SpHeader,
|
ByteConversionError, SpHeader,
|
||||||
ecss::{
|
ecss::{
|
||||||
@@ -507,27 +507,28 @@ mod tests {
|
|||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
ComponentId,
|
||||||
queue::{GenericReceiveError, GenericSendError},
|
queue::{GenericReceiveError, GenericSendError},
|
||||||
request::{Apid, MessageMetadata, MessageSenderMap, MessageSenderStoreProvider},
|
request::{Apid, MessageMetadata, MessageSenderMap, MessageSenderStoreProvider},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{GenericMessage, MessageReceiverWithId, UniqueApidTargetId};
|
use super::{GenericMessage, MessageReceiverWithId, UniqueApidTargetId};
|
||||||
|
|
||||||
const TEST_CHANNEL_ID_0: u64 = 1;
|
const TEST_CHANNEL_ID_0: ComponentId = 1;
|
||||||
const TEST_CHANNEL_ID_1: u64 = 2;
|
const TEST_CHANNEL_ID_1: ComponentId = 2;
|
||||||
const TEST_CHANNEL_ID_2: u64 = 3;
|
const TEST_CHANNEL_ID_2: ComponentId = 3;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_basic_target_id_with_apid() {
|
fn test_basic_target_id_with_apid() {
|
||||||
let id = UniqueApidTargetId::new(Apid::new(0x111), 0x01);
|
let id = UniqueApidTargetId::new(Apid::new(0x111), u21::new(0x01));
|
||||||
assert_eq!(id.apid.value(), 0x111);
|
assert_eq!(id.apid.value(), 0x111);
|
||||||
assert_eq!(id.unique_id, 0x01);
|
assert_eq!(id.unique_id.value(), 0x01);
|
||||||
assert_eq!(id.id(), id.raw());
|
assert_eq!(id.id(), id.raw());
|
||||||
assert_eq!(u64::from(id), id.raw());
|
assert_eq!(ComponentId::from(id), id.raw());
|
||||||
let id_raw = id.raw();
|
let id_raw = id.raw();
|
||||||
let id_from_raw = UniqueApidTargetId::from(id_raw);
|
let id_from_raw = UniqueApidTargetId::from(id_raw);
|
||||||
assert_eq!(id_from_raw, id);
|
assert_eq!(id_from_raw, id);
|
||||||
assert_eq!(id.id(), (0x111 << 32) | 0x01);
|
assert_eq!(id.id(), (0x111 << 21) | 0x01);
|
||||||
let string = id.to_string();
|
let string = id.to_string();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
string,
|
string,
|
||||||
@@ -543,7 +544,7 @@ mod tests {
|
|||||||
PusTcCreator::new_simple(sp_header, 17, 1, &app_data, CreatorConfig::default());
|
PusTcCreator::new_simple(sp_header, 17, 1, &app_data, CreatorConfig::default());
|
||||||
let id = UniqueApidTargetId::from_pus_tc(&pus_tc).unwrap();
|
let id = UniqueApidTargetId::from_pus_tc(&pus_tc).unwrap();
|
||||||
assert_eq!(id.apid.value(), 0x111);
|
assert_eq!(id.apid.value(), 0x111);
|
||||||
assert_eq!(id.unique_id, 1);
|
assert_eq!(id.unique_id.value(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@@ -782,7 +782,7 @@ mod tests {
|
|||||||
);
|
);
|
||||||
assert_eq!(self.sender.requests.borrow().len(), 2);
|
assert_eq!(self.sender.requests.borrow().len(), 2);
|
||||||
let req_0 = self.sender.requests.get_mut().pop_front().unwrap();
|
let req_0 = self.sender.requests.get_mut().pop_front().unwrap();
|
||||||
assert_eq!(req_0.target_id, ExampleTargetId::Target0 as u64);
|
assert_eq!(req_0.target_id, ExampleTargetId::Target0 as ComponentId);
|
||||||
assert_eq!(req_0.request_id, expected_req_id);
|
assert_eq!(req_0.request_id, expected_req_id);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
req_0.request,
|
req_0.request,
|
||||||
@@ -792,7 +792,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
let req_1 = self.sender.requests.borrow_mut().pop_front().unwrap();
|
let req_1 = self.sender.requests.borrow_mut().pop_front().unwrap();
|
||||||
assert_eq!(req_1.target_id, ExampleTargetId::Target1 as u64);
|
assert_eq!(req_1.target_id, ExampleTargetId::Target1 as ComponentId);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
req_1.request,
|
req_1.request,
|
||||||
ModeRequest::SetMode {
|
ModeRequest::SetMode {
|
||||||
@@ -808,7 +808,7 @@ mod tests {
|
|||||||
);
|
);
|
||||||
assert_eq!(self.sender.requests.borrow().len(), 1);
|
assert_eq!(self.sender.requests.borrow().len(), 1);
|
||||||
let req_0 = self.sender.requests.get_mut().pop_front().unwrap();
|
let req_0 = self.sender.requests.get_mut().pop_front().unwrap();
|
||||||
assert_eq!(req_0.target_id, ExampleTargetId::Target2 as u64);
|
assert_eq!(req_0.target_id, ExampleTargetId::Target2 as ComponentId);
|
||||||
assert_eq!(req_0.request_id, expected_req_id);
|
assert_eq!(req_0.request_id, expected_req_id);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
req_0.request,
|
req_0.request,
|
||||||
@@ -827,7 +827,7 @@ mod tests {
|
|||||||
assert_eq!(self.execution_helper.current_sequence_index().unwrap(), 0);
|
assert_eq!(self.execution_helper.current_sequence_index().unwrap(), 0);
|
||||||
assert_eq!(self.sender.requests.borrow().len(), 2);
|
assert_eq!(self.sender.requests.borrow().len(), 2);
|
||||||
let req_0 = self.sender.requests.get_mut().pop_front().unwrap();
|
let req_0 = self.sender.requests.get_mut().pop_front().unwrap();
|
||||||
assert_eq!(req_0.target_id, ExampleTargetId::Target0 as u64);
|
assert_eq!(req_0.target_id, ExampleTargetId::Target0 as ComponentId);
|
||||||
assert_eq!(req_0.request_id, expected_req_id);
|
assert_eq!(req_0.request_id, expected_req_id);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
req_0.request,
|
req_0.request,
|
||||||
@@ -837,7 +837,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
let req_1 = self.sender.requests.borrow_mut().pop_front().unwrap();
|
let req_1 = self.sender.requests.borrow_mut().pop_front().unwrap();
|
||||||
assert_eq!(req_1.target_id, ExampleTargetId::Target1 as u64);
|
assert_eq!(req_1.target_id, ExampleTargetId::Target1 as ComponentId);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
req_1.request,
|
req_1.request,
|
||||||
ModeRequest::SetMode {
|
ModeRequest::SetMode {
|
||||||
@@ -850,9 +850,9 @@ mod tests {
|
|||||||
|
|
||||||
fn create_default_mode_store() -> ModeStoreVec {
|
fn create_default_mode_store() -> ModeStoreVec {
|
||||||
let mut mode_store = ModeStoreVec::default();
|
let mut mode_store = ModeStoreVec::default();
|
||||||
mode_store.add_component(ExampleTargetId::Target0 as u64, UNKNOWN_MODE);
|
mode_store.add_component(ExampleTargetId::Target0 as ComponentId, UNKNOWN_MODE);
|
||||||
mode_store.add_component(ExampleTargetId::Target1 as u64, UNKNOWN_MODE);
|
mode_store.add_component(ExampleTargetId::Target1 as ComponentId, UNKNOWN_MODE);
|
||||||
mode_store.add_component(ExampleTargetId::Target2 as u64, UNKNOWN_MODE);
|
mode_store.add_component(ExampleTargetId::Target2 as ComponentId, UNKNOWN_MODE);
|
||||||
mode_store
|
mode_store
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -863,13 +863,13 @@ mod tests {
|
|||||||
let mut table_seq_0 = SequenceTableMapTable::new("MODE_0_SEQ_0");
|
let mut table_seq_0 = SequenceTableMapTable::new("MODE_0_SEQ_0");
|
||||||
table_seq_0.add_entry(SequenceTableEntry::new(
|
table_seq_0.add_entry(SequenceTableEntry::new(
|
||||||
"TARGET_0",
|
"TARGET_0",
|
||||||
ExampleTargetId::Target0 as u64,
|
ExampleTargetId::Target0 as ComponentId,
|
||||||
SUBSYSTEM_MD0_TGT0_MODE,
|
SUBSYSTEM_MD0_TGT0_MODE,
|
||||||
false,
|
false,
|
||||||
));
|
));
|
||||||
table_seq_0.add_entry(SequenceTableEntry::new(
|
table_seq_0.add_entry(SequenceTableEntry::new(
|
||||||
"TARGET_1",
|
"TARGET_1",
|
||||||
ExampleTargetId::Target1 as u64,
|
ExampleTargetId::Target1 as ComponentId,
|
||||||
SUBSYSTEM_MD0_TGT1_MODE,
|
SUBSYSTEM_MD0_TGT1_MODE,
|
||||||
false,
|
false,
|
||||||
));
|
));
|
||||||
@@ -881,13 +881,13 @@ mod tests {
|
|||||||
let mut table_seq_0 = SequenceTableMapTable::new("MODE_1_SEQ_0");
|
let mut table_seq_0 = SequenceTableMapTable::new("MODE_1_SEQ_0");
|
||||||
table_seq_0.add_entry(SequenceTableEntry::new(
|
table_seq_0.add_entry(SequenceTableEntry::new(
|
||||||
"MD1_SEQ0_TGT0",
|
"MD1_SEQ0_TGT0",
|
||||||
ExampleTargetId::Target0 as u64,
|
ExampleTargetId::Target0 as ComponentId,
|
||||||
SUBSYSTEM_MD1_ST0_TGT0_MODE,
|
SUBSYSTEM_MD1_ST0_TGT0_MODE,
|
||||||
false,
|
false,
|
||||||
));
|
));
|
||||||
table_seq_0.add_entry(SequenceTableEntry::new(
|
table_seq_0.add_entry(SequenceTableEntry::new(
|
||||||
"MD1_SEQ0_TGT1",
|
"MD1_SEQ0_TGT1",
|
||||||
ExampleTargetId::Target1 as u64,
|
ExampleTargetId::Target1 as ComponentId,
|
||||||
SUBSYSTEM_MD1_ST0_TGT1_MODE,
|
SUBSYSTEM_MD1_ST0_TGT1_MODE,
|
||||||
false,
|
false,
|
||||||
));
|
));
|
||||||
@@ -895,7 +895,7 @@ mod tests {
|
|||||||
let mut table_seq_1 = SequenceTableMapTable::new("MODE_1_SEQ_1");
|
let mut table_seq_1 = SequenceTableMapTable::new("MODE_1_SEQ_1");
|
||||||
table_seq_1.add_entry(SequenceTableEntry::new(
|
table_seq_1.add_entry(SequenceTableEntry::new(
|
||||||
"MD1_SEQ1_TGT2",
|
"MD1_SEQ1_TGT2",
|
||||||
ExampleTargetId::Target2 as u64,
|
ExampleTargetId::Target2 as ComponentId,
|
||||||
SUBSYSTEM_MD1_ST1_TGT2_MODE,
|
SUBSYSTEM_MD1_ST1_TGT2_MODE,
|
||||||
false,
|
false,
|
||||||
));
|
));
|
||||||
@@ -1263,11 +1263,11 @@ mod tests {
|
|||||||
assert_eq!(req.request, ModeRequest::AnnounceModeRecursive);
|
assert_eq!(req.request, ModeRequest::AnnounceModeRecursive);
|
||||||
};
|
};
|
||||||
let req0 = tb.sender.requests.borrow_mut().pop_front().unwrap();
|
let req0 = tb.sender.requests.borrow_mut().pop_front().unwrap();
|
||||||
check_req(req0, ExampleTargetId::Target0 as u64);
|
check_req(req0, ExampleTargetId::Target0 as ComponentId);
|
||||||
let req1 = tb.sender.requests.borrow_mut().pop_front().unwrap();
|
let req1 = tb.sender.requests.borrow_mut().pop_front().unwrap();
|
||||||
check_req(req1, ExampleTargetId::Target1 as u64);
|
check_req(req1, ExampleTargetId::Target1 as ComponentId);
|
||||||
let req2 = tb.sender.requests.borrow_mut().pop_front().unwrap();
|
let req2 = tb.sender.requests.borrow_mut().pop_front().unwrap();
|
||||||
check_req(req2, ExampleTargetId::Target2 as u64);
|
check_req(req2, ExampleTargetId::Target2 as ComponentId);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -1283,11 +1283,11 @@ mod tests {
|
|||||||
assert_eq!(req.request, ModeRequest::AnnounceMode);
|
assert_eq!(req.request, ModeRequest::AnnounceMode);
|
||||||
};
|
};
|
||||||
let req0 = tb.sender.requests.borrow_mut().pop_front().unwrap();
|
let req0 = tb.sender.requests.borrow_mut().pop_front().unwrap();
|
||||||
check_req(req0, ExampleTargetId::Target0 as u64);
|
check_req(req0, ExampleTargetId::Target0 as ComponentId);
|
||||||
let req1 = tb.sender.requests.borrow_mut().pop_front().unwrap();
|
let req1 = tb.sender.requests.borrow_mut().pop_front().unwrap();
|
||||||
check_req(req1, ExampleTargetId::Target1 as u64);
|
check_req(req1, ExampleTargetId::Target1 as ComponentId);
|
||||||
let req2 = tb.sender.requests.borrow_mut().pop_front().unwrap();
|
let req2 = tb.sender.requests.borrow_mut().pop_front().unwrap();
|
||||||
check_req(req2, ExampleTargetId::Target2 as u64);
|
check_req(req2, ExampleTargetId::Target2 as ComponentId);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@@ -50,20 +50,20 @@ impl PacketInPool {
|
|||||||
|
|
||||||
/// Generic trait for object which can send any packets in form of a raw bytestream, with
|
/// Generic trait for object which can send any packets in form of a raw bytestream, with
|
||||||
/// no assumptions about the received protocol.
|
/// no assumptions about the received protocol.
|
||||||
pub trait PacketSenderRaw: Send {
|
pub trait PacketHandler: Send {
|
||||||
type Error;
|
type Error;
|
||||||
fn send_packet(&self, sender_id: ComponentId, packet: &[u8]) -> Result<(), Self::Error>;
|
fn handle_packet(&self, sender_id: ComponentId, packet: &[u8]) -> Result<(), Self::Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Extension trait of [PacketSenderRaw] which allows downcasting by implementing [Downcast].
|
/// Extension trait of [PacketHandler] which allows downcasting by implementing [Downcast].
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
pub trait PacketSenderRawExt: PacketSenderRaw + Downcast {
|
pub trait PacketSenderRawExt: PacketHandler + Downcast {
|
||||||
// Remove this once trait upcasting coercion has been implemented.
|
// Remove this once trait upcasting coercion has been implemented.
|
||||||
// Tracking issue: https://github.com/rust-lang/rust/issues/65991
|
// Tracking issue: https://github.com/rust-lang/rust/issues/65991
|
||||||
fn upcast(&self) -> &dyn PacketSenderRaw<Error = Self::Error>;
|
fn upcast(&self) -> &dyn PacketHandler<Error = Self::Error>;
|
||||||
// Remove this once trait upcasting coercion has been implemented.
|
// Remove this once trait upcasting coercion has been implemented.
|
||||||
// Tracking issue: https://github.com/rust-lang/rust/issues/65991
|
// Tracking issue: https://github.com/rust-lang/rust/issues/65991
|
||||||
fn upcast_mut(&mut self) -> &mut dyn PacketSenderRaw<Error = Self::Error>;
|
fn upcast_mut(&mut self) -> &mut dyn PacketHandler<Error = Self::Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Blanket implementation to automatically implement [PacketSenderRawExt] when the [alloc]
|
/// Blanket implementation to automatically implement [PacketSenderRawExt] when the [alloc]
|
||||||
@@ -71,16 +71,16 @@ pub trait PacketSenderRawExt: PacketSenderRaw + Downcast {
|
|||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
impl<T> PacketSenderRawExt for T
|
impl<T> PacketSenderRawExt for T
|
||||||
where
|
where
|
||||||
T: PacketSenderRaw + Send + 'static,
|
T: PacketHandler + Send + 'static,
|
||||||
{
|
{
|
||||||
// Remove this once trait upcasting coercion has been implemented.
|
// Remove this once trait upcasting coercion has been implemented.
|
||||||
// Tracking issue: https://github.com/rust-lang/rust/issues/65991
|
// Tracking issue: https://github.com/rust-lang/rust/issues/65991
|
||||||
fn upcast(&self) -> &dyn PacketSenderRaw<Error = Self::Error> {
|
fn upcast(&self) -> &dyn PacketHandler<Error = Self::Error> {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
// Remove this once trait upcasting coercion has been implemented.
|
// Remove this once trait upcasting coercion has been implemented.
|
||||||
// Tracking issue: https://github.com/rust-lang/rust/issues/65991
|
// Tracking issue: https://github.com/rust-lang/rust/issues/65991
|
||||||
fn upcast_mut(&mut self) -> &mut dyn PacketSenderRaw<Error = Self::Error> {
|
fn upcast_mut(&mut self) -> &mut dyn PacketHandler<Error = Self::Error> {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -288,19 +288,19 @@ pub mod std_mod {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PacketSenderRaw for mpsc::Sender<PacketAsVec> {
|
impl PacketHandler for mpsc::Sender<PacketAsVec> {
|
||||||
type Error = GenericSendError;
|
type Error = GenericSendError;
|
||||||
|
|
||||||
fn send_packet(&self, sender_id: ComponentId, packet: &[u8]) -> Result<(), Self::Error> {
|
fn handle_packet(&self, sender_id: ComponentId, packet: &[u8]) -> Result<(), Self::Error> {
|
||||||
self.send(PacketAsVec::new(sender_id, packet.to_vec()))
|
self.send(PacketAsVec::new(sender_id, packet.to_vec()))
|
||||||
.map_err(|_| GenericSendError::RxDisconnected)
|
.map_err(|_| GenericSendError::RxDisconnected)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PacketSenderRaw for mpsc::SyncSender<PacketAsVec> {
|
impl PacketHandler for mpsc::SyncSender<PacketAsVec> {
|
||||||
type Error = GenericSendError;
|
type Error = GenericSendError;
|
||||||
|
|
||||||
fn send_packet(&self, sender_id: ComponentId, tc_raw: &[u8]) -> Result<(), Self::Error> {
|
fn handle_packet(&self, sender_id: ComponentId, tc_raw: &[u8]) -> Result<(), Self::Error> {
|
||||||
self.try_send(PacketAsVec::new(sender_id, tc_raw.to_vec()))
|
self.try_send(PacketAsVec::new(sender_id, tc_raw.to_vec()))
|
||||||
.map_err(|e| match e {
|
.map_err(|e| match e {
|
||||||
mpsc::TrySendError::Full(_) => GenericSendError::QueueFull(None),
|
mpsc::TrySendError::Full(_) => GenericSendError::QueueFull(None),
|
||||||
@@ -402,12 +402,12 @@ pub mod std_mod {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Sender: PacketInPoolSender, PacketStore: CcsdsPacketPool + Send> PacketSenderRaw
|
impl<Sender: PacketInPoolSender, PacketStore: CcsdsPacketPool + Send> PacketHandler
|
||||||
for PacketSenderWithSharedPool<Sender, PacketStore>
|
for PacketSenderWithSharedPool<Sender, PacketStore>
|
||||||
{
|
{
|
||||||
type Error = StoreAndSendError;
|
type Error = StoreAndSendError;
|
||||||
|
|
||||||
fn send_packet(&self, sender_id: ComponentId, packet: &[u8]) -> Result<(), Self::Error> {
|
fn handle_packet(&self, sender_id: ComponentId, packet: &[u8]) -> Result<(), Self::Error> {
|
||||||
let mut shared_pool = self.shared_pool.borrow_mut();
|
let mut shared_pool = self.shared_pool.borrow_mut();
|
||||||
let store_addr = shared_pool.add_raw_tc(packet)?;
|
let store_addr = shared_pool.add_raw_tc(packet)?;
|
||||||
drop(shared_pool);
|
drop(shared_pool);
|
||||||
@@ -450,7 +450,7 @@ pub mod std_mod {
|
|||||||
_sp_header: &SpHeader,
|
_sp_header: &SpHeader,
|
||||||
tc_raw: &[u8],
|
tc_raw: &[u8],
|
||||||
) -> Result<(), Self::Error> {
|
) -> Result<(), Self::Error> {
|
||||||
self.send_packet(sender_id, tc_raw)
|
self.handle_packet(sender_id, tc_raw)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -494,10 +494,10 @@ pub(crate) mod tests {
|
|||||||
|
|
||||||
pub(crate) fn send_with_sender<SendError>(
|
pub(crate) fn send_with_sender<SendError>(
|
||||||
sender_id: ComponentId,
|
sender_id: ComponentId,
|
||||||
packet_sender: &(impl PacketSenderRaw<Error = SendError> + ?Sized),
|
packet_sender: &(impl PacketHandler<Error = SendError> + ?Sized),
|
||||||
packet: &[u8],
|
packet: &[u8],
|
||||||
) -> Result<(), SendError> {
|
) -> Result<(), SendError> {
|
||||||
packet_sender.send_packet(sender_id, packet)
|
packet_sender.handle_packet(sender_id, packet)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ pub enum AcsMode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, TryFromPrimitive)]
|
#[derive(Debug, TryFromPrimitive)]
|
||||||
#[repr(u64)]
|
#[repr(u32)]
|
||||||
pub enum TestComponentId {
|
pub enum TestComponentId {
|
||||||
MagnetometerDevice0 = 1,
|
MagnetometerDevice0 = 1,
|
||||||
MagnetometerDevice1 = 2,
|
MagnetometerDevice1 = 2,
|
||||||
@@ -299,7 +299,7 @@ struct AcsSubsystem {
|
|||||||
|
|
||||||
impl AcsSubsystem {
|
impl AcsSubsystem {
|
||||||
pub fn id() -> ComponentId {
|
pub fn id() -> ComponentId {
|
||||||
TestComponentId::AcsSubsystem as u64
|
TestComponentId::AcsSubsystem as ComponentId
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new(mode_node: ModeRequestorAndHandlerMpscBounded) -> Self {
|
pub fn new(mode_node: ModeRequestorAndHandlerMpscBounded) -> Self {
|
||||||
@@ -518,7 +518,7 @@ struct MgmAssembly {
|
|||||||
|
|
||||||
impl MgmAssembly {
|
impl MgmAssembly {
|
||||||
pub fn id() -> ComponentId {
|
pub fn id() -> ComponentId {
|
||||||
TestComponentId::MagnetometerAssembly as u64
|
TestComponentId::MagnetometerAssembly as ComponentId
|
||||||
}
|
}
|
||||||
pub fn new(mode_node: ModeRequestorAndHandlerMpscBounded) -> Self {
|
pub fn new(mode_node: ModeRequestorAndHandlerMpscBounded) -> Self {
|
||||||
Self {
|
Self {
|
||||||
@@ -923,7 +923,7 @@ impl ModeRequestHandler for CommonDevice {
|
|||||||
mode_and_submode: ModeAndSubmode,
|
mode_and_submode: ModeAndSubmode,
|
||||||
forced: bool,
|
forced: bool,
|
||||||
) -> Result<(), ModeError> {
|
) -> Result<(), ModeError> {
|
||||||
if self.id() == TestComponentId::MagnetorquerDevice as u64 {
|
if self.id() == TestComponentId::MagnetorquerDevice as ComponentId {
|
||||||
println!("test");
|
println!("test");
|
||||||
}
|
}
|
||||||
self.mode_and_submode = mode_and_submode;
|
self.mode_and_submode = mode_and_submode;
|
||||||
@@ -996,7 +996,7 @@ pub struct AcsController {
|
|||||||
|
|
||||||
impl AcsController {
|
impl AcsController {
|
||||||
pub fn id() -> ComponentId {
|
pub fn id() -> ComponentId {
|
||||||
TestComponentId::AcsController as u64
|
TestComponentId::AcsController as ComponentId
|
||||||
}
|
}
|
||||||
pub fn new(mode_node: ModeRequestHandlerMpscBounded) -> Self {
|
pub fn new(mode_node: ModeRequestHandlerMpscBounded) -> Self {
|
||||||
Self {
|
Self {
|
||||||
@@ -1020,7 +1020,7 @@ impl AcsController {
|
|||||||
|
|
||||||
impl ModeNode for AcsController {
|
impl ModeNode for AcsController {
|
||||||
fn id(&self) -> ComponentId {
|
fn id(&self) -> ComponentId {
|
||||||
TestComponentId::AcsController as u64
|
TestComponentId::AcsController as ComponentId
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1185,22 +1185,22 @@ impl TreeTestbench {
|
|||||||
|
|
||||||
let mut mgm_dev_0 = CommonDevice::new(
|
let mut mgm_dev_0 = CommonDevice::new(
|
||||||
"MGM_0",
|
"MGM_0",
|
||||||
TestComponentId::MagnetometerDevice0 as u64,
|
TestComponentId::MagnetometerDevice0 as ComponentId,
|
||||||
mgm_dev_node_0,
|
mgm_dev_node_0,
|
||||||
);
|
);
|
||||||
let mut mgm_dev_1 = CommonDevice::new(
|
let mut mgm_dev_1 = CommonDevice::new(
|
||||||
"MGM_1",
|
"MGM_1",
|
||||||
TestComponentId::MagnetometerDevice1 as u64,
|
TestComponentId::MagnetometerDevice1 as ComponentId,
|
||||||
mgm_dev_node_1,
|
mgm_dev_node_1,
|
||||||
);
|
);
|
||||||
let mut mgt_dev = CommonDevice::new(
|
let mut mgt_dev = CommonDevice::new(
|
||||||
"MGT",
|
"MGT",
|
||||||
TestComponentId::MagnetorquerDevice as u64,
|
TestComponentId::MagnetorquerDevice as ComponentId,
|
||||||
mgt_dev_node,
|
mgt_dev_node,
|
||||||
);
|
);
|
||||||
let mut mgt_manager = DeviceManager::new(
|
let mut mgt_manager = DeviceManager::new(
|
||||||
"MGT_MANAGER",
|
"MGT_MANAGER",
|
||||||
TestComponentId::MgtDevManager as u64,
|
TestComponentId::MgtDevManager as ComponentId,
|
||||||
mgt_dev_mgmt_node,
|
mgt_dev_mgmt_node,
|
||||||
);
|
);
|
||||||
let mut mgm_assy = MgmAssembly::new(mgm_assy_node);
|
let mut mgm_assy = MgmAssembly::new(mgm_assy_node);
|
||||||
@@ -1212,38 +1212,38 @@ impl TreeTestbench {
|
|||||||
let mut target_table_safe = TargetTablesMapValue::new("SAFE_TARGET_TBL", None);
|
let mut target_table_safe = TargetTablesMapValue::new("SAFE_TARGET_TBL", None);
|
||||||
target_table_safe.add_entry(TargetTableEntry::new(
|
target_table_safe.add_entry(TargetTableEntry::new(
|
||||||
"CTRL_SAFE",
|
"CTRL_SAFE",
|
||||||
TestComponentId::AcsController as u64,
|
TestComponentId::AcsController as ComponentId,
|
||||||
ModeAndSubmode::new(AcsMode::SAFE as u32, 0),
|
ModeAndSubmode::new(AcsMode::SAFE as u32, 0),
|
||||||
// All submodes allowed.
|
// All submodes allowed.
|
||||||
Some(0xffff),
|
Some(0xffff),
|
||||||
));
|
));
|
||||||
target_table_safe.add_entry(TargetTableEntry::new_with_precise_submode(
|
target_table_safe.add_entry(TargetTableEntry::new_with_precise_submode(
|
||||||
"MGM_A_NML",
|
"MGM_A_NML",
|
||||||
TestComponentId::MagnetometerAssembly as u64,
|
TestComponentId::MagnetometerAssembly as ComponentId,
|
||||||
ModeAndSubmode::new(DefaultMode::NORMAL as u32, 0),
|
ModeAndSubmode::new(DefaultMode::NORMAL as u32, 0),
|
||||||
));
|
));
|
||||||
target_table_safe.add_entry(TargetTableEntry::new_with_precise_submode(
|
target_table_safe.add_entry(TargetTableEntry::new_with_precise_submode(
|
||||||
"MGT_MAN_NML",
|
"MGT_MAN_NML",
|
||||||
TestComponentId::MgtDevManager as u64,
|
TestComponentId::MgtDevManager as ComponentId,
|
||||||
ModeAndSubmode::new(DefaultMode::NORMAL as u32, 0),
|
ModeAndSubmode::new(DefaultMode::NORMAL as u32, 0),
|
||||||
));
|
));
|
||||||
let mut sequence_tbl_safe_0 = SequenceTableMapTable::new("SAFE_SEQ_0_TBL");
|
let mut sequence_tbl_safe_0 = SequenceTableMapTable::new("SAFE_SEQ_0_TBL");
|
||||||
sequence_tbl_safe_0.add_entry(SequenceTableEntry::new(
|
sequence_tbl_safe_0.add_entry(SequenceTableEntry::new(
|
||||||
"SAFE_SEQ_0_MGM_A",
|
"SAFE_SEQ_0_MGM_A",
|
||||||
TestComponentId::MagnetometerAssembly as u64,
|
TestComponentId::MagnetometerAssembly as ComponentId,
|
||||||
ModeAndSubmode::new(DefaultMode::NORMAL as Mode, 0),
|
ModeAndSubmode::new(DefaultMode::NORMAL as Mode, 0),
|
||||||
false,
|
false,
|
||||||
));
|
));
|
||||||
sequence_tbl_safe_0.add_entry(SequenceTableEntry::new(
|
sequence_tbl_safe_0.add_entry(SequenceTableEntry::new(
|
||||||
"SAFE_SEQ_0_MGT_MAN",
|
"SAFE_SEQ_0_MGT_MAN",
|
||||||
TestComponentId::MgtDevManager as u64,
|
TestComponentId::MgtDevManager as ComponentId,
|
||||||
ModeAndSubmode::new(DefaultMode::NORMAL as Mode, 0),
|
ModeAndSubmode::new(DefaultMode::NORMAL as Mode, 0),
|
||||||
false,
|
false,
|
||||||
));
|
));
|
||||||
let mut sequence_tbl_safe_1 = SequenceTableMapTable::new("SAFE_SEQ_1_TBL");
|
let mut sequence_tbl_safe_1 = SequenceTableMapTable::new("SAFE_SEQ_1_TBL");
|
||||||
sequence_tbl_safe_1.add_entry(SequenceTableEntry::new(
|
sequence_tbl_safe_1.add_entry(SequenceTableEntry::new(
|
||||||
"SAFE_SEQ_1_ACS_CTRL",
|
"SAFE_SEQ_1_ACS_CTRL",
|
||||||
TestComponentId::AcsController as u64,
|
TestComponentId::AcsController as ComponentId,
|
||||||
ModeAndSubmode::new(AcsMode::SAFE as Mode, 0),
|
ModeAndSubmode::new(AcsMode::SAFE as Mode, 0),
|
||||||
false,
|
false,
|
||||||
));
|
));
|
||||||
@@ -1408,7 +1408,7 @@ fn announce_recursively() {
|
|||||||
fn generic_mode_reply_checker(
|
fn generic_mode_reply_checker(
|
||||||
reply_meta: MessageMetadata,
|
reply_meta: MessageMetadata,
|
||||||
mode_and_submode: ModeAndSubmode,
|
mode_and_submode: ModeAndSubmode,
|
||||||
expected_modes: &mut HashMap<u64, ModeAndSubmode>,
|
expected_modes: &mut HashMap<ComponentId, ModeAndSubmode>,
|
||||||
) {
|
) {
|
||||||
let id = TestComponentId::try_from(reply_meta.sender_id()).expect("invalid sender id");
|
let id = TestComponentId::try_from(reply_meta.sender_id()).expect("invalid sender id");
|
||||||
if !expected_modes.contains_key(&reply_meta.sender_id()) {
|
if !expected_modes.contains_key(&reply_meta.sender_id()) {
|
||||||
@@ -1528,15 +1528,15 @@ fn command_safe_mode() {
|
|||||||
);
|
);
|
||||||
let mut expected_modes = HashMap::new();
|
let mut expected_modes = HashMap::new();
|
||||||
expected_modes.insert(
|
expected_modes.insert(
|
||||||
TestComponentId::AcsController as u64,
|
TestComponentId::AcsController as ComponentId,
|
||||||
ModeAndSubmode::new(AcsMode::SAFE as u32, 0),
|
ModeAndSubmode::new(AcsMode::SAFE as u32, 0),
|
||||||
);
|
);
|
||||||
expected_modes.insert(
|
expected_modes.insert(
|
||||||
TestComponentId::MagnetometerAssembly as u64,
|
TestComponentId::MagnetometerAssembly as ComponentId,
|
||||||
ModeAndSubmode::new(DefaultMode::NORMAL as u32, 0),
|
ModeAndSubmode::new(DefaultMode::NORMAL as u32, 0),
|
||||||
);
|
);
|
||||||
expected_modes.insert(
|
expected_modes.insert(
|
||||||
TestComponentId::MgtDevManager as u64,
|
TestComponentId::MgtDevManager as ComponentId,
|
||||||
ModeAndSubmode::new(DefaultMode::NORMAL as u32, 0),
|
ModeAndSubmode::new(DefaultMode::NORMAL as u32, 0),
|
||||||
);
|
);
|
||||||
while let Some(reply) = tb.subsystem.mode_reply_mock.mode_reply_messages.pop_front() {
|
while let Some(reply) = tb.subsystem.mode_reply_mock.mode_reply_messages.pop_front() {
|
||||||
@@ -1558,11 +1558,11 @@ fn command_safe_mode() {
|
|||||||
);
|
);
|
||||||
let mut expected_modes = HashMap::new();
|
let mut expected_modes = HashMap::new();
|
||||||
expected_modes.insert(
|
expected_modes.insert(
|
||||||
TestComponentId::MagnetometerDevice0 as u64,
|
TestComponentId::MagnetometerDevice0 as ComponentId,
|
||||||
ModeAndSubmode::new(DefaultMode::NORMAL as u32, 0),
|
ModeAndSubmode::new(DefaultMode::NORMAL as u32, 0),
|
||||||
);
|
);
|
||||||
expected_modes.insert(
|
expected_modes.insert(
|
||||||
TestComponentId::MagnetometerDevice1 as u64,
|
TestComponentId::MagnetometerDevice1 as ComponentId,
|
||||||
ModeAndSubmode::new(DefaultMode::NORMAL as u32, 0),
|
ModeAndSubmode::new(DefaultMode::NORMAL as u32, 0),
|
||||||
);
|
);
|
||||||
while let Some(reply) = tb.mgm_assy.mode_reply_mock.mode_reply_messages.pop_front() {
|
while let Some(reply) = tb.mgm_assy.mode_reply_mock.mode_reply_messages.pop_front() {
|
||||||
@@ -1578,7 +1578,7 @@ fn command_safe_mode() {
|
|||||||
);
|
);
|
||||||
let mut expected_modes = HashMap::new();
|
let mut expected_modes = HashMap::new();
|
||||||
expected_modes.insert(
|
expected_modes.insert(
|
||||||
TestComponentId::MagnetorquerDevice as u64,
|
TestComponentId::MagnetorquerDevice as ComponentId,
|
||||||
ModeAndSubmode::new(DefaultMode::NORMAL as u32, 0),
|
ModeAndSubmode::new(DefaultMode::NORMAL as u32, 0),
|
||||||
);
|
);
|
||||||
let reply = tb
|
let reply = tb
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use arbitrary_int::u11;
|
use arbitrary_int::{u11, u21};
|
||||||
use satrs::event_man_legacy::{
|
use satrs::event_man_legacy::{
|
||||||
EventManagerWithMpsc, EventMessage, EventMessageU32, EventRoutingError, EventSendProvider,
|
EventManagerWithMpsc, EventMessage, EventMessageU32, EventRoutingError, EventSendProvider,
|
||||||
EventU32SenderMpsc,
|
EventU32SenderMpsc,
|
||||||
@@ -18,7 +18,7 @@ const INFO_EVENT: EventU32TypedSev<SeverityInfo> = EventU32TypedSev::<SeverityIn
|
|||||||
const LOW_SEV_EVENT: EventU32 = EventU32::new(Severity::Low, 1, 5);
|
const LOW_SEV_EVENT: EventU32 = EventU32::new(Severity::Low, 1, 5);
|
||||||
const EMPTY_STAMP: [u8; 7] = [0; 7];
|
const EMPTY_STAMP: [u8; 7] = [0; 7];
|
||||||
const TEST_APID: u11 = u11::new(0x02);
|
const TEST_APID: u11 = u11::new(0x02);
|
||||||
const TEST_ID: UniqueApidTargetId = UniqueApidTargetId::new(TEST_APID, 0x05);
|
const TEST_ID: UniqueApidTargetId = UniqueApidTargetId::new(TEST_APID, u21::new(0x05));
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum CustomTmSenderError {
|
pub enum CustomTmSenderError {
|
||||||
|
|||||||
@@ -29,9 +29,12 @@ use satrs::{
|
|||||||
ccsds::{SpValidity, SpacePacketValidator},
|
ccsds::{SpValidity, SpacePacketValidator},
|
||||||
cobs::encode_packet_with_cobs,
|
cobs::encode_packet_with_cobs,
|
||||||
},
|
},
|
||||||
hal::std::tcp_server::{
|
hal::std::{
|
||||||
ConnectionResult, HandledConnectionHandler, HandledConnectionInfo, ServerConfig,
|
tcp_server::{
|
||||||
TcpSpacepacketsServer, TcpTmtcInCobsServer,
|
CobsTcParser, ConnectionResult, HandledConnectionHandler, HandledConnectionInfo,
|
||||||
|
ServerConfig, TcpSpacepacketsServer, TcpTmtcInCobsServer,
|
||||||
|
},
|
||||||
|
tcp_spacepackets_server::CcsdsPacketParser,
|
||||||
},
|
},
|
||||||
tmtc::PacketSource,
|
tmtc::PacketSource,
|
||||||
};
|
};
|
||||||
@@ -121,7 +124,7 @@ fn test_cobs_server() {
|
|||||||
1024,
|
1024,
|
||||||
),
|
),
|
||||||
tm_source,
|
tm_source,
|
||||||
tc_sender.clone(),
|
CobsTcParser::new(TCP_SERVER_ID, 1024, tc_sender.clone()),
|
||||||
ConnectionFinishedHandler::default(),
|
ConnectionFinishedHandler::default(),
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
@@ -233,8 +236,7 @@ fn test_ccsds_server() {
|
|||||||
1024,
|
1024,
|
||||||
),
|
),
|
||||||
tm_source,
|
tm_source,
|
||||||
tc_sender,
|
CcsdsPacketParser::new(TCP_SERVER_ID, 1024, tc_sender, packet_id_lookup),
|
||||||
packet_id_lookup,
|
|
||||||
ConnectionFinishedHandler::default(),
|
ConnectionFinishedHandler::default(),
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user