rust/hedgewars-server/src/server/handlers/loggingin.rs
changeset 15074 c5a6e8566425
parent 15073 7732013ce64c
child 15075 e935b1ad23f3
equal deleted inserted replaced
15073:7732013ce64c 15074:c5a6e8566425
     1 use mio;
       
     2 
       
     3 use crate::protocol::messages::HWProtocolMessage::LoadRoom;
       
     4 use crate::server::client::HWClient;
       
     5 use crate::server::core::HWServer;
       
     6 use crate::{
       
     7     protocol::messages::{HWProtocolMessage, HWServerMessage::*},
       
     8     server::{
       
     9         core::{HWAnteClient, HWAnteroom},
       
    10         coretypes::ClientId,
       
    11     },
       
    12     utils::is_name_illegal,
       
    13 };
       
    14 use log::*;
       
    15 #[cfg(feature = "official-server")]
       
    16 use openssl::sha::sha1;
       
    17 use std::{
       
    18     fmt::{Formatter, LowerHex},
       
    19     num::NonZeroU16,
       
    20 };
       
    21 
       
    22 pub enum LoginResult {
       
    23     Unchanged,
       
    24     Complete,
       
    25     Exit,
       
    26 }
       
    27 
       
    28 fn completion_result<'a, I>(
       
    29     mut other_clients: I,
       
    30     client: &mut HWAnteClient,
       
    31     response: &mut super::Response,
       
    32 ) -> LoginResult
       
    33 where
       
    34     I: Iterator<Item = (ClientId, &'a HWClient)>,
       
    35 {
       
    36     let has_nick_clash =
       
    37         other_clients.any(|(_, c)| !c.is_checker() && c.nick == *client.nick.as_ref().unwrap());
       
    38 
       
    39     if has_nick_clash {
       
    40         if client.protocol_number.unwrap().get() < 38 {
       
    41             response.add(Bye("User quit: Nickname is already in use".to_string()).send_self());
       
    42             LoginResult::Exit
       
    43         } else {
       
    44             client.nick = None;
       
    45             response.add(Notice("NickAlreadyInUse".to_string()).send_self());
       
    46             LoginResult::Unchanged
       
    47         }
       
    48     } else {
       
    49         #[cfg(feature = "official-server")]
       
    50         {
       
    51             response.add(AskPassword(client.server_salt.clone()).send_self());
       
    52             LoginResult::Unchanged
       
    53         }
       
    54 
       
    55         #[cfg(not(feature = "official-server"))]
       
    56         {
       
    57             LoginResult::Complete
       
    58         }
       
    59     }
       
    60 }
       
    61 
       
    62 pub fn handle(
       
    63     server: &mut HWServer,
       
    64     client_id: ClientId,
       
    65     response: &mut super::Response,
       
    66     message: HWProtocolMessage,
       
    67 ) -> LoginResult {
       
    68     match message {
       
    69         HWProtocolMessage::Quit(_) => {
       
    70             response.add(Bye("User quit".to_string()).send_self());
       
    71             LoginResult::Exit
       
    72         }
       
    73         HWProtocolMessage::Nick(nick) => {
       
    74             let client = &mut server.anteroom.clients[client_id];
       
    75 
       
    76             if client.nick.is_some() {
       
    77                 response.add(Error("Nickname already provided.".to_string()).send_self());
       
    78                 LoginResult::Unchanged
       
    79             } else if is_name_illegal(&nick) {
       
    80                 response.add(Bye("Illegal nickname! Nicknames must be between 1-40 characters long, must not have a trailing or leading space and must not have any of these characters: $()*+?[]^{|}".to_string()).send_self());
       
    81                 LoginResult::Exit
       
    82             } else {
       
    83                 client.nick = Some(nick.clone());
       
    84                 response.add(Nick(nick).send_self());
       
    85 
       
    86                 if client.protocol_number.is_some() {
       
    87                     completion_result(server.clients.iter(), client, response)
       
    88                 } else {
       
    89                     LoginResult::Unchanged
       
    90                 }
       
    91             }
       
    92         }
       
    93         HWProtocolMessage::Proto(proto) => {
       
    94             let client = &mut server.anteroom.clients[client_id];
       
    95             if client.protocol_number.is_some() {
       
    96                 response.add(Error("Protocol already known.".to_string()).send_self());
       
    97                 LoginResult::Unchanged
       
    98             } else if proto == 0 {
       
    99                 response.add(Error("Bad number.".to_string()).send_self());
       
   100                 LoginResult::Unchanged
       
   101             } else {
       
   102                 client.protocol_number = NonZeroU16::new(proto);
       
   103                 response.add(Proto(proto).send_self());
       
   104 
       
   105                 if client.nick.is_some() {
       
   106                     completion_result(server.clients.iter(), client, response)
       
   107                 } else {
       
   108                     LoginResult::Unchanged
       
   109                 }
       
   110             }
       
   111         }
       
   112         #[cfg(feature = "official-server")]
       
   113         HWProtocolMessage::Password(hash, salt) => {
       
   114             let client = &server.anteroom.clients[client_id];
       
   115 
       
   116             if let (Some(nick), Some(protocol)) = (client.nick.as_ref(), client.protocol_number) {
       
   117                 response.request_io(super::IoTask::GetAccount {
       
   118                     nick: nick.clone(),
       
   119                     protocol: protocol.get(),
       
   120                     server_salt: client.server_salt.clone(),
       
   121                     client_salt: salt,
       
   122                     password_hash: hash,
       
   123                 });
       
   124             };
       
   125 
       
   126             LoginResult::Unchanged
       
   127         }
       
   128         #[cfg(feature = "official-server")]
       
   129         HWProtocolMessage::Checker(protocol, nick, password) => {
       
   130             let client = &mut server.anteroom.clients[client_id];
       
   131             if protocol == 0 {
       
   132                 response.add(Error("Bad number.".to_string()).send_self());
       
   133                 LoginResult::Unchanged
       
   134             } else {
       
   135                 client.protocol_number = NonZeroU16::new(protocol);
       
   136                 client.nick = Some(nick);
       
   137                 client.is_checker = true;
       
   138                 LoginResult::Complete
       
   139             }
       
   140         }
       
   141         _ => {
       
   142             warn!("Incorrect command in logging-in state");
       
   143             LoginResult::Unchanged
       
   144         }
       
   145     }
       
   146 }