* Oracle machine finished.
[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 pub fn close(&mut self) -> IoResult<()> {
87 self.end_point.close()
88 }
89
90 pub fn send(&mut self, packet: PacketType) -> bool {
91 match packet {
92 Command(_) => {
93 self.end_point.print("Client", format!("Sending: {}", packet));
94 match self.end_point.send_with_result(packet) {
95 Ok(Ok(packet@Packet { t: Answer(..), .. })) => {
96 self.end_point.print("Client", format!("Command transmitted correctly, answer: {}", packet));
97 true
98 },
99 Ok(Ok(packet)) => {
100 self.end_point.print("Client", format!("Command transmitted correctly, wrong answer: {}", packet));
101 false
102 }
103 Ok(Err(e)) => {
104 self.end_point.print("Client", format!("Answer error: {}", e));
105 false
106 }
107 Err(e) => {
108 self.end_point.print("Client", format!("Can't send the packet. Error: {}", e));
109 false
110 }
111 }
112 },
113 other => {
114 self.end_point.print("Client", format!("Cannot send this type of packet: {}", other));
115 false
116 }
117 }
118 }
119
120 /// Send some valid and not-valid packets to the server and check the result.
121 /// For each test a new client is created.
122 pub fn start_tests(address: &str, port: u16, variant: packet::Variant) {
123 let execute = |f: &mut |&mut Client| -> bool| -> bool {
124 match Client::new(address, port, variant) {
125 Ok(ref mut client) => (*f)(client),
126 Err(e) => {
127 println!("Unable to create a client. Error: {}", e);
128 false
129 }
130 }
131 };
132
133 fn raw_packet(timestamp: u64) -> Vec<u8> {
134 let mut m = MemWriter::new();
135 match (Packet { t: Command(Packet::random_packet_data([42])), timestamp: timestamp }).write(&mut m, packet::Weak) {
136 Err(_) => vec!(),
137 _ => m.unwrap()
138 }
139 }
140
141 let mut tests = vec!(
142 // 1)
143 |client: &mut Client| -> bool {
144 println!("Sending a valid packet...");
145 client.send(Command(Packet::random_packet_data([42])))
146 },
147 // 2)
148 |client: &mut Client| -> bool {
149 println!("Sending a packet with an unknown type...");
150 client.end_point.current_timestamp += 1;
151 let mut raw_packet = raw_packet(client.end_point.current_timestamp);
152 raw_packet[2] = 0xEE; // Alter the type.
153 match client.end_point.send_raw_with_result(raw_packet.as_slice()) {
154 Ok(Err(packet::IOReadError( IoError { kind: io::TimedOut, .. }))) => true, // OK: the server should not send any packet.
155 other => {
156 println!("Error: {}", other);
157 false
158 }
159 }
160 },
161 // 3)
162 |client: &mut Client| -> bool {
163 println!("Sending a packet with an old timestamp...");
164 client.end_point.current_timestamp += 1;
165 let raw_packet = raw_packet(0);
166 match client.end_point.send_raw_with_result(raw_packet.as_slice()) {
167 Ok(Err(packet::IOReadError( IoError { kind: io::TimedOut, .. }))) => true, // OK: the server should not send any packet.
168 other => {
169 println!("Error: {}", other);
170 false
171 }
172 }
173 },
174 // 4)
175 |client: &mut Client| -> bool {
176 println!("Sending a packet with altered crypted data (do not alter the padding)...");
177 client.end_point.current_timestamp += 1;
178 let mut raw_packet = raw_packet(client.end_point.current_timestamp);
179 raw_packet[11] = 0xDE;
180 raw_packet[12] = 0xAD;
181 raw_packet[13] = 0xBE;
182 raw_packet[14] = 0xEF;
183 match client.end_point.send_raw_with_result(raw_packet.as_slice()) {
184 Ok(Ok(Packet { t: Error(packet::AuthError), .. })) => true,
185 other => {
186 println!("Error: {}", other);
187 false
188 }
189 }
190 },
191 // 5)
192 |client: &mut Client| -> bool {
193 println!("Sending a packet with too small data...");
194 let command = Command(Packet::new_packet_data(0, Vec::from_elem(6, 0x00)));
195 match client.end_point.send_with_result(command) {
196 Ok(Err(packet::IOReadError( IoError { kind: io::TimedOut, .. }))) => true, // OK: the server should not send any packet.
197 other => {
198 println!("Error: {}", other);
199 false
200 }
201 }
202 },
203 // 6)
204 |client: &mut Client| -> bool {
205 println!("Sending a packet with too large data...");
206 let command = Command(Packet::new_packet_data(0, Vec::from_elem(40, 0x00)));
207 match client.end_point.send_with_result(command) {
208 Ok(Err(packet::IOReadError( IoError { kind: io::TimedOut, .. }))) => true, // OK: the server should not send any packet.
209 other => {
210 println!("Error: {}", other);
211 false
212 }
213 }
214 },
215 // 7)
216 |client: &mut Client| -> bool {
217 println!("Sending a packet with wrong padding (all 0)...");
218 client.end_point.current_timestamp += 1;
219 let mut m = MemWriter::new();
220 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 }) {
221 Err(_) => vec!(),
222 _ => m.unwrap()
223 };
224
225 match client.end_point.send_raw_with_result(raw_packet.as_slice()) {
226 Ok(Ok(Packet { t: Error(packet::CryptError), .. })) => true,
227 other => {
228 println!("Error: {}", other);
229 false
230 }
231 }
232 },
233 );
234
235 let mut nb_test_passed = 0;
236 for (i, test) in range(1, tests.len()+1).zip(tests.iter_mut()) {
237 println!("===== Test case #{}:", i)
238 if execute(test) {
239 nb_test_passed += 1;
240 println!("===== Test passed");
241 } else {
242 println!("===== Test failed");
243 }
244 }
245
246 if nb_test_passed == tests.len() {
247 println!("All tests passed");
248 } else {
249 println!("#{} test(s) failed", tests.len() - nb_test_passed);
250 }
251 }
252 }
253
254 impl EndPoint {
255 pub fn new(mut socket: TcpStream, variant: packet::Variant) -> EndPoint {
256 let _ = socket.set_nodelay(true);
257 EndPoint { socket: socket, current_timestamp: 0 , variant: variant}
258 }
259
260 fn close(&mut self) -> IoResult<()> {
261 try!(self.socket.close_read());
262 try!(self.socket.close_write());
263 Ok(())
264 }
265
266 fn print(&self, prefix: &str, s: String) {
267 println!("[{}] time: {}. {}", prefix, self.current_timestamp, s);
268 }
269
270 /// Send a packet and wait for an answer synchronously.
271 fn send_with_result(&mut self, p: PacketType) -> IoResult<ReadingResult> {
272 match self.send(p) {
273 Err(e) => Err(e),
274 _ => Ok(self.read())
275 }
276 }
277
278 /// Send arbitrary data and wait for an answer synchronously.
279 /// Do not increment the current timestamp.
280 pub fn send_raw_with_result(&mut self, p: &[u8]) -> IoResult<ReadingResult> {
281 self.socket.set_timeout(DEFAULT_TIMEOUT);
282 match self.socket.write(p) {
283 Err(e) => Err(e),
284 _ => Ok(self.read())
285 }
286 }
287
288 fn send(&mut self, p: PacketType) -> IoResult<()> {
289 self.socket.set_timeout(DEFAULT_TIMEOUT);
290 self.current_timestamp += 1;
291 match (Packet { t: p, timestamp: self.current_timestamp }).write(&mut self.socket, self.variant) {
292 Err(packet::WriteIOError(e)) => Err(e),
293 _ => Ok(())
294 }
295 }
296
297 fn read(&mut self) -> ReadingResult {
298 fn send_error(ep: &mut EndPoint, error_type: packet::ErrorType) {
299 match ep.send(Error(error_type)) {
300 Err(e) => println!("Unable to send error packet: {}", e),
301 Ok(_) => ()
302 };
303 };
304
305 self.socket.set_timeout(DEFAULT_TIMEOUT);
306 match Packet::read(&mut self.socket, self.variant) {
307 Ok(packet) => {
308 if packet.timestamp <= self.current_timestamp {
309 println!("Error, timestamp mismatch, current timestamp: {}, packet received: {}", self.current_timestamp, packet);
310 Err(packet::InvalidTimestampError)
311 } else {
312 self.current_timestamp = packet.timestamp + 1;
313 Ok(packet)
314 }
315 },
316 e @ Err(packet::PaddingError) => {
317 self.current_timestamp += 1;
318 send_error(self, packet::CryptError);
319 e
320 },
321 e @ Err(packet::MACMismatchError) => {
322 self.current_timestamp += 1;
323 send_error(self, packet::AuthError);
324 e
325 },
326 other =>
327 other
328 }
329 }
330 }