diff -r 7732013ce64c -r c5a6e8566425 rust/hedgewars-server/src/handlers/inanteroom.rs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rust/hedgewars-server/src/handlers/inanteroom.rs Tue May 28 19:04:18 2019 +0300 @@ -0,0 +1,148 @@ +use mio; + +use crate::{ + protocol::messages::{ + HWProtocolMessage::LoadRoom, + HWProtocolMessage, + HWServerMessage::*}, + core::{ + client::HWClient, + server::{HWServer, HWAnteClient, HWAnteroom}, + types::ClientId + }, + utils::is_name_illegal +}; + +use log::*; +#[cfg(feature = "official-server")] +use openssl::sha::sha1; +use std::{ + fmt::{Formatter, LowerHex}, + num::NonZeroU16, +}; + +pub enum LoginResult { + Unchanged, + Complete, + Exit, +} + +fn completion_result<'a, I>( + mut other_clients: I, + client: &mut HWAnteClient, + response: &mut super::Response, +) -> LoginResult +where + I: Iterator, +{ + let has_nick_clash = + other_clients.any(|(_, c)| !c.is_checker() && c.nick == *client.nick.as_ref().unwrap()); + + if has_nick_clash { + if client.protocol_number.unwrap().get() < 38 { + response.add(Bye("User quit: Nickname is already in use".to_string()).send_self()); + LoginResult::Exit + } else { + client.nick = None; + response.add(Notice("NickAlreadyInUse".to_string()).send_self()); + LoginResult::Unchanged + } + } else { + #[cfg(feature = "official-server")] + { + response.add(AskPassword(client.server_salt.clone()).send_self()); + LoginResult::Unchanged + } + + #[cfg(not(feature = "official-server"))] + { + LoginResult::Complete + } + } +} + +pub fn handle( + server: &mut HWServer, + client_id: ClientId, + response: &mut super::Response, + message: HWProtocolMessage, +) -> LoginResult { + match message { + HWProtocolMessage::Quit(_) => { + response.add(Bye("User quit".to_string()).send_self()); + LoginResult::Exit + } + HWProtocolMessage::Nick(nick) => { + let client = &mut server.anteroom.clients[client_id]; + + if client.nick.is_some() { + response.add(Error("Nickname already provided.".to_string()).send_self()); + LoginResult::Unchanged + } else if is_name_illegal(&nick) { + 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()); + LoginResult::Exit + } else { + client.nick = Some(nick.clone()); + response.add(Nick(nick).send_self()); + + if client.protocol_number.is_some() { + completion_result(server.clients.iter(), client, response) + } else { + LoginResult::Unchanged + } + } + } + HWProtocolMessage::Proto(proto) => { + let client = &mut server.anteroom.clients[client_id]; + if client.protocol_number.is_some() { + response.add(Error("Protocol already known.".to_string()).send_self()); + LoginResult::Unchanged + } else if proto == 0 { + response.add(Error("Bad number.".to_string()).send_self()); + LoginResult::Unchanged + } else { + client.protocol_number = NonZeroU16::new(proto); + response.add(Proto(proto).send_self()); + + if client.nick.is_some() { + completion_result(server.clients.iter(), client, response) + } else { + LoginResult::Unchanged + } + } + } + #[cfg(feature = "official-server")] + HWProtocolMessage::Password(hash, salt) => { + let client = &server.anteroom.clients[client_id]; + + if let (Some(nick), Some(protocol)) = (client.nick.as_ref(), client.protocol_number) { + response.request_io(super::IoTask::GetAccount { + nick: nick.clone(), + protocol: protocol.get(), + server_salt: client.server_salt.clone(), + client_salt: salt, + password_hash: hash, + }); + }; + + LoginResult::Unchanged + } + #[cfg(feature = "official-server")] + HWProtocolMessage::Checker(protocol, nick, password) => { + let client = &mut server.anteroom.clients[client_id]; + if protocol == 0 { + response.add(Error("Bad number.".to_string()).send_self()); + LoginResult::Unchanged + } else { + client.protocol_number = NonZeroU16::new(protocol); + client.nick = Some(nick); + client.is_checker = true; + LoginResult::Complete + } + } + _ => { + warn!("Incorrect command in logging-in state"); + LoginResult::Unchanged + } + } +}