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