rust/hedgewars-server/src/server/handlers.rs
changeset 14779 f43ab2bd76ae
parent 14696 8a45c90f4580
child 14780 65861ba8b4e8
equal deleted inserted replaced
14778:bbec6b28d072 14779:f43ab2bd76ae
     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 }