2023-09-16 21:28:22 +02:00
|
|
|
//! Generic TCP TMTC servers with different TMTC format flavours.
|
2023-09-15 15:37:57 +02:00
|
|
|
use alloc::vec;
|
2023-09-15 19:15:26 +02:00
|
|
|
use alloc::{boxed::Box, vec::Vec};
|
2023-09-17 01:32:18 +02:00
|
|
|
use socket2::{Domain, Socket, Type};
|
2023-09-15 19:15:26 +02:00
|
|
|
use std::net::SocketAddr;
|
2023-09-17 01:32:18 +02:00
|
|
|
use std::net::TcpListener;
|
2023-09-15 19:15:26 +02:00
|
|
|
|
|
|
|
use crate::tmtc::{ReceivesTc, TmPacketSource};
|
2023-09-15 18:34:05 +02:00
|
|
|
use thiserror::Error;
|
2023-09-15 15:37:57 +02:00
|
|
|
|
2023-09-15 19:15:26 +02:00
|
|
|
// Re-export the TMTC in COBS server.
|
2023-09-16 21:28:22 +02:00
|
|
|
pub use crate::hal::std::tcp_with_cobs_server::{
|
2023-09-15 19:22:12 +02:00
|
|
|
parse_buffer_for_cobs_encoded_packets, TcpTmtcInCobsServer,
|
|
|
|
};
|
2023-09-15 18:34:05 +02:00
|
|
|
|
|
|
|
#[derive(Error, Debug)]
|
2023-09-16 16:23:42 +02:00
|
|
|
pub enum TcpTmtcError<TmError, TcError> {
|
2023-09-15 18:34:05 +02:00
|
|
|
#[error("TM retrieval error: {0}")]
|
|
|
|
TmError(TmError),
|
|
|
|
#[error("TC retrieval error: {0}")]
|
|
|
|
TcError(TcError),
|
|
|
|
#[error("io error: {0}")]
|
|
|
|
Io(#[from] std::io::Error),
|
2023-09-15 15:37:57 +02:00
|
|
|
}
|
|
|
|
|
2023-09-15 19:15:26 +02:00
|
|
|
/// Result of one connection attempt. Contains the client address if a connection was established,
|
|
|
|
/// in addition to the number of telecommands and telemetry packets exchanged.
|
|
|
|
#[derive(Debug, Default)]
|
|
|
|
pub struct ConnectionResult {
|
|
|
|
pub addr: Option<SocketAddr>,
|
|
|
|
pub num_received_tcs: u32,
|
|
|
|
pub num_sent_tms: u32,
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) struct TcpTmtcServerBase<TcError, TmError> {
|
2023-09-15 19:22:12 +02:00
|
|
|
pub(crate) listener: TcpListener,
|
2023-09-16 16:23:42 +02:00
|
|
|
pub(crate) tm_source: Box<dyn TmPacketSource<Error = TmError> + Send>,
|
2023-09-15 19:22:12 +02:00
|
|
|
pub(crate) tm_buffer: Vec<u8>,
|
2023-09-16 16:23:42 +02:00
|
|
|
pub(crate) tc_receiver: Box<dyn ReceivesTc<Error = TcError> + Send>,
|
2023-09-15 19:22:12 +02:00
|
|
|
pub(crate) tc_buffer: Vec<u8>,
|
2023-09-15 19:15:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<TcError, TmError> TcpTmtcServerBase<TcError, TmError> {
|
2023-09-17 01:32:18 +02:00
|
|
|
pub(crate) fn new(
|
|
|
|
addr: &SocketAddr,
|
|
|
|
reuse_addr: bool,
|
|
|
|
reuse_port: bool,
|
2023-09-15 18:34:05 +02:00
|
|
|
tm_buffer_size: usize,
|
2023-09-16 16:23:42 +02:00
|
|
|
tm_source: Box<dyn TmPacketSource<Error = TmError> + Send>,
|
2023-09-15 18:34:05 +02:00
|
|
|
tc_buffer_size: usize,
|
2023-09-16 16:23:42 +02:00
|
|
|
tc_receiver: Box<dyn ReceivesTc<Error = TcError> + Send>,
|
2023-09-15 15:37:57 +02:00
|
|
|
) -> Result<Self, std::io::Error> {
|
2023-09-17 01:32:18 +02:00
|
|
|
// Create a TCP listener bound to two addresses.
|
|
|
|
let socket = Socket::new(Domain::IPV4, Type::STREAM, None)?;
|
|
|
|
socket.set_reuse_address(reuse_addr)?;
|
|
|
|
socket.set_reuse_port(reuse_port)?;
|
|
|
|
let addr = (*addr).into();
|
|
|
|
socket.bind(&addr)?;
|
|
|
|
socket.listen(128)?;
|
2023-09-15 18:34:05 +02:00
|
|
|
Ok(Self {
|
2023-09-17 01:32:18 +02:00
|
|
|
listener: socket.into(),
|
2023-09-15 18:34:05 +02:00
|
|
|
tm_source,
|
|
|
|
tm_buffer: vec![0; tm_buffer_size],
|
2023-09-15 15:37:57 +02:00
|
|
|
tc_receiver,
|
2023-09-15 18:34:05 +02:00
|
|
|
tc_buffer: vec![0; tc_buffer_size],
|
2023-09-15 15:37:57 +02:00
|
|
|
})
|
|
|
|
}
|
2023-09-16 22:19:48 +02:00
|
|
|
|
2023-09-17 01:32:18 +02:00
|
|
|
pub(crate) fn listener(&mut self) -> &mut TcpListener {
|
|
|
|
&mut self.listener
|
|
|
|
}
|
|
|
|
|
2023-09-16 22:19:48 +02:00
|
|
|
pub(crate) fn local_addr(&self) -> std::io::Result<SocketAddr> {
|
2023-09-16 21:51:06 +02:00
|
|
|
self.listener.local_addr()
|
|
|
|
}
|
2023-09-14 23:51:17 +02:00
|
|
|
}
|