1 use mio; |
1 use mio; |
2 use std::{io, io::Write}; |
2 use std::{collections::HashMap, io, io::Write}; |
3 |
3 |
4 use super::{ |
4 use super::{ |
5 actions::{Destination, DestinationRoom}, |
5 actions::{Destination, DestinationRoom}, |
6 core::HWServer, |
6 core::HWServer, |
7 coretypes::ClientId, |
7 coretypes::ClientId, |
|
8 room::RoomSave, |
8 }; |
9 }; |
9 use crate::{ |
10 use crate::{ |
10 protocol::messages::{HWProtocolMessage, HWServerMessage, HWServerMessage::*}, |
11 protocol::messages::{HWProtocolMessage, HWServerMessage, HWServerMessage::*}, |
11 server::actions::PendingMessage, |
12 server::actions::PendingMessage, |
12 utils, |
13 utils, |
20 mod inroom; |
21 mod inroom; |
21 mod lobby; |
22 mod lobby; |
22 mod loggingin; |
23 mod loggingin; |
23 |
24 |
24 use self::loggingin::LoginResult; |
25 use self::loggingin::LoginResult; |
|
26 use std::fmt::{Formatter, LowerHex}; |
|
27 |
|
28 #[derive(PartialEq)] |
|
29 pub struct Sha1Digest([u8; 20]); |
|
30 |
|
31 impl Sha1Digest { |
|
32 pub fn new(digest: [u8; 20]) -> Self { |
|
33 Self(digest) |
|
34 } |
|
35 } |
|
36 |
|
37 impl LowerHex for Sha1Digest { |
|
38 fn fmt(&self, f: &mut Formatter) -> Result<(), std::fmt::Error> { |
|
39 for byte in &self.0 { |
|
40 write!(f, "{:02x}", byte)?; |
|
41 } |
|
42 Ok(()) |
|
43 } |
|
44 } |
|
45 |
|
46 pub struct AccountInfo { |
|
47 pub is_registered: bool, |
|
48 pub is_admin: bool, |
|
49 pub is_contributor: bool, |
|
50 pub server_hash: Sha1Digest, |
|
51 } |
|
52 |
|
53 pub enum IoTask { |
|
54 GetAccount { |
|
55 nick: String, |
|
56 protocol: u16, |
|
57 password_hash: String, |
|
58 client_salt: String, |
|
59 server_salt: String, |
|
60 }, |
|
61 } |
|
62 |
|
63 pub enum IoResult { |
|
64 Account(Option<AccountInfo>), |
|
65 } |
25 |
66 |
26 pub struct Response { |
67 pub struct Response { |
27 client_id: ClientId, |
68 client_id: ClientId, |
28 messages: Vec<PendingMessage>, |
69 messages: Vec<PendingMessage>, |
|
70 io_tasks: Vec<IoTask>, |
29 removed_clients: Vec<ClientId>, |
71 removed_clients: Vec<ClientId>, |
30 } |
72 } |
31 |
73 |
32 impl Response { |
74 impl Response { |
33 pub fn new(client_id: ClientId) -> Self { |
75 pub fn new(client_id: ClientId) -> Self { |
34 Self { |
76 Self { |
35 client_id, |
77 client_id, |
36 messages: vec![], |
78 messages: vec![], |
|
79 io_tasks: vec![], |
37 removed_clients: vec![], |
80 removed_clients: vec![], |
38 } |
81 } |
39 } |
82 } |
40 |
83 |
41 #[inline] |
84 #[inline] |
42 pub fn is_empty(&self) -> bool { |
85 pub fn is_empty(&self) -> bool { |
43 self.messages.is_empty() && self.removed_clients.is_empty() |
86 self.messages.is_empty() && self.removed_clients.is_empty() && self.io_tasks.is_empty() |
44 } |
87 } |
45 |
88 |
46 #[inline] |
89 #[inline] |
47 pub fn len(&self) -> usize { |
90 pub fn len(&self) -> usize { |
48 self.messages.len() |
91 self.messages.len() |
54 } |
97 } |
55 |
98 |
56 #[inline] |
99 #[inline] |
57 pub fn add(&mut self, message: PendingMessage) { |
100 pub fn add(&mut self, message: PendingMessage) { |
58 self.messages.push(message) |
101 self.messages.push(message) |
|
102 } |
|
103 |
|
104 #[inline] |
|
105 pub fn request_io(&mut self, task: IoTask) { |
|
106 self.io_tasks.push(task) |
59 } |
107 } |
60 |
108 |
61 pub fn extract_messages<'a, 'b: 'a>( |
109 pub fn extract_messages<'a, 'b: 'a>( |
62 &'b mut self, |
110 &'b mut self, |
63 server: &'a HWServer, |
111 server: &'a HWServer, |
73 self.removed_clients.push(client_id); |
121 self.removed_clients.push(client_id); |
74 } |
122 } |
75 |
123 |
76 pub fn extract_removed_clients(&mut self) -> impl Iterator<Item = ClientId> + '_ { |
124 pub fn extract_removed_clients(&mut self) -> impl Iterator<Item = ClientId> + '_ { |
77 self.removed_clients.drain(..) |
125 self.removed_clients.drain(..) |
|
126 } |
|
127 |
|
128 pub fn extract_io_tasks(&mut self) -> impl Iterator<Item = IoTask> + '_ { |
|
129 self.io_tasks.drain(..) |
78 } |
130 } |
79 } |
131 } |
80 |
132 |
81 impl Extend<PendingMessage> for Response { |
133 impl Extend<PendingMessage> for Response { |
82 fn extend<T: IntoIterator<Item = PendingMessage>>(&mut self, iter: T) { |
134 fn extend<T: IntoIterator<Item = PendingMessage>>(&mut self, iter: T) { |
175 pub fn handle_client_loss(server: &mut HWServer, client_id: ClientId, response: &mut Response) { |
227 pub fn handle_client_loss(server: &mut HWServer, client_id: ClientId, response: &mut Response) { |
176 if server.anteroom.remove_client(client_id).is_none() { |
228 if server.anteroom.remove_client(client_id).is_none() { |
177 common::remove_client(server, response, "Connection reset".to_string()); |
229 common::remove_client(server, response, "Connection reset".to_string()); |
178 } |
230 } |
179 } |
231 } |
|
232 |
|
233 pub fn handle_io_result( |
|
234 server: &mut HWServer, |
|
235 client_id: ClientId, |
|
236 response: &mut Response, |
|
237 io_result: IoResult, |
|
238 ) { |
|
239 match io_result { |
|
240 IoResult::Account(Some(info)) => { |
|
241 response.add(ServerAuth(format!("{:x}", info.server_hash)).send_self()); |
|
242 if let Some(client) = server.anteroom.remove_client(client_id) { |
|
243 server.add_client(client_id, client); |
|
244 let client = &mut server.clients[client_id]; |
|
245 client.set_is_admin(info.is_admin); |
|
246 client.set_is_contributor(info.is_admin) |
|
247 } |
|
248 } |
|
249 IoResult::Account(None) => { |
|
250 response.add(Error("Authentication failed.".to_string()).send_self()); |
|
251 response.remove_client(client_id); |
|
252 } |
|
253 } |
|
254 } |