Fix to the new nightly.
[crypto_lab1.git] / lab1_rust / src / end_point.rs
index 2d0a66c..d2cedcb 100644 (file)
@@ -1,14 +1,16 @@
 use std::io;
 use std::io::{ MemWriter, Acceptor, Listener, TcpStream, IoResult, IoError, EndOfFile };
 use std::io::net::tcp::{ TcpAcceptor, TcpListener };
+use std::thread::Thread;
 use packet;
-use packet::{ Packet, Command, Answer, Error, ReadingResult, PacketType };
+use packet::{ Packet, ReadingResult, PacketType };
+use packet::PacketType::{ Command, Answer, Error };
 
 // Default timeout when waiting data on a stream (for instance: 'TcpStream::read').
 static DEFAULT_TIMEOUT: Option<u64> = Some(500); // [ms].
 
 pub struct Server {
-   acceptor: TcpAcceptor
+   acceptor: TcpAcceptor,
 }
 
 pub struct Client {
@@ -17,29 +19,31 @@ pub struct Client {
 
 pub struct EndPoint {
    socket: TcpStream,
-   current_timestamp: u64
+   current_timestamp: u64,
+   variant: packet::Variant,
 }
 
 impl Server {
-   pub fn new(interface: &str, port: u16) -> IoResult<Server> {
-      let mut acceptor = try!(TcpListener::bind(interface, port).listen());
+   pub fn new(interface: &str, port: u16, variant: packet::Variant) -> IoResult<Server> {
+      let mut acceptor = try!(TcpListener::bind((interface, port)).listen());
 
       let server = Server {
          acceptor: acceptor.clone()
       };
 
-      spawn(proc() {
+      Thread::spawn(move || {
          loop {
             for stream in acceptor.incoming() {
                match stream {
-                  Ok(stream) => spawn(proc() {
-                     Server::handle_client(EndPoint::new(stream));
-                  }),
+                  Ok(stream) =>
+                     Thread::spawn(move || {
+                        Server::handle_client(EndPoint::new(stream, variant));
+                     }).detach(),
                   _ => return
                }
             }
          }
-      });
+      }).detach();
 
       Ok(server)
    }
@@ -52,64 +56,76 @@ impl Server {
       loop {
          match end_point.read() {
             Ok(packet@Packet { t: Command(..), .. }) => {
-               println!("[Server] Valid command received: {}", packet);
-               let answer = Answer(Packet::random_packet_data([]));
+               end_point.print("Server",  format!("Valid command received: {}", packet));
+               let answer = Answer(Packet::random_packet_data(&[]));
                match end_point.send(answer.clone()) {
                   Ok(_) =>
-                     println!("[Server] Answer sent: {}", answer),
+                     end_point.print("Server", format!("Answer sent: {}", answer)),
                   Err(e) =>
-                     println!("[Server] Can't send the answer. Error: {}", e)
+                     end_point.print("Server", format!("Can't send the answer. Error: {}", e))
                }
             },
             // Socket has been closed.
-            Err(packet::IOReadError(IoError { kind: EndOfFile, .. })) => {
-               println!("[Server] Connection closed: EOF");
+            Err(packet::ReadingError::IO(IoError { kind: EndOfFile, .. })) => {
+               end_point.print("Server", format!("Connection closed: EOF"));
                return
             },
             other =>
-               println!("[Server] Error or invalid packet: {}", other)
+               end_point.print("Server", format!("Error or invalid packet: {}", other))
          }
       }
    }
 }
 
 impl Client {
-   pub fn new(address: &str, port: u16) -> IoResult<Client> {
+   pub fn new(address: &str, port: u16, variant: packet::Variant) -> IoResult<Client> {
       Ok(Client { end_point: EndPoint {
-         socket: try!(TcpStream::connect(address, port)),
-         current_timestamp: 0
+         socket: try!(TcpStream::connect((address, port))),
+         current_timestamp: 0,
+         variant: variant,
       }})
    }
 
+   #[allow(dead_code)]
    pub fn close(&mut self) -> IoResult<()> {
       self.end_point.close()
    }
 
-   pub fn send(&mut self, packet: PacketType) {
+   pub fn send(&mut self, packet: PacketType) -> bool {
       match packet {
          Command(_) => {
-            println!("[Client] Sending: {}", packet);
+            self.end_point.print("Client", format!("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)
+               Ok(Ok(packet@Packet { t: Answer(..), .. })) => {
+                  self.end_point.print("Client", format!("Command transmitted correctly, answer: {}", packet));
+                  true
+               },
+               Ok(Ok(packet)) => {
+                  self.end_point.print("Client", format!("Command transmitted correctly, wrong answer: {}", packet));
+                  false
+               }
+               Ok(Err(e)) => {
+                  self.end_point.print("Client", format!("Answer error: {}", e));
+                  false
+               }
+               Err(e) => {
+                  self.end_point.print("Client", format!("Can't send the packet. Error: {}", e));
+                  false
+               }
             }
          },
-         other =>
-            println!("[Client] Cannot send this type of packet: {}", other)
+         other => {
+            self.end_point.print("Client", format!("Cannot send this type of packet: {}", other));
+            false
+         }
       }
    }
 
-   /// Send some valid and not-valid packets to the server and check the result.
+   /// Sends some valid and not-valid packets to the server and check the result.
    /// For each test a new client is created.
-   pub fn start_tests(address: &str, port: u16) {
+   pub fn start_tests(address: &str, port: u16, variant: packet::Variant) {
       let execute = |f: &mut |&mut Client| -> bool| -> bool {
-         match Client::new(address, port) {
+         match Client::new(address, port, variant) {
             Ok(ref mut client) => (*f)(client),
             Err(e) => {
                println!("Unable to create a client. Error: {}", e);
@@ -120,9 +136,9 @@ impl Client {
 
       fn raw_packet(timestamp: u64) -> Vec<u8> {
          let mut m = MemWriter::new();
-         match (Packet { t: Command(Packet::random_packet_data([42])), timestamp: timestamp }).write(&mut m) {
+         match (Packet { t: Command(Packet::random_packet_data(&[42])), timestamp: timestamp }).write(&mut m, packet::Variant::Weak) {
             Err(_) => vec!(),
-            _ => m.unwrap()
+            _ => m.into_inner()
          }
       }
 
@@ -130,13 +146,7 @@ impl Client {
          // 1)
          |client: &mut Client| -> bool {
             println!("Sending a valid packet...");
-            match client.end_point.send_with_result(Command(Packet::random_packet_data([42]))) {
-               Ok(Ok(Packet { t: Answer(..), .. })) => true,
-               other => {
-                  println!("Error: {}", other);
-                  false
-               }
-            }
+            client.send(Command(Packet::random_packet_data(&[42])))
          },
          // 2)
          |client: &mut Client| -> bool {
@@ -145,7 +155,7 @@ impl Client {
             let mut raw_packet = raw_packet(client.end_point.current_timestamp);
             raw_packet[2] = 0xEE; // Alter the type.
             match client.end_point.send_raw_with_result(raw_packet.as_slice()) {
-               Ok(Err(packet::IOReadError( IoError { kind: io::TimedOut, .. }))) => true, // OK: the server should not send any packet.
+               Ok(Err(packet::ReadingError::IO( IoError { kind: io::TimedOut, .. }))) => true, // OK: the server should not send any packet.
                other => {
                   println!("Error: {}", other);
                   false
@@ -158,7 +168,7 @@ impl Client {
             client.end_point.current_timestamp += 1;
             let raw_packet = raw_packet(0);
             match client.end_point.send_raw_with_result(raw_packet.as_slice()) {
-               Ok(Err(packet::IOReadError( IoError { kind: io::TimedOut, .. }))) => true, // OK: the server should not send any packet.
+               Ok(Err(packet::ReadingError::IO( IoError { kind: io::TimedOut, .. }))) => true, // OK: the server should not send any packet.
                other => {
                   println!("Error: {}", other);
                   false
@@ -175,7 +185,7 @@ impl Client {
             raw_packet[13] = 0xBE;
             raw_packet[14] = 0xEF;
             match client.end_point.send_raw_with_result(raw_packet.as_slice()) {
-               Ok(Ok(Packet { t: Error(packet::AuthError), .. })) => true,
+               Ok(Ok(Packet { t: Error(packet::ErrorType::Auth), .. })) => true,
                other => {
                   println!("Error: {}", other);
                   false
@@ -187,7 +197,7 @@ impl Client {
             println!("Sending a packet with too small data...");
             let command = Command(Packet::new_packet_data(0, Vec::from_elem(6, 0x00)));
             match client.end_point.send_with_result(command) {
-               Ok(Err(packet::IOReadError( IoError { kind: io::TimedOut, .. }))) => true, // OK: the server should not send any packet.
+               Ok(Err(packet::ReadingError::IO( IoError { kind: io::TimedOut, .. }))) => true, // OK: the server should not send any packet.
                other => {
                   println!("Error: {}", other);
                   false
@@ -199,7 +209,7 @@ impl Client {
             println!("Sending a packet with too large data...");
             let command = Command(Packet::new_packet_data(0, Vec::from_elem(40, 0x00)));
             match client.end_point.send_with_result(command) {
-               Ok(Err(packet::IOReadError( IoError { kind: io::TimedOut, .. }))) => true, // OK: the server should not send any packet.
+               Ok(Err(packet::ReadingError::IO( IoError { kind: io::TimedOut, .. }))) => true, // OK: the server should not send any packet.
                other => {
                   println!("Error: {}", other);
                   false
@@ -211,13 +221,13 @@ impl Client {
             println!("Sending a packet with wrong padding (all 0)...");
             client.end_point.current_timestamp += 1;
             let mut m = MemWriter::new();
-            let raw_packet = match (Packet { t: Command(Packet::random_packet_data([42])), timestamp: client.end_point.current_timestamp }).write_with_padding_fun(&mut m, |_, _| -> u8 { 0 }) {
+            let raw_packet = match (Packet { t: Command(Packet::random_packet_data(&[42])), timestamp: client.end_point.current_timestamp }).write_with_padding_fun(&mut m, packet::Variant::Weak, |_, _| -> u8 { 0 }) {
                Err(_) => vec!(),
-               _ => m.unwrap()
+               _ => m.into_inner()
             };
 
             match client.end_point.send_raw_with_result(raw_packet.as_slice()) {
-               Ok(Ok(Packet { t: Error(packet::CryptError), .. })) => true,
+               Ok(Ok(Packet { t: Error(packet::ErrorType::Crypt), .. })) => true,
                other => {
                   println!("Error: {}", other);
                   false
@@ -228,7 +238,7 @@ impl Client {
 
       let mut nb_test_passed = 0;
       for (i, test) in range(1, tests.len()+1).zip(tests.iter_mut()) {
-         println!("===== Test case #{}:", i)
+         println!("===== Test case #{}:", i);
          if execute(test) {
             nb_test_passed += 1;
             println!("===== Test passed");
@@ -246,17 +256,23 @@ impl Client {
 }
 
 impl EndPoint {
-   pub fn new(socket: TcpStream) -> EndPoint {
-      EndPoint { socket: socket, current_timestamp: 0 }
+   pub fn new(mut socket: TcpStream, variant: packet::Variant) -> EndPoint {
+      let _ = socket.set_nodelay(true);
+      EndPoint { socket: socket, current_timestamp: 0 , variant: variant}
    }
 
+   #[allow(dead_code)]
    fn close(&mut self) -> IoResult<()> {
       try!(self.socket.close_read());
       try!(self.socket.close_write());
       Ok(())
    }
 
-   /// Send a packet and wait for an answer synchronously.
+   fn print(&self, prefix: &str, s: String) {
+      println!("[{}] time: {}. {}", prefix, self.current_timestamp, s);
+   }
+
+   /// Sends a packet and wait for an answer synchronously.
    fn send_with_result(&mut self, p: PacketType) -> IoResult<ReadingResult> {
       match self.send(p) {
          Err(e) => Err(e),
@@ -264,9 +280,9 @@ impl EndPoint {
       }
    }
 
-   /// Send arbitrary data and wait for an answer synchronously.
-   /// Do not increment the current timestamp.
-   fn send_raw_with_result(&mut self, p: &[u8]) -> IoResult<ReadingResult> {
+   /// Sends arbitrary data and wait for an answer synchronously.
+   /// Doesn't increment the current timestamp.
+   pub fn send_raw_with_result(&mut self, p: &[u8]) -> IoResult<ReadingResult> {
       self.socket.set_timeout(DEFAULT_TIMEOUT);
       match self.socket.write(p) {
          Err(e) => Err(e),
@@ -277,39 +293,38 @@ impl EndPoint {
    fn send(&mut self, p: PacketType) -> IoResult<()> {
       self.socket.set_timeout(DEFAULT_TIMEOUT);
       self.current_timestamp += 1;
-      match (Packet { t: p, timestamp: self.current_timestamp }).write(&mut self.socket) {
-         Err(packet::WriteIOError(e)) => Err(e),
+      match (Packet { t: p, timestamp: self.current_timestamp }).write(&mut self.socket, self.variant) {
+         Err(packet::WritingError::IO(e)) => Err(e),
          _ => Ok(())
       }
    }
 
    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(_) => ()
-         };
+         if let Err(e) = ep.send(Error(error_type)) {
+            println!("Unable to send error packet: {}", e)
+         }
       };
 
       self.socket.set_timeout(DEFAULT_TIMEOUT);
-      match Packet::read(&mut self.socket) {
+      match Packet::read(&mut self.socket, self.variant) {
          Ok(packet) => {
             if packet.timestamp <= self.current_timestamp {
                println!("Error, timestamp mismatch, current timestamp: {}, packet received: {}", self.current_timestamp, packet);
-               Err(packet::InvalidTimestampError)
+               Err(packet::ReadingError::InvalidTimestamp)
             } else {
                self.current_timestamp = packet.timestamp + 1;
                Ok(packet)
             }
          },
-         e @ Err(packet::PaddingError) => {
+         e @ Err(packet::ReadingError::Padding) => {
             self.current_timestamp += 1;
-            send_error(self, packet::CryptError);
+            send_error(self, packet::ErrorType::Crypt);
             e
          },
-         e @ Err(packet::MACMismatchError) => {
+         e @ Err(packet::ReadingError::MACMismatch) => {
             self.current_timestamp += 1;
-            send_error(self, packet::AuthError);
+            send_error(self, packet::ErrorType::Auth);
             e
          },
          other =>