X-Git-Url: http://git.euphorik.ch/?p=crypto_lab1.git;a=blobdiff_plain;f=src%2Fend_point.rs;fp=src%2Fend_point.rs;h=0000000000000000000000000000000000000000;hp=2d0a66c9e09815cc76a7fffb2efa176ef43dbab8;hb=ecdec5bf7022018eadf4a38b01890bbb3ab79c89;hpb=c9318a07ce0ec00f999ff17943b83048d536ecd1 diff --git a/src/end_point.rs b/src/end_point.rs deleted file mode 100644 index 2d0a66c..0000000 --- a/src/end_point.rs +++ /dev/null @@ -1,319 +0,0 @@ -use std::io; -use std::io::{ MemWriter, Acceptor, Listener, TcpStream, IoResult, IoError, EndOfFile }; -use std::io::net::tcp::{ TcpAcceptor, TcpListener }; -use packet; -use packet::{ Packet, Command, Answer, Error, ReadingResult, PacketType }; - -// Default timeout when waiting data on a stream (for instance: 'TcpStream::read'). -static DEFAULT_TIMEOUT: Option = Some(500); // [ms]. - -pub struct Server { - acceptor: TcpAcceptor -} - -pub struct Client { - end_point: EndPoint, -} - -pub struct EndPoint { - socket: TcpStream, - current_timestamp: u64 -} - -impl Server { - pub fn new(interface: &str, port: u16) -> IoResult { - let mut acceptor = try!(TcpListener::bind(interface, port).listen()); - - let server = Server { - acceptor: acceptor.clone() - }; - - spawn(proc() { - loop { - for stream in acceptor.incoming() { - match stream { - Ok(stream) => spawn(proc() { - Server::handle_client(EndPoint::new(stream)); - }), - _ => return - } - } - } - }); - - 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) - } - } - - /// Send 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) { - let execute = |f: &mut |&mut Client| -> bool| -> bool { - match Client::new(address, port) { - Ok(ref mut client) => (*f)(client), - Err(e) => { - println!("Unable to create a client. Error: {}", e); - false - } - } - }; - - 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) { - Err(_) => vec!(), - _ => m.unwrap() - } - } - - let mut tests = vec!( - // 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 - } - } - }, - // 2) - |client: &mut Client| -> bool { - println!("Sending a packet with an unknown type..."); - client.end_point.current_timestamp += 1; - 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. - other => { - println!("Error: {}", other); - false - } - } - }, - // 3) - |client: &mut Client| -> bool { - println!("Sending a packet with an old timestamp..."); - 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. - other => { - println!("Error: {}", other); - false - } - } - }, - // 4) - |client: &mut Client| -> bool { - println!("Sending a packet with altered crypted data (do not alter the padding)..."); - client.end_point.current_timestamp += 1; - let mut raw_packet = raw_packet(client.end_point.current_timestamp); - raw_packet[11] = 0xDE; - raw_packet[12] = 0xAD; - 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, - other => { - println!("Error: {}", other); - false - } - } - }, - // 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))); - 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. - other => { - println!("Error: {}", other); - false - } - } - }, - // 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))); - 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. - other => { - println!("Error: {}", other); - false - } - } - }, - // 7) - |client: &mut Client| -> bool { - 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 }) { - Err(_) => vec!(), - _ => m.unwrap() - }; - - match client.end_point.send_raw_with_result(raw_packet.as_slice()) { - Ok(Ok(Packet { t: Error(packet::CryptError), .. })) => true, - other => { - println!("Error: {}", other); - false - } - } - }, - ); - - let mut nb_test_passed = 0; - for (i, test) in range(1, tests.len()+1).zip(tests.iter_mut()) { - println!("===== Test case #{}:", i) - if execute(test) { - nb_test_passed += 1; - println!("===== Test passed"); - } else { - println!("===== Test failed"); - } - } - - if nb_test_passed == tests.len() { - println!("All tests passed"); - } else { - println!("#{} test(s) failed", tests.len() - nb_test_passed); - } - } -} - -impl EndPoint { - pub fn new(socket: TcpStream) -> EndPoint { - EndPoint { socket: socket, current_timestamp: 0 } - } - - 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 send_with_result(&mut self, p: PacketType) -> IoResult { - match self.send(p) { - Err(e) => Err(e), - _ => Ok(self.read()) - } - } - - /// 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 { - self.socket.set_timeout(DEFAULT_TIMEOUT); - match self.socket.write(p) { - Err(e) => Err(e), - _ => Ok(self.read()) - } - } - - 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), - _ => 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(_) => () - }; - }; - - self.socket.set_timeout(DEFAULT_TIMEOUT); - 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::InvalidTimestampError) - } else { - self.current_timestamp = packet.timestamp + 1; - Ok(packet) - } - }, - e @ Err(packet::PaddingError) => { - self.current_timestamp += 1; - send_error(self, packet::CryptError); - e - }, - e @ Err(packet::MACMismatchError) => { - self.current_timestamp += 1; - send_error(self, packet::AuthError); - e - }, - other => - other - } - } -}