Put the structures 'Server' and 'Client' in the same module called 'end_point'.
authorUmmon <greg.burri@gmail.com>
Sat, 1 Nov 2014 17:39:08 +0000 (18:39 +0100)
committerUmmon <greg.burri@gmail.com>
Sat, 1 Nov 2014 17:39:08 +0000 (18:39 +0100)
src/end_point.rs [new file with mode: 0644]

diff --git a/src/end_point.rs b/src/end_point.rs
new file mode 100644 (file)
index 0000000..9488d13
--- /dev/null
@@ -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<Server> {
+      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<Client> {
+      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<ReadingResult> {
+      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