Add the figure used in the report.
[crypto_lab1.git] / lab1_rust / src / end_point.rs
1 use std::io;
2 use std::io::{ MemWriter, Acceptor, Listener, TcpStream, IoResult, IoError, EndOfFile };
3 use std::io::net::tcp::{ TcpAcceptor, TcpListener };
4 use packet;
5 use packet::{ Packet, Command, Answer, Error, ReadingResult, PacketType };
6
7 // Default timeout when waiting data on a stream (for instance: 'TcpStream::read').
8 static DEFAULT_TIMEOUT: Option<u64> = Some(500); // [ms].
9
10 pub struct Server {
11 acceptor: TcpAcceptor,
12 }
13
14 pub struct Client {
15 end_point: EndPoint,
16 }
17
18 pub struct EndPoint {
19 socket: TcpStream,
20 current_timestamp: u64,
21 variant: packet::Variant,
22 }
23
24 impl Server {
25 pub fn new(interface: &str, port: u16, variant: packet::Variant) -> IoResult<Server> {
26 let mut acceptor = try!(TcpListener::bind(interface, port).listen());
27
28 let server = Server {
29 acceptor: acceptor.clone()
30 };
31
32 spawn(proc() {
33 loop {
34 for stream in acceptor.incoming() {
35 match stream {
36 Ok(stream) => spawn(proc() {
37 Server::handle_client(EndPoint::new(stream, variant));
38 }),
39 _ => return
40 }
41 }
42 }
43 });
44
45 Ok(server)
46 }
47
48 pub fn close(&mut self) -> IoResult<()> {
49 self.acceptor.close_accept()
50 }
51
52 fn handle_client(mut end_point: EndPoint) {
53 loop {
54 match end_point.read() {
55 Ok(packet@Packet { t: Command(..), .. }) => {
56 end_point.print("Server", format!("Valid command received: {}", packet));
57 let answer = Answer(Packet::random_packet_data([]));
58 match end_point.send(answer.clone()) {
59 Ok(_) =>
60 end_point.print("Server", format!("Answer sent: {}", answer)),
61 Err(e) =>
62 end_point.print("Server", format!("Can't send the answer. Error: {}", e))
63 }
64 },
65 // Socket has been closed.
66 Err(packet::IOReadError(IoError { kind: EndOfFile, .. })) => {
67 end_point.print("Server", format!("Connection closed: EOF"));
68 return
69 },
70 other =>
71 end_point.print("Server", format!("Error or invalid packet: {}", other))
72 }
73 }
74 }
75 }
76
77 impl Client {
78 pub fn new(address: &str, port: u16, variant: packet::Variant) -> IoResult<Client> {
79 Ok(Client { end_point: EndPoint {
80 socket: try!(TcpStream::connect(address, port)),
81 current_timestamp: 0,
82 variant: variant,
83 }})
84 }
85
86 #[allow(dead_code)]
87 pub fn close(&mut self) -> IoResult<()> {
88 self.end_point.close()
89 }
90
91 pub fn send(&mut self, packet: PacketType) -> bool {
92 match packet {
93 Command(_) => {
94 self.end_point.print("Client", format!("Sending: {}", packet));
95 match self.end_point.send_with_result(packet) {
96 Ok(Ok(packet@Packet { t: Answer(..), .. })) => {
97 self.end_point.print("Client", format!("Command transmitted correctly, answer: {}", packet));
98 true
99 },
100 Ok(Ok(packet)) => {
101 self.end_point.print("Client", format!("Command transmitted correctly, wrong answer: {}", packet));
102 false
103 }
104 Ok(Err(e)) => {
105 self.end_point.print("Client", format!("Answer error: {}", e));
106 false
107 }
108 Err(e) => {
109 self.end_point.print("Client", format!("Can't send the packet. Error: {}", e));
110 false
111 }
112 }
113 },
114 other => {
115 self.end_point.print("Client", format!("Cannot send this type of packet: {}", other));
116 false
117 }
118 }
119 }
120
121 /// Send some valid and not-valid packets to the server and check the result.
122 /// For each test a new client is created.
123 pub fn start_tests(address: &str, port: u16, variant: packet::Variant) {
124 let execute = |f: &mut |&mut Client| -> bool| -> bool {
125 match Client::new(address, port, variant) {
126 Ok(ref mut client) => (*f)(client),
127 Err(e) => {
128 println!("Unable to create a client. Error: {}", e);
129 false
130 }
131 }
132 };
133
134 fn raw_packet(timestamp: u64) -> Vec<u8> {
135 let mut m = MemWriter::new();
136 match (Packet { t: Command(Packet::random_packet_data([42])), timestamp: timestamp }).write(&mut m, packet::Weak) {
137 Err(_) => vec!(),
138 _ => m.unwrap()
139 }
140 }
141
142 let mut tests = vec!(
143 // 1)
144 |client: &mut Client| -> bool {
145 println!("Sending a valid packet...");
146 client.send(Command(Packet::random_packet_data([42])))
147 },
148 // 2)
149 |client: &mut Client| -> bool {
150 println!("Sending a packet with an unknown type...");
151 client.end_point.current_timestamp += 1;
152 let mut raw_packet = raw_packet(client.end_point.current_timestamp);
153 raw_packet[2] = 0xEE; // Alter the type.
154 match client.end_point.send_raw_with_result(raw_packet.as_slice()) {
155 Ok(Err(packet::IOReadError( IoError { kind: io::TimedOut, .. }))) => true, // OK: the server should not send any packet.
156 other => {
157 println!("Error: {}", other);
158 false
159 }
160 }
161 },
162 // 3)
163 |client: &mut Client| -> bool {
164 println!("Sending a packet with an old timestamp...");
165 client.end_point.current_timestamp += 1;
166 let raw_packet = raw_packet(0);
167 match client.end_point.send_raw_with_result(raw_packet.as_slice()) {
168 Ok(Err(packet::IOReadError( IoError { kind: io::TimedOut, .. }))) => true, // OK: the server should not send any packet.
169 other => {
170 println!("Error: {}", other);
171 false
172 }
173 }
174 },
175 // 4)
176 |client: &mut Client| -> bool {
177 println!("Sending a packet with altered crypted data (do not alter the padding)...");
178 client.end_point.current_timestamp += 1;
179 let mut raw_packet = raw_packet(client.end_point.current_timestamp);
180 raw_packet[11] = 0xDE;
181 raw_packet[12] = 0xAD;
182 raw_packet[13] = 0xBE;
183 raw_packet[14] = 0xEF;
184 match client.end_point.send_raw_with_result(raw_packet.as_slice()) {
185 Ok(Ok(Packet { t: Error(packet::AuthError), .. })) => true,
186 other => {
187 println!("Error: {}", other);
188 false
189 }
190 }
191 },
192 // 5)
193 |client: &mut Client| -> bool {
194 println!("Sending a packet with too small data...");
195 let command = Command(Packet::new_packet_data(0, Vec::from_elem(6, 0x00)));
196 match client.end_point.send_with_result(command) {
197 Ok(Err(packet::IOReadError( IoError { kind: io::TimedOut, .. }))) => true, // OK: the server should not send any packet.
198 other => {
199 println!("Error: {}", other);
200 false
201 }
202 }
203 },
204 // 6)
205 |client: &mut Client| -> bool {
206 println!("Sending a packet with too large data...");
207 let command = Command(Packet::new_packet_data(0, Vec::from_elem(40, 0x00)));
208 match client.end_point.send_with_result(command) {
209 Ok(Err(packet::IOReadError( IoError { kind: io::TimedOut, .. }))) => true, // OK: the server should not send any packet.
210 other => {
211 println!("Error: {}", other);
212 false
213 }
214 }
215 },
216 // 7)
217 |client: &mut Client| -> bool {
218 println!("Sending a packet with wrong padding (all 0)...");
219 client.end_point.current_timestamp += 1;
220 let mut m = MemWriter::new();
221 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::Weak, |_, _| -> u8 { 0 }) {
222 Err(_) => vec!(),
223 _ => m.unwrap()
224 };
225
226 match client.end_point.send_raw_with_result(raw_packet.as_slice()) {
227 Ok(Ok(Packet { t: Error(packet::CryptError), .. })) => true,
228 other => {
229 println!("Error: {}", other);
230 false
231 }
232 }
233 },
234 );
235
236 let mut nb_test_passed = 0;
237 for (i, test) in range(1, tests.len()+1).zip(tests.iter_mut()) {
238 println!("===== Test case #{}:", i)
239 if execute(test) {
240 nb_test_passed += 1;
241 println!("===== Test passed");
242 } else {
243 println!("===== Test failed");
244 }
245 }
246
247 if nb_test_passed == tests.len() {
248 println!("All tests passed");
249 } else {
250 println!("#{} test(s) failed", tests.len() - nb_test_passed);
251 }
252 }
253 }
254
255 impl EndPoint {
256 pub fn new(mut socket: TcpStream, variant: packet::Variant) -> EndPoint {
257 let _ = socket.set_nodelay(true);
258 EndPoint { socket: socket, current_timestamp: 0 , variant: variant}
259 }
260
261 #[allow(dead_code)]
262 fn close(&mut self) -> IoResult<()> {
263 try!(self.socket.close_read());
264 try!(self.socket.close_write());
265 Ok(())
266 }
267
268 fn print(&self, prefix: &str, s: String) {
269 println!("[{}] time: {}. {}", prefix, self.current_timestamp, s);
270 }
271
272 /// Send a packet and wait for an answer synchronously.
273 fn send_with_result(&mut self, p: PacketType) -> IoResult<ReadingResult> {
274 match self.send(p) {
275 Err(e) => Err(e),
276 _ => Ok(self.read())
277 }
278 }
279
280 /// Send arbitrary data and wait for an answer synchronously.
281 /// Do not increment the current timestamp.
282 pub fn send_raw_with_result(&mut self, p: &[u8]) -> IoResult<ReadingResult> {
283 self.socket.set_timeout(DEFAULT_TIMEOUT);
284 match self.socket.write(p) {
285 Err(e) => Err(e),
286 _ => Ok(self.read())
287 }
288 }
289
290 fn send(&mut self, p: PacketType) -> IoResult<()> {
291 self.socket.set_timeout(DEFAULT_TIMEOUT);
292 self.current_timestamp += 1;
293 match (Packet { t: p, timestamp: self.current_timestamp }).write(&mut self.socket, self.variant) {
294 Err(packet::WriteIOError(e)) => Err(e),
295 _ => Ok(())
296 }
297 }
298
299 fn read(&mut self) -> ReadingResult {
300 fn send_error(ep: &mut EndPoint, error_type: packet::ErrorType) {
301 match ep.send(Error(error_type)) {
302 Err(e) => println!("Unable to send error packet: {}", e),
303 Ok(_) => ()
304 };
305 };
306
307 self.socket.set_timeout(DEFAULT_TIMEOUT);
308 match Packet::read(&mut self.socket, self.variant) {
309 Ok(packet) => {
310 if packet.timestamp <= self.current_timestamp {
311 println!("Error, timestamp mismatch, current timestamp: {}, packet received: {}", self.current_timestamp, packet);
312 Err(packet::InvalidTimestampError)
313 } else {
314 self.current_timestamp = packet.timestamp + 1;
315 Ok(packet)
316 }
317 },
318 e @ Err(packet::PaddingError) => {
319 self.current_timestamp += 1;
320 send_error(self, packet::CryptError);
321 e
322 },
323 e @ Err(packet::MACMismatchError) => {
324 self.current_timestamp += 1;
325 send_error(self, packet::AuthError);
326 e
327 },
328 other =>
329 other
330 }
331 }
332 }