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