//! A TCP-connection from a client to the server. use super::super::packet::{Packet, PacketRwError}; use super::connection_manager::ConnId; use serde::de::DeserializeOwned; use serde::Serialize; use std::fmt::Debug; use std::net::TcpStream; use std::sync::mpsc::Sender; use std::thread::{self, JoinHandle}; /// Holds a stream to the client and manages receiving packets from said client /// in an extra thread. pub struct Connection { stream: TcpStream, rcv_thread_handle: JoinHandle<()>, } impl Connection { /// Start up the receiving thread after a client connection has been detected. /// Will create a ghost disconnect packet in case the client disconnects. pub(super) fn start_rcv
( conn_id: ConnId, stream: TcpStream, packet_tx: Sender<(ConnId, Packet
)>, ) -> Self where P: 'static + Debug + Send + DeserializeOwned + Serialize, { let mut stream_cl = stream .try_clone() .expect("Unable to clone TcpStream handle"); let rcv_thread_handle = thread::spawn(move || { let mut running = true; while running { // Read the newest packet from the stream. let packet = match Packet::read_from_stream(&mut stream_cl) { Ok(packet) => dbg!(packet), Err(PacketRwError::Closed) => { // Stop the thread after this packet. running = false; /* Generate an internal disconnection packet, so the connection * manager can call cleanup code if necessary. */ Packet::Disconnect } Err(err) => { error!( "Receiving packet failed. Connection `{}`. {:?}", conn_id, err ); // Ignore the received data. continue; } }; /* Try sending the packet to the Connection manager. If it has already * stopped and hung up on the channel, stop this receive thread as well. */ if packet_tx.send((conn_id, packet)).is_err() { info!("Shutting down connection `{}`", conn_id); running = false; } } info!("Packet receive thread has stopped running."); }); Self { stream, rcv_thread_handle, } } /// Send a packet to the client via TCP. pub(super) fn send
(&mut self, packet: &Packet
) -> Result<(), PacketRwError> where P: 'static + Debug + Send + DeserializeOwned + Serialize, { packet.write_to_stream(&mut self.stream) } }