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