2023-09-29 14:11:03 +02:00
|
|
|
use std::{
|
2024-04-04 15:18:53 +02:00
|
|
|
collections::{HashSet, VecDeque},
|
2024-04-16 11:04:22 +02:00
|
|
|
fmt::Debug,
|
|
|
|
marker::PhantomData,
|
2023-09-29 14:11:03 +02:00
|
|
|
sync::{Arc, Mutex},
|
|
|
|
};
|
|
|
|
|
|
|
|
use log::{info, warn};
|
2024-02-12 15:51:37 +01:00
|
|
|
use satrs::{
|
2024-04-16 11:04:22 +02:00
|
|
|
encoding::ccsds::{SpValidity, SpacePacketValidator},
|
2024-04-10 11:28:16 +02:00
|
|
|
hal::std::tcp_server::{HandledConnectionHandler, ServerConfig, TcpSpacepacketsServer},
|
2024-04-16 11:04:22 +02:00
|
|
|
spacepackets::{CcsdsPacket, PacketId},
|
|
|
|
tmtc::{PacketSenderRaw, PacketSource},
|
2023-09-29 14:11:03 +02:00
|
|
|
};
|
|
|
|
|
2024-04-10 11:28:16 +02:00
|
|
|
#[derive(Default)]
|
|
|
|
pub struct ConnectionFinishedHandler {}
|
|
|
|
|
2024-04-16 11:04:22 +02:00
|
|
|
pub struct SimplePacketValidator {
|
|
|
|
pub valid_ids: HashSet<PacketId>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl SpacePacketValidator for SimplePacketValidator {
|
|
|
|
fn validate(
|
|
|
|
&self,
|
|
|
|
sp_header: &satrs::spacepackets::SpHeader,
|
|
|
|
_raw_buf: &[u8],
|
|
|
|
) -> satrs::encoding::ccsds::SpValidity {
|
|
|
|
if self.valid_ids.contains(&sp_header.packet_id()) {
|
|
|
|
return SpValidity::Valid;
|
|
|
|
}
|
|
|
|
log::warn!("ignoring space packet with header {:?}", sp_header);
|
|
|
|
// We could perform a CRC check.. but lets keep this simple and assume that TCP ensures
|
|
|
|
// data integrity.
|
|
|
|
SpValidity::Skip
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-04-10 11:28:16 +02:00
|
|
|
impl HandledConnectionHandler for ConnectionFinishedHandler {
|
|
|
|
fn handled_connection(&mut self, info: satrs::hal::std::tcp_server::HandledConnectionInfo) {
|
|
|
|
info!(
|
|
|
|
"Served {} TMs and {} TCs for client {:?}",
|
|
|
|
info.num_sent_tms, info.num_received_tcs, info.addr
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-09-29 14:11:03 +02:00
|
|
|
#[derive(Default, Clone)]
|
|
|
|
pub struct SyncTcpTmSource {
|
|
|
|
tm_queue: Arc<Mutex<VecDeque<Vec<u8>>>>,
|
|
|
|
max_packets_stored: usize,
|
|
|
|
pub silent_packet_overwrite: bool,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl SyncTcpTmSource {
|
|
|
|
pub fn new(max_packets_stored: usize) -> Self {
|
|
|
|
Self {
|
|
|
|
tm_queue: Arc::default(),
|
|
|
|
max_packets_stored,
|
|
|
|
silent_packet_overwrite: true,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn add_tm(&mut self, tm: &[u8]) {
|
|
|
|
let mut tm_queue = self.tm_queue.lock().expect("locking tm queue failec");
|
|
|
|
if tm_queue.len() > self.max_packets_stored {
|
|
|
|
if !self.silent_packet_overwrite {
|
|
|
|
warn!("TPC TM source is full, deleting oldest packet");
|
|
|
|
}
|
|
|
|
tm_queue.pop_front();
|
|
|
|
}
|
|
|
|
tm_queue.push_back(tm.to_vec());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-04-16 11:04:22 +02:00
|
|
|
impl PacketSource for SyncTcpTmSource {
|
2023-09-29 14:11:03 +02:00
|
|
|
type Error = ();
|
|
|
|
|
|
|
|
fn retrieve_packet(&mut self, buffer: &mut [u8]) -> Result<usize, Self::Error> {
|
|
|
|
let mut tm_queue = self.tm_queue.lock().expect("locking tm queue failed");
|
|
|
|
if !tm_queue.is_empty() {
|
|
|
|
let next_vec = tm_queue.front().unwrap();
|
|
|
|
if buffer.len() < next_vec.len() {
|
|
|
|
panic!(
|
|
|
|
"provided buffer too small, must be at least {} bytes",
|
|
|
|
next_vec.len()
|
|
|
|
);
|
|
|
|
}
|
|
|
|
let next_vec = tm_queue.pop_front().unwrap();
|
|
|
|
buffer[0..next_vec.len()].copy_from_slice(&next_vec);
|
|
|
|
if next_vec.len() > 9 {
|
|
|
|
let service = next_vec[7];
|
|
|
|
let subservice = next_vec[8];
|
|
|
|
info!("Sending PUS TM[{service},{subservice}]")
|
|
|
|
} else {
|
|
|
|
info!("Sending PUS TM");
|
|
|
|
}
|
|
|
|
return Ok(next_vec.len());
|
|
|
|
}
|
|
|
|
Ok(0)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-04-16 11:04:22 +02:00
|
|
|
pub type TcpServer<ReceivesTc, SendError> = TcpSpacepacketsServer<
|
2024-03-04 16:26:34 +01:00
|
|
|
SyncTcpTmSource,
|
2024-04-16 11:04:22 +02:00
|
|
|
ReceivesTc,
|
|
|
|
SimplePacketValidator,
|
2024-04-10 11:28:16 +02:00
|
|
|
ConnectionFinishedHandler,
|
|
|
|
(),
|
2024-04-16 11:04:22 +02:00
|
|
|
SendError,
|
2024-03-04 16:26:34 +01:00
|
|
|
>;
|
|
|
|
|
2024-04-16 11:04:22 +02:00
|
|
|
pub struct TcpTask<TcSender: PacketSenderRaw<Error = SendError>, SendError: Debug + 'static>(
|
|
|
|
pub TcpServer<TcSender, SendError>,
|
|
|
|
PhantomData<SendError>,
|
|
|
|
);
|
2023-09-29 14:11:03 +02:00
|
|
|
|
2024-04-16 11:04:22 +02:00
|
|
|
impl<TcSender: PacketSenderRaw<Error = SendError>, SendError: Debug + 'static>
|
|
|
|
TcpTask<TcSender, SendError>
|
2024-03-04 16:26:34 +01:00
|
|
|
{
|
2023-09-29 14:11:03 +02:00
|
|
|
pub fn new(
|
|
|
|
cfg: ServerConfig,
|
|
|
|
tm_source: SyncTcpTmSource,
|
2024-04-16 11:04:22 +02:00
|
|
|
tc_sender: TcSender,
|
|
|
|
valid_ids: HashSet<PacketId>,
|
2023-09-29 14:11:03 +02:00
|
|
|
) -> Result<Self, std::io::Error> {
|
2024-04-16 11:04:22 +02:00
|
|
|
Ok(Self(
|
|
|
|
TcpSpacepacketsServer::new(
|
2024-04-09 17:21:43 +02:00
|
|
|
cfg,
|
|
|
|
tm_source,
|
2024-04-16 11:04:22 +02:00
|
|
|
tc_sender,
|
|
|
|
SimplePacketValidator { valid_ids },
|
2024-04-10 11:28:16 +02:00
|
|
|
ConnectionFinishedHandler::default(),
|
2024-04-09 17:21:43 +02:00
|
|
|
None,
|
|
|
|
)?,
|
2024-04-16 11:04:22 +02:00
|
|
|
PhantomData,
|
|
|
|
))
|
2023-09-29 14:11:03 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn periodic_operation(&mut self) {
|
|
|
|
loop {
|
2024-04-16 11:04:22 +02:00
|
|
|
let result = self.0.handle_all_connections(None);
|
2023-09-29 14:11:03 +02:00
|
|
|
match result {
|
2024-04-10 11:28:16 +02:00
|
|
|
Ok(_conn_result) => (),
|
2023-09-29 14:11:03 +02:00
|
|
|
Err(e) => {
|
|
|
|
warn!("TCP server error: {e:?}");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|