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