use crate::packet::{Packet, PacketReceiver}; use std::{ io::{self, Read, Write}, net::{Shutdown, SocketAddr, TcpListener, TcpStream, ToSocketAddrs}, sync::{ atomic::{AtomicBool, Ordering}, mpsc::{channel, Receiver, Sender}, Arc, Mutex, }, thread, }; /// Used to send [Packet] to the sending thread. type ConnectionSender = Arc)>>>; /// A TCP [Connection] that can send and receive [Packet]. pub struct Connection { /// Whether or not the [Connection] is currently connected. connected: Arc, /// Used to store the received [Packet]s. packets: Arc, /// Used to send [Packet] to the sending thread. sender: ConnectionSender, /// The [TcpStream] of the [Connection]. stream: TcpStream, /// The address of the [Connection]. address: SocketAddr, } impl Connection { /// Creates a new [Connection] with the given [TcpStream]. pub fn new(stream: TcpStream) -> io::Result { let connected = Arc::new(AtomicBool::new(true)); let packets = Arc::new(PacketReceiver::new()); // Receiving part let mut thread_stream = stream.try_clone()?; let thread_packets = Arc::clone(&packets); let thread_connected = Arc::clone(&connected); thread::spawn(move || { let mut int_buffer = [0; 4]; loop { // Check if the connection is closed if !thread_connected.load(Ordering::Relaxed) { return; } // Read the length of the packet if thread_stream.read_exact(&mut int_buffer).is_err() { break; } let len = u32::from_be_bytes(int_buffer); // Read the packet identifier if thread_stream.read_exact(&mut int_buffer).is_err() { break; } let id = u32::from_be_bytes(int_buffer); // Read the packet let mut buffer = vec![0; len as usize]; if thread_stream.read_exact(&mut buffer).is_err() { break; } // Insert the packet thread_packets.insert(id, buffer); } // Close the connection thread_connected.store(false, Ordering::Relaxed); }); // Sending part let mut thread_stream = stream.try_clone()?; let (sender, receiver) = channel(); let thread_connected = Arc::clone(&connected); thread::spawn(move || { loop { // Check if the connection is closed if !thread_connected.load(Ordering::Relaxed) { return; } // Get the data to send let (id, buffer): (u32, Vec) = match receiver.recv() { Ok(data) => data, Err(_) => break, }; // Send the length of the data let len = buffer.len() as u32; if thread_stream.write_all(&len.to_be_bytes()).is_err() { break; } // Send the packet identifier if thread_stream.write_all(&id.to_be_bytes()).is_err() { break; } // Send the data if thread_stream.write_all(&buffer).is_err() { break; } // Flush the stream if thread_stream.flush().is_err() { break; } } // Close the connection thread_connected.store(false, Ordering::Relaxed); }); Ok(Self { connected, packets, sender: Arc::new(Mutex::new(sender)), address: stream.peer_addr()?, stream, }) } /// Creates a [Connection] to the given address. pub fn connect(address: A) -> io::Result { Self::new(TcpStream::connect(address)?) } /// Returns whether or not the [Connection] is currently connected. pub fn connected(&self) -> bool { self.connected.load(Ordering::Relaxed) } /// Clears the [Packet] cache. pub fn clear(&self) { self.packets.clear(); } /// Gets all the received [Packet]s of a certain type. pub fn recv(&self) -> Vec

{ self.packets.extract() } /// Sends the given [Packet] to the [Connection]. /// Does nothing if the [Connection] is closed. pub fn send(&self, packet: P) { let data = bincode::serialize(&packet).expect("Failed to serialize packet"); self.sender .lock() .map(|sender| sender.send((P::ID, data))) .ok(); } /// Returns the address of the [Connection]. pub fn address(&self) -> SocketAddr { self.address } } impl Drop for Connection { fn drop(&mut self) { self.connected.store(false, Ordering::Relaxed); self.stream.shutdown(Shutdown::Both).ok(); } } /// A TCP [Listener] that can accept [Connection]s. pub struct Listener { /// Whether the [Listener] is listening. listening: Arc, /// The receiving part of the [Listener]. receiver: Arc>>, /// The address the [Listener] is bound to. address: SocketAddr, } impl Listener { /// Creates a new [Listener] binded to the given address. pub fn bind(address: A) -> io::Result { let listener = TcpListener::bind(address)?; let address = listener.local_addr()?; let listening = Arc::new(AtomicBool::new(true)); let listening_thread = Arc::clone(&listening); let (sender, receiver) = channel(); thread::spawn(move || { for stream in listener.incoming() { let connection = match stream { Ok(stream) => match Connection::new(stream) { Ok(connection) => connection, Err(_) => break, }, Err(_) => break, }; if sender.send(connection).is_err() { break; } } listening_thread.store(false, Ordering::Relaxed); }); Ok(Self { listening, receiver: Arc::new(Mutex::new(receiver)), address, }) } /// Returns whether or not the [Listener] is listening. pub fn listening(&self) -> bool { self.listening.load(Ordering::Relaxed) } /// Receives the next [Connection] from the [Listener]. pub fn accept(&self) -> Option { self.receiver .lock() .ok() .and_then(|receiver| receiver.try_recv().ok()) } /// Returns the address the [Listener] is bound to. pub fn address(&self) -> SocketAddr { self.address } }