X-Git-Url: http://git.euphorik.ch/?p=crypto_lab1.git;a=blobdiff_plain;f=lab1_rust%2Fsrc%2Fend_point.rs;h=83967dac4640651ecce039c4ecc277da7d58ccfe;hp=2d0a66c9e09815cc76a7fffb2efa176ef43dbab8;hb=d7f0bb987b21e93a5798403d294f7905151682f7;hpb=ecdec5bf7022018eadf4a38b01890bbb3ab79c89 diff --git a/lab1_rust/src/end_point.rs b/lab1_rust/src/end_point.rs index 2d0a66c..83967da 100644 --- a/lab1_rust/src/end_point.rs +++ b/lab1_rust/src/end_point.rs @@ -1,14 +1,17 @@ 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 }; +use utils::from_elem; // Default timeout when waiting data on a stream (for instance: 'TcpStream::read'). static DEFAULT_TIMEOUT: Option = Some(500); // [ms]. pub struct Server { - acceptor: TcpAcceptor + acceptor: TcpAcceptor, } pub struct Client { @@ -17,29 +20,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 { - let mut acceptor = try!(TcpListener::bind(interface, port).listen()); + pub fn new(interface: &str, port: u16, variant: packet::Variant) -> IoResult { + 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 +57,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 { + pub fn new(address: &str, port: u16, variant: packet::Variant) -> IoResult { 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 +137,9 @@ impl Client { fn raw_packet(timestamp: u64) -> Vec { 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 +147,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 +156,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 +169,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 +186,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 @@ -185,9 +196,9 @@ impl Client { // 5) |client: &mut Client| -> bool { println!("Sending a packet with too small data..."); - let command = Command(Packet::new_packet_data(0, Vec::from_elem(6, 0x00))); + let command = Command(Packet::new_packet_data(0, 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 @@ -197,9 +208,9 @@ impl Client { // 6) |client: &mut Client| -> bool { println!("Sending a packet with too large data..."); - let command = Command(Packet::new_packet_data(0, Vec::from_elem(40, 0x00))); + let command = Command(Packet::new_packet_data(0, 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 +222,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 +239,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 +257,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 { match self.send(p) { Err(e) => Err(e), @@ -264,9 +281,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 { + /// 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 { self.socket.set_timeout(DEFAULT_TIMEOUT); match self.socket.write(p) { Err(e) => Err(e), @@ -277,39 +294,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 =>