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