|
|
@ -1,10 +1,25 @@
|
|
|
|
|
|
|
|
//! UDP server helper components
|
|
|
|
use crate::tmtc::ReceivesTc;
|
|
|
|
use crate::tmtc::ReceivesTc;
|
|
|
|
use std::boxed::Box;
|
|
|
|
use std::boxed::Box;
|
|
|
|
use std::io::ErrorKind;
|
|
|
|
use std::io::{Error, ErrorKind};
|
|
|
|
use std::net::{SocketAddr, ToSocketAddrs, UdpSocket};
|
|
|
|
use std::net::{SocketAddr, ToSocketAddrs, UdpSocket};
|
|
|
|
use std::vec;
|
|
|
|
use std::vec;
|
|
|
|
use std::vec::Vec;
|
|
|
|
use std::vec::Vec;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// This TC server helper can be used to receive raw PUS telecommands thorough a UDP interface.
|
|
|
|
|
|
|
|
///
|
|
|
|
|
|
|
|
/// 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
|
|
|
|
|
|
|
|
/// receiver in form of a special trait object which implements [ReceivesTc]. Please note that the
|
|
|
|
|
|
|
|
/// receiver should copy out the received data if it the data is required past the
|
|
|
|
|
|
|
|
/// [ReceivesTc::pass_tc] call.
|
|
|
|
|
|
|
|
///
|
|
|
|
|
|
|
|
/// # Examples
|
|
|
|
|
|
|
|
///
|
|
|
|
|
|
|
|
/// The [fsrc-example crate](https://egit.irs.uni-stuttgart.de/rust/fsrc-launchpad/src/branch/obsw-client-example/fsrc-example) server code includes
|
|
|
|
|
|
|
|
/// [example code](https://egit.irs.uni-stuttgart.de/rust/fsrc-launchpad/src/branch/obsw-client-example/fsrc-example/src/bin/obsw/tmtc.rs)
|
|
|
|
|
|
|
|
/// 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.
|
|
|
|
pub struct UdpTcServer<E> {
|
|
|
|
pub struct UdpTcServer<E> {
|
|
|
|
pub socket: UdpSocket,
|
|
|
|
pub socket: UdpSocket,
|
|
|
|
recv_buf: Vec<u8>,
|
|
|
|
recv_buf: Vec<u8>,
|
|
|
@ -15,26 +30,29 @@ pub struct UdpTcServer<E> {
|
|
|
|
#[derive(Debug)]
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub enum ReceiveResult<E> {
|
|
|
|
pub enum ReceiveResult<E> {
|
|
|
|
WouldBlock,
|
|
|
|
WouldBlock,
|
|
|
|
OtherIoError(std::io::Error),
|
|
|
|
IoError(Error),
|
|
|
|
ReceiverError(E),
|
|
|
|
ReceiverError(E),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl<E> From<Error> for ReceiveResult<E> {
|
|
|
|
|
|
|
|
fn from(e: Error) -> Self {
|
|
|
|
|
|
|
|
ReceiveResult::IoError(e)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl<E> UdpTcServer<E> {
|
|
|
|
impl<E> UdpTcServer<E> {
|
|
|
|
pub fn new<A: ToSocketAddrs>(
|
|
|
|
pub fn new<A: ToSocketAddrs>(
|
|
|
|
addr: A,
|
|
|
|
addr: A,
|
|
|
|
max_recv_size: usize,
|
|
|
|
max_recv_size: usize,
|
|
|
|
tc_receiver: Box<dyn ReceivesTc<Error = E>>,
|
|
|
|
tc_receiver: Box<dyn ReceivesTc<Error = E>>,
|
|
|
|
) -> Result<Self, std::io::Error> {
|
|
|
|
) -> Result<Self, Error> {
|
|
|
|
let server = Self {
|
|
|
|
let server = Self {
|
|
|
|
socket: UdpSocket::bind(addr)?,
|
|
|
|
socket: UdpSocket::bind(addr)?,
|
|
|
|
recv_buf: vec![0; max_recv_size],
|
|
|
|
recv_buf: vec![0; max_recv_size],
|
|
|
|
sender_addr: None,
|
|
|
|
sender_addr: None,
|
|
|
|
tc_receiver,
|
|
|
|
tc_receiver,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
server
|
|
|
|
server.socket.set_nonblocking(true)?;
|
|
|
|
.socket
|
|
|
|
|
|
|
|
.set_nonblocking(true)
|
|
|
|
|
|
|
|
.expect("Setting server non blocking failed");
|
|
|
|
|
|
|
|
Ok(server)
|
|
|
|
Ok(server)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -42,10 +60,10 @@ impl<E> UdpTcServer<E> {
|
|
|
|
let res = match self.socket.recv_from(&mut self.recv_buf) {
|
|
|
|
let res = match self.socket.recv_from(&mut self.recv_buf) {
|
|
|
|
Ok(res) => res,
|
|
|
|
Ok(res) => res,
|
|
|
|
Err(e) => {
|
|
|
|
Err(e) => {
|
|
|
|
return if e.kind() == ErrorKind::WouldBlock {
|
|
|
|
return if e.kind() == ErrorKind::WouldBlock || e.kind() == ErrorKind::TimedOut {
|
|
|
|
Err(ReceiveResult::WouldBlock)
|
|
|
|
Err(ReceiveResult::WouldBlock)
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
Err(ReceiveResult::OtherIoError(e))
|
|
|
|
Err(e.into())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
};
|
|
|
|