sat-rs/satrs/src/hal/std/tcp_cobs_server.rs

495 lines
19 KiB
Rust
Raw Normal View History

2024-04-09 17:21:43 +02:00
use alloc::sync::Arc;
2023-09-15 19:15:26 +02:00
use alloc::vec;
use cobs::encode;
2024-04-09 17:21:43 +02:00
use core::sync::atomic::AtomicBool;
2024-04-10 11:28:16 +02:00
use core::time::Duration;
2023-09-18 00:11:01 +02:00
use delegate::delegate;
2024-04-10 11:28:16 +02:00
use mio::net::{TcpListener, TcpStream};
2023-09-15 19:15:26 +02:00
use std::io::Write;
2023-09-16 22:19:48 +02:00
use std::net::SocketAddr;
2023-09-15 19:15:26 +02:00
use std::vec::Vec;
2023-09-20 15:18:20 +02:00
use crate::encoding::parse_buffer_for_cobs_encoded_packets;
2024-04-16 11:04:22 +02:00
use crate::tmtc::PacketSenderRaw;
use crate::tmtc::PacketSource;
2023-09-15 19:15:26 +02:00
2023-09-18 00:18:01 +02:00
use crate::hal::std::tcp_server::{
2023-09-18 00:45:13 +02:00
ConnectionResult, ServerConfig, TcpTcParser, TcpTmSender, TcpTmtcError, TcpTmtcGenericServer,
2023-09-18 00:18:01 +02:00
};
2024-04-16 11:04:22 +02:00
use crate::ComponentId;
2023-09-18 00:11:01 +02:00
2024-04-10 11:28:16 +02:00
use super::tcp_server::HandledConnectionHandler;
use super::tcp_server::HandledConnectionInfo;
/// Concrete [TcpTcParser] implementation for the [TcpTmtcInCobsServer].
2023-09-18 00:11:01 +02:00
#[derive(Default)]
2023-09-18 00:45:13 +02:00
pub struct CobsTcParser {}
2023-09-18 00:11:01 +02:00
impl<TmError, TcError: 'static> TcpTcParser<TmError, TcError> for CobsTcParser {
2023-09-18 00:11:01 +02:00
fn handle_tc_parsing(
&mut self,
tc_buffer: &mut [u8],
2024-04-16 11:04:22 +02:00
sender_id: ComponentId,
tc_sender: &(impl PacketSenderRaw<Error = TcError> + ?Sized),
2024-04-10 11:28:16 +02:00
conn_result: &mut HandledConnectionInfo,
2023-09-18 00:11:01 +02:00
current_write_idx: usize,
next_write_idx: &mut usize,
) -> Result<(), TcpTmtcError<TmError, TcError>> {
conn_result.num_received_tcs += parse_buffer_for_cobs_encoded_packets(
&mut tc_buffer[..current_write_idx],
2024-04-16 11:04:22 +02:00
sender_id,
tc_sender,
2023-09-18 00:11:01 +02:00
next_write_idx,
)
.map_err(|e| TcpTmtcError::TcError(e))?;
Ok(())
}
}
/// Concrete [TcpTmSender] implementation for the [TcpTmtcInCobsServer].
2023-09-18 00:45:13 +02:00
pub struct CobsTmSender {
2023-09-15 19:15:26 +02:00
tm_encoding_buffer: Vec<u8>,
}
2023-09-18 00:45:13 +02:00
impl CobsTmSender {
2023-09-18 00:11:01 +02:00
fn new(tm_buffer_size: usize) -> Self {
Self {
// The buffer should be large enough to hold the maximum expected TM size encoded with
// COBS.
tm_encoding_buffer: vec![0; cobs::max_encoding_length(tm_buffer_size)],
}
}
}
2023-09-18 00:45:13 +02:00
impl<TmError, TcError> TcpTmSender<TmError, TcError> for CobsTmSender {
2023-09-18 00:11:01 +02:00
fn handle_tm_sending(
&mut self,
tm_buffer: &mut [u8],
2024-04-16 11:04:22 +02:00
tm_source: &mut (impl PacketSource<Error = TmError> + ?Sized),
2024-04-10 11:28:16 +02:00
conn_result: &mut HandledConnectionInfo,
2023-09-18 00:11:01 +02:00
stream: &mut TcpStream,
) -> Result<bool, TcpTmtcError<TmError, TcError>> {
let mut tm_was_sent = false;
loop {
// Write TM until TM source is exhausted. For now, there is no limit for the amount
// 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 {
return Ok(tm_was_sent);
}
tm_was_sent = true;
conn_result.num_sent_tms += 1;
// Encode into COBS and sent to client.
let mut current_idx = 0;
self.tm_encoding_buffer[current_idx] = 0;
current_idx += 1;
current_idx += encode(
&tm_buffer[..read_tm_len],
&mut self.tm_encoding_buffer[current_idx..],
);
self.tm_encoding_buffer[current_idx] = 0;
current_idx += 1;
stream.write_all(&self.tm_encoding_buffer[..current_idx])?;
}
}
}
/// TCP TMTC server implementation for exchange of generic TMTC packets which are framed with the
/// [COBS protocol](https://en.wikipedia.org/wiki/Consistent_Overhead_Byte_Stuffing).
///
2023-09-18 00:45:13 +02:00
/// Telemetry will be encoded with the COBS protocol using [cobs::encode] in addition to being
/// wrapped with the sentinel value 0 as the packet delimiter as well before being sent back to
/// the client. Please note that the server will send as much data as it can retrieve from the
2024-04-16 11:04:22 +02:00
/// [PacketSource] in its current implementation.
2023-09-18 00:11:01 +02:00
///
/// 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
/// packets even from a data stream which is split up. The server wil use the
/// [parse_buffer_for_cobs_encoded_packets] function to parse for packets and pass them to a
2023-09-20 15:22:37 +02:00
/// generic TC receiver. The user can use [crate::encoding::encode_packet_with_cobs] to encode
/// telecommands sent to the server.
2023-09-20 11:45:27 +02:00
///
/// ## Example
///
2024-02-23 14:19:30 +01:00
/// The [TCP integration tests](https://egit.irs.uni-stuttgart.de/rust/sat-rs/src/branch/main/satrs/tests/tcp_servers.rs)
2023-09-20 15:04:46 +02:00
/// test also serves as the example application for this module.
2023-10-01 14:32:15 +02:00
pub struct TcpTmtcInCobsServer<
2024-04-16 11:04:22 +02:00
TmSource: PacketSource<Error = TmError>,
TcSender: PacketSenderRaw<Error = SendError>,
2024-04-10 11:28:16 +02:00
HandledConnection: HandledConnectionHandler,
TmError,
2024-04-16 11:04:22 +02:00
SendError: 'static,
2023-10-01 14:32:15 +02:00
> {
2024-04-10 11:28:16 +02:00
pub generic_server: TcpTmtcGenericServer<
TmSource,
2024-04-16 11:04:22 +02:00
TcSender,
2024-04-10 11:28:16 +02:00
CobsTmSender,
CobsTcParser,
HandledConnection,
TmError,
2024-04-16 11:04:22 +02:00
SendError,
2024-04-10 11:28:16 +02:00
>,
2023-09-18 00:11:01 +02:00
}
2023-10-01 14:32:15 +02:00
impl<
2024-04-16 11:04:22 +02:00
TmSource: PacketSource<Error = TmError>,
TcReceiver: PacketSenderRaw<Error = TcError>,
2024-04-10 11:28:16 +02:00
HandledConnection: HandledConnectionHandler,
TmError: 'static,
TcError: 'static,
> TcpTmtcInCobsServer<TmSource, TcReceiver, HandledConnection, TmError, TcError>
2023-10-01 14:32:15 +02:00
{
2023-09-18 00:45:13 +02:00
/// Create a new TCP TMTC server which exchanges TMTC packets encoded with
/// [COBS protocol](https://en.wikipedia.org/wiki/Consistent_Overhead_Byte_Stuffing).
///
/// ## Parameter
///
/// * `cfg` - Configuration of the server.
/// * `tm_source` - Generic TM source used by the server to pull telemetry packets which are
/// then sent back to the client.
/// * `tc_receiver` - Any received telecommands which were decoded successfully will be
/// forwarded to this TC receiver.
2023-09-18 00:11:01 +02:00
pub fn new(
cfg: ServerConfig,
2023-10-01 14:32:15 +02:00
tm_source: TmSource,
tc_receiver: TcReceiver,
2024-04-10 11:28:16 +02:00
handled_connection: HandledConnection,
2024-04-09 17:21:43 +02:00
stop_signal: Option<Arc<AtomicBool>>,
2023-09-29 14:11:03 +02:00
) -> Result<Self, std::io::Error> {
2023-09-18 00:11:01 +02:00
Ok(Self {
generic_server: TcpTmtcGenericServer::new(
cfg,
CobsTcParser::default(),
2023-09-18 00:45:13 +02:00
CobsTmSender::new(cfg.tm_buffer_size),
2023-09-18 00:11:01 +02:00
tm_source,
tc_receiver,
2024-04-10 11:28:16 +02:00
handled_connection,
2024-04-09 17:21:43 +02:00
stop_signal,
2023-09-18 00:11:01 +02:00
)?,
})
2023-09-17 02:31:02 +02:00
}
2023-09-18 00:11:01 +02:00
delegate! {
to self.generic_server {
pub fn listener(&mut self) -> &mut TcpListener;
2023-09-17 02:31:02 +02:00
2023-09-18 00:11:01 +02:00
/// Can be used to retrieve the local assigned address of the TCP server. This is especially
/// useful if using the port number 0 for OS auto-assignment.
pub fn local_addr(&self) -> std::io::Result<SocketAddr>;
2023-09-15 19:15:26 +02:00
2024-04-16 11:04:22 +02:00
/// Delegation to the [TcpTmtcGenericServer::handle_all_connections] call.
pub fn handle_all_connections(
2023-09-18 00:11:01 +02:00
&mut self,
2024-04-10 11:28:16 +02:00
poll_duration: Option<Duration>,
2023-09-18 00:11:01 +02:00
) -> Result<ConnectionResult, TcpTmtcError<TmError, TcError>>;
2023-09-15 19:15:26 +02:00
}
}
}
#[cfg(test)]
mod tests {
2023-09-16 16:23:42 +02:00
use core::{
sync::atomic::{AtomicBool, Ordering},
time::Duration,
};
use std::{
2023-09-16 21:24:01 +02:00
io::{Read, Write},
2023-09-16 16:23:42 +02:00
net::{IpAddr, Ipv4Addr, SocketAddr, TcpStream},
2024-04-16 11:04:22 +02:00
panic,
sync::mpsc,
thread,
2024-04-09 17:21:43 +02:00
time::Instant,
2023-09-16 16:23:42 +02:00
};
2023-09-18 16:08:35 +02:00
use crate::{
2023-09-20 15:18:20 +02:00
encoding::tests::{INVERTED_PACKET, SIMPLE_PACKET},
2023-09-26 12:51:11 +02:00
hal::std::tcp_server::{
2024-04-16 11:04:22 +02:00
tests::{ConnectionFinishedHandler, SyncTmSource},
2024-04-10 11:28:16 +02:00
ConnectionResult, ServerConfig,
2023-09-26 12:51:11 +02:00
},
2024-04-16 11:04:22 +02:00
queue::GenericSendError,
tmtc::PacketAsVec,
ComponentId,
2023-09-18 16:08:35 +02:00
};
2023-10-01 14:32:15 +02:00
use alloc::sync::Arc;
2023-09-15 19:15:26 +02:00
use cobs::encode;
2023-09-18 16:08:09 +02:00
use super::TcpTmtcInCobsServer;
2023-09-15 19:15:26 +02:00
2024-04-16 11:04:22 +02:00
const TCP_SERVER_ID: ComponentId = 0x05;
2023-09-15 19:15:26 +02:00
fn encode_simple_packet(encoded_buf: &mut [u8], current_idx: &mut usize) {
2023-09-20 14:57:11 +02:00
encode_packet(&SIMPLE_PACKET, encoded_buf, current_idx)
}
fn encode_inverted_packet(encoded_buf: &mut [u8], current_idx: &mut usize) {
encode_packet(&INVERTED_PACKET, encoded_buf, current_idx)
}
fn encode_packet(packet: &[u8], encoded_buf: &mut [u8], current_idx: &mut usize) {
2023-09-15 19:15:26 +02:00
encoded_buf[*current_idx] = 0;
*current_idx += 1;
2023-09-20 14:57:11 +02:00
*current_idx += encode(packet, &mut encoded_buf[*current_idx..]);
2023-09-15 19:15:26 +02:00
encoded_buf[*current_idx] = 0;
*current_idx += 1;
}
2023-09-16 21:24:01 +02:00
fn generic_tmtc_server(
addr: &SocketAddr,
2024-04-16 11:04:22 +02:00
tc_sender: mpsc::Sender<PacketAsVec>,
2023-09-16 21:24:01 +02:00
tm_source: SyncTmSource,
2024-04-09 17:21:43 +02:00
stop_signal: Option<Arc<AtomicBool>>,
2024-04-16 11:04:22 +02:00
) -> TcpTmtcInCobsServer<
SyncTmSource,
mpsc::Sender<PacketAsVec>,
ConnectionFinishedHandler,
(),
GenericSendError,
> {
2023-09-16 21:24:01 +02:00
TcpTmtcInCobsServer::new(
2024-04-16 11:04:22 +02:00
ServerConfig::new(TCP_SERVER_ID, *addr, Duration::from_millis(2), 1024, 1024),
2023-10-01 14:32:15 +02:00
tm_source,
2024-04-16 11:04:22 +02:00
tc_sender,
2024-04-10 11:28:16 +02:00
ConnectionFinishedHandler::default(),
2024-04-09 17:21:43 +02:00
stop_signal,
2023-09-16 16:23:42 +02:00
)
2023-09-16 21:24:01 +02:00
.expect("TCP server generation failed")
}
#[test]
fn test_server_basic_no_tm() {
2023-09-16 21:51:06 +02:00
let auto_port_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 0);
2024-04-16 11:04:22 +02:00
let (tc_sender, tc_receiver) = mpsc::channel();
2023-09-16 21:24:01 +02:00
let tm_source = SyncTmSource::default();
2024-04-09 17:21:43 +02:00
let mut tcp_server =
2024-04-16 11:04:22 +02:00
generic_tmtc_server(&auto_port_addr, tc_sender.clone(), tm_source, None);
2023-09-16 22:19:48 +02:00
let dest_addr = tcp_server
.local_addr()
.expect("retrieving dest addr failed");
2023-09-16 21:24:01 +02:00
let conn_handled: Arc<AtomicBool> = Default::default();
let set_if_done = conn_handled.clone();
// Call the connection handler in separate thread, does block.
thread::spawn(move || {
2024-04-16 11:04:22 +02:00
let result = tcp_server.handle_all_connections(Some(Duration::from_millis(100)));
2023-09-16 21:24:01 +02:00
if result.is_err() {
panic!("handling connection failed: {:?}", result.unwrap_err());
}
2024-04-10 11:28:16 +02:00
let result = result.unwrap();
assert_eq!(result, ConnectionResult::HandledConnections(1));
tcp_server
.generic_server
.finished_handler
.check_last_connection(0, 1);
tcp_server
.generic_server
.finished_handler
.check_no_connections_left();
2023-09-16 21:24:01 +02:00
set_if_done.store(true, Ordering::Relaxed);
});
// Send TC to server now.
let mut encoded_buf: [u8; 16] = [0; 16];
let mut current_idx = 0;
encode_simple_packet(&mut encoded_buf, &mut current_idx);
let mut stream = TcpStream::connect(dest_addr).expect("connecting to TCP server failed");
stream
.write_all(&encoded_buf[..current_idx])
.expect("writing to TCP server failed");
drop(stream);
// A certain amount of time is allowed for the transaction to complete.
for _ in 0..3 {
if !conn_handled.load(Ordering::Relaxed) {
thread::sleep(Duration::from_millis(5));
}
}
if !conn_handled.load(Ordering::Relaxed) {
panic!("connection was not handled properly");
}
// Check that the packet was received and decoded successfully.
2024-04-16 11:04:22 +02:00
let packet_with_sender = tc_receiver.recv().expect("receiving TC failed");
assert_eq!(packet_with_sender.packet, &SIMPLE_PACKET);
matches!(tc_receiver.try_recv(), Err(mpsc::TryRecvError::Empty));
2023-09-16 21:24:01 +02:00
}
#[test]
2023-09-20 14:57:11 +02:00
fn test_server_basic_multi_tm_multi_tc() {
2023-09-16 21:51:06 +02:00
let auto_port_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 0);
2024-04-16 11:04:22 +02:00
let (tc_sender, tc_receiver) = mpsc::channel();
2023-09-16 21:24:01 +02:00
let mut tm_source = SyncTmSource::default();
tm_source.add_tm(&INVERTED_PACKET);
2023-09-20 14:57:11 +02:00
tm_source.add_tm(&SIMPLE_PACKET);
2024-04-16 11:04:22 +02:00
let mut tcp_server =
generic_tmtc_server(&auto_port_addr, tc_sender.clone(), tm_source.clone(), None);
2023-09-16 22:19:48 +02:00
let dest_addr = tcp_server
.local_addr()
.expect("retrieving dest addr failed");
2023-09-16 16:23:42 +02:00
let conn_handled: Arc<AtomicBool> = Default::default();
let set_if_done = conn_handled.clone();
// Call the connection handler in separate thread, does block.
thread::spawn(move || {
2024-04-16 11:04:22 +02:00
let result = tcp_server.handle_all_connections(Some(Duration::from_millis(100)));
2023-09-16 16:23:42 +02:00
if result.is_err() {
panic!("handling connection failed: {:?}", result.unwrap_err());
}
2024-04-10 11:28:16 +02:00
let result = result.unwrap();
assert_eq!(result, ConnectionResult::HandledConnections(1));
tcp_server
.generic_server
.finished_handler
.check_last_connection(2, 2);
tcp_server
.generic_server
.finished_handler
.check_no_connections_left();
2023-09-16 16:23:42 +02:00
set_if_done.store(true, Ordering::Relaxed);
});
// Send TC to server now.
2023-09-20 14:57:11 +02:00
let mut encoded_buf: [u8; 32] = [0; 32];
2023-09-16 16:23:42 +02:00
let mut current_idx = 0;
encode_simple_packet(&mut encoded_buf, &mut current_idx);
2023-09-20 14:57:11 +02:00
encode_inverted_packet(&mut encoded_buf, &mut current_idx);
2023-09-16 16:23:42 +02:00
let mut stream = TcpStream::connect(dest_addr).expect("connecting to TCP server failed");
2023-09-20 14:57:11 +02:00
stream
.set_read_timeout(Some(Duration::from_millis(10)))
.expect("setting reas timeout failed");
2023-09-16 16:23:42 +02:00
stream
2023-09-16 21:24:01 +02:00
.write_all(&encoded_buf[..current_idx])
2023-09-16 16:23:42 +02:00
.expect("writing to TCP server failed");
2023-09-16 22:19:48 +02:00
// Done with writing.
stream
.shutdown(std::net::Shutdown::Write)
.expect("shutting down write failed");
2023-09-16 21:24:01 +02:00
let mut read_buf: [u8; 16] = [0; 16];
2023-09-20 14:57:11 +02:00
let mut read_len_total = 0;
// Timeout ensures this does not block forever.
while read_len_total < 16 {
let read_len = stream.read(&mut read_buf).expect("read failed");
read_len_total += read_len;
// Read until full expected size is available.
if read_len == 16 {
// Read first TM packet.
current_idx = 0;
assert_eq!(read_len, 16);
assert_eq!(read_buf[0], 0);
current_idx += 1;
let mut dec_report = cobs::decode_in_place_report(&mut read_buf[current_idx..])
.expect("COBS decoding failed");
assert_eq!(dec_report.dst_used, 5);
// Skip first sentinel byte.
assert_eq!(
&read_buf[current_idx..current_idx + INVERTED_PACKET.len()],
&INVERTED_PACKET
);
current_idx += dec_report.src_used;
// End sentinel.
assert_eq!(read_buf[current_idx], 0, "invalid sentinel end byte");
current_idx += 1;
2023-09-20 11:45:27 +02:00
2023-09-20 14:57:11 +02:00
// Read second TM packet.
assert_eq!(read_buf[current_idx], 0);
current_idx += 1;
dec_report = cobs::decode_in_place_report(&mut read_buf[current_idx..])
.expect("COBS decoding failed");
assert_eq!(dec_report.dst_used, 5);
// Skip first sentinel byte.
assert_eq!(
&read_buf[current_idx..current_idx + SIMPLE_PACKET.len()],
&SIMPLE_PACKET
);
current_idx += dec_report.src_used;
// End sentinel.
assert_eq!(read_buf[current_idx], 0);
break;
}
}
drop(stream);
2023-09-16 21:24:01 +02:00
2023-09-16 16:23:42 +02:00
// A certain amount of time is allowed for the transaction to complete.
for _ in 0..3 {
if !conn_handled.load(Ordering::Relaxed) {
2023-09-16 21:24:01 +02:00
thread::sleep(Duration::from_millis(5));
2023-09-16 16:23:42 +02:00
}
}
if !conn_handled.load(Ordering::Relaxed) {
panic!("connection was not handled properly");
}
2023-09-16 21:24:01 +02:00
// Check that the packet was received and decoded successfully.
2024-04-16 11:04:22 +02:00
let packet_with_sender = tc_receiver.recv().expect("receiving TC failed");
let packet = &packet_with_sender.packet;
assert_eq!(packet, &SIMPLE_PACKET);
let packet_with_sender = tc_receiver.recv().expect("receiving TC failed");
let packet = &packet_with_sender.packet;
assert_eq!(packet, &INVERTED_PACKET);
matches!(tc_receiver.try_recv(), Err(mpsc::TryRecvError::Empty));
2023-09-16 16:23:42 +02:00
}
2024-04-09 17:21:43 +02:00
2024-04-10 11:28:16 +02:00
#[test]
fn test_server_accept_timeout() {
let auto_port_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 0);
2024-04-16 11:04:22 +02:00
let (tc_sender, _tc_receiver) = mpsc::channel();
2024-04-10 11:28:16 +02:00
let tm_source = SyncTmSource::default();
let mut tcp_server =
2024-04-16 11:04:22 +02:00
generic_tmtc_server(&auto_port_addr, tc_sender.clone(), tm_source, None);
2024-04-10 11:28:16 +02:00
let start = Instant::now();
// Call the connection handler in separate thread, does block.
let thread_jh = thread::spawn(move || loop {
2024-04-16 11:04:22 +02:00
let result = tcp_server.handle_all_connections(Some(Duration::from_millis(20)));
2024-04-10 11:28:16 +02:00
if result.is_err() {
panic!("handling connection failed: {:?}", result.unwrap_err());
}
let result = result.unwrap();
if result == ConnectionResult::AcceptTimeout {
break;
}
if Instant::now() - start > Duration::from_millis(100) {
panic!("regular stop signal handling failed");
}
});
thread_jh.join().expect("thread join failed");
}
2024-04-09 17:21:43 +02:00
#[test]
fn test_server_stop_signal() {
let auto_port_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 0);
2024-04-16 11:04:22 +02:00
let (tc_sender, _tc_receiver) = mpsc::channel();
2024-04-09 17:21:43 +02:00
let tm_source = SyncTmSource::default();
let stop_signal = Arc::new(AtomicBool::new(false));
let mut tcp_server = generic_tmtc_server(
&auto_port_addr,
2024-04-16 11:04:22 +02:00
tc_sender.clone(),
2024-04-09 17:21:43 +02:00
tm_source,
Some(stop_signal.clone()),
);
2024-04-10 11:28:16 +02:00
let dest_addr = tcp_server
.local_addr()
.expect("retrieving dest addr failed");
let stop_signal_copy = stop_signal.clone();
2024-04-09 17:21:43 +02:00
let start = Instant::now();
// Call the connection handler in separate thread, does block.
2024-04-09 19:40:55 +02:00
let thread_jh = thread::spawn(move || loop {
2024-04-16 11:04:22 +02:00
let result = tcp_server.handle_all_connections(Some(Duration::from_millis(20)));
2024-04-09 17:21:43 +02:00
if result.is_err() {
panic!("handling connection failed: {:?}", result.unwrap_err());
}
2024-04-09 19:40:55 +02:00
let result = result.unwrap();
2024-04-10 11:28:16 +02:00
if result == ConnectionResult::AcceptTimeout {
panic!("unexpected accept timeout");
}
if stop_signal_copy.load(Ordering::Relaxed) {
2024-04-09 19:40:55 +02:00
break;
}
2024-04-10 11:28:16 +02:00
if Instant::now() - start > Duration::from_millis(100) {
2024-04-09 17:21:43 +02:00
panic!("regular stop signal handling failed");
}
});
2024-04-10 11:28:16 +02:00
// We connect but do not do anything.
let _stream = TcpStream::connect(dest_addr).expect("connecting to TCP server failed");
2024-04-09 17:21:43 +02:00
stop_signal.store(true, Ordering::Relaxed);
2024-04-10 11:28:16 +02:00
// No need to drop the connection, the stop signal should take take of everything.
thread_jh.join().expect("thread join failed");
2024-04-09 17:21:43 +02:00
}
2023-09-15 19:15:26 +02:00
}