From c52e8d69e983c2ae02554841e35670078569b66d Mon Sep 17 00:00:00 2001 From: Ummon Date: Sat, 1 Nov 2014 18:39:08 +0100 Subject: [PATCH] Put the structures 'Server' and 'Client' in the same module called 'end_point'. --- src/end_point.rs | 160 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 160 insertions(+) create mode 100644 src/end_point.rs diff --git a/src/end_point.rs b/src/end_point.rs new file mode 100644 index 0000000..9488d13 --- /dev/null +++ b/src/end_point.rs @@ -0,0 +1,160 @@ +use std::io::{ Acceptor, Listener, TcpStream, IoResult, IoError, EndOfFile }; +use std::io::net::tcp::{ TcpAcceptor, TcpListener }; +use packet; +use packet::{ Packet, Command, Answer, Error, ReadingResult, PacketType }; + +pub struct Server { + acceptor: TcpAcceptor +} + +pub struct Client { + end_point: EndPoint, +} + +struct EndPoint { + socket: TcpStream, + current_timestamp: u64 +} + +impl Server { + pub fn new(port: u16) -> IoResult { + let mut acceptor = try!(TcpListener::bind("127.0.0.1", port).listen()); + + let server = Server { + acceptor: acceptor.clone() + }; + + spawn(proc() { + loop { + for stream in acceptor.incoming() { + match stream { + Err(_) => return, + Ok(stream) => spawn(proc() { + Server::handle_client(EndPoint { socket: stream, current_timestamp: 0 }); + }) + } + } + } + }); + + Ok(server) + } + + pub fn close(&mut self) -> IoResult<()> { + self.acceptor.close_accept() + } + + fn handle_client(mut end_point: EndPoint) { + loop { + match end_point.read() { + Ok(packet@Packet { t: Command(..), .. }) => { + println!("[Server] Valid command received: {}", packet); + let answer = Answer(Packet::random_packet_data()); + match end_point.send(answer.clone()) { + Ok(_) => + println!("[Server] Answer sent: {}", answer), + Err(e) => + println!("[Server] Can't send the answer. Error: {}", e) + } + }, + // Socket has been closed. + Err(packet::IOReadError(IoError { kind: EndOfFile, .. })) => { + println!("[Server] Connection closed: EOF"); + return + }, + other => + println!("[Server] Error or invalid packet: {}", other) + } + } + } +} + +impl Client { + pub fn new(address: &str, port: u16) -> IoResult { + Ok(Client { end_point: EndPoint { + socket: try!(TcpStream::connect(address, port)), + current_timestamp: 0 + }}) + } + + pub fn close(&mut self) -> IoResult<()> { + self.end_point.close() + } + + pub fn send(&mut self, packet: PacketType) { + match packet { + Command(_) => { + println!("[Client] Sending: {}", packet); + match self.end_point.send_with_result(packet) { + Ok(Ok(packet@Packet { t: Answer(..), .. })) => + println!("[Client] Command transmitted correctly, answer: {}", packet), + Ok(Ok(packet)) => + println!("[Client] Command transmitted correctly, wrong answer: {}", packet), + Ok(Err(e)) => + println!("[Client] Answer error: {}", e), + Err(e) => + println!("[Client] Can't send the packet. Error: {}", e) + } + }, + other => + println!("[Client] Cannot send this type of packet: {}", other) + } + } +} + +impl EndPoint { + fn close(&mut self) -> IoResult<()> { + try!(self.socket.close_read()); + try!(self.socket.close_write()); + Ok(()) + } + + /** + * Send a packet and wait synchronously an answer. + */ + fn send_with_result(&mut self, p: PacketType) -> IoResult { + match self.send(p) { + Err(e) => Err(e), + _ => Ok(self.read()) + } + } + + fn send(&mut self, p: PacketType) -> IoResult<()> { + self.current_timestamp += 1; + match (Packet { t: p, timestamp: self.current_timestamp }).write(&mut self.socket) { + Ok(_) => Ok(()), + Err(packet::WriteIOError(e)) => Err(e) + } + } + + fn read(&mut self) -> ReadingResult { + fn send_error(ep: &mut EndPoint, error_type: packet::ErrorType) { + match ep.send(Error(error_type)) { + Err(e) => println!("Unable to send error packet: {}", e), + Ok(_) => () + }; + }; + + match Packet::read(&mut self.socket) { + Ok(packet) => { + if packet.timestamp <= self.current_timestamp { + println!("Error, timestamp mismatch, current timestamp: {}, packet received: {}", self.current_timestamp, packet); + Err(packet::InvalidTimestamp) + } else { + self.current_timestamp = packet.timestamp + 1; + Ok(packet) + } + }, + e @ Err(packet::PaddingError) => { + send_error(self, packet::CryptError); + e + }, + e @ Err(packet::MACMismatchError) => { + send_error(self, packet::AuthError); + e + }, + other => + other + } + } +} \ No newline at end of file -- 2.45.2