--- a/rust/hedgewars-server/src/core/client.rs Thu Dec 26 21:55:51 2019 +0300
+++ b/rust/hedgewars-server/src/core/client.rs Fri Dec 27 22:36:19 2019 +0300
@@ -2,16 +2,15 @@
use bitflags::*;
bitflags! {
- pub struct ClientFlags: u16 {
+ pub struct ClientFlags: u8 {
const IS_ADMIN = 0b0000_0001;
const IS_MASTER = 0b0000_0010;
const IS_READY = 0b0000_0100;
const IS_IN_GAME = 0b0000_1000;
const IS_JOINED_MID_GAME = 0b0001_0000;
- const IS_CHECKER = 0b0010_0000;
- const IS_CONTRIBUTOR = 0b0100_0000;
- const HAS_SUPER_POWER = 0b1000_0000;
- const IS_REGISTERED = 0b0001_0000_0000;
+ const IS_CONTRIBUTOR = 0b0010_0000;
+ const HAS_SUPER_POWER = 0b0100_0000;
+ const IS_REGISTERED = 0b1000_0000;
const NONE = 0b0000_0000;
const DEFAULT = Self::NONE.bits;
@@ -66,9 +65,6 @@
pub fn is_joined_mid_game(&self) -> bool {
self.contains(ClientFlags::IS_JOINED_MID_GAME)
}
- pub fn is_checker(&self) -> bool {
- self.contains(ClientFlags::IS_CHECKER)
- }
pub fn is_contributor(&self) -> bool {
self.contains(ClientFlags::IS_CONTRIBUTOR)
}
@@ -94,9 +90,6 @@
pub fn set_is_joined_mid_game(&mut self, value: bool) {
self.set(ClientFlags::IS_JOINED_MID_GAME, value)
}
- pub fn set_is_checker(&mut self, value: bool) {
- self.set(ClientFlags::IS_CHECKER, value)
- }
pub fn set_is_contributor(&mut self, value: bool) {
self.set(ClientFlags::IS_CONTRIBUTOR, value)
}
--- a/rust/hedgewars-server/src/core/server.rs Thu Dec 26 21:55:51 2019 +0300
+++ b/rust/hedgewars-server/src/core/server.rs Fri Dec 27 22:36:19 2019 +0300
@@ -157,9 +157,24 @@
}
}
+struct HwChecker {
+ pub id: ClientId,
+ pub is_ready: bool,
+}
+
+impl HwChecker {
+ pub fn new(id: ClientId) -> Self {
+ Self {
+ id,
+ is_ready: false,
+ }
+ }
+}
+
pub struct HwServer {
clients: IndexSlab<HwClient>,
rooms: Slab<HwRoom>,
+ checkers: IndexSlab<HwChecker>,
latest_protocol: u16,
flags: ServerFlags,
greetings: ServerGreetings,
@@ -169,9 +184,11 @@
pub fn new(clients_limit: usize, rooms_limit: usize) -> Self {
let rooms = Slab::with_capacity(rooms_limit);
let clients = IndexSlab::with_capacity(clients_limit);
+ let checkers = IndexSlab::new();
Self {
clients,
rooms,
+ checkers,
greetings: ServerGreetings::new(),
latest_protocol: 58,
flags: ServerFlags::empty(),
@@ -242,9 +259,10 @@
}
pub fn add_client(&mut self, client_id: ClientId, data: HwAnteroomClient) {
- if let (Some(protocol), Some(nick)) = (data.protocol_number, data.nick) {
+ if data.is_checker {
+ self.checkers.insert(client_id, HwChecker::new(client_id));
+ } else if let (Some(protocol), Some(nick)) = (data.protocol_number, data.nick) {
let mut client = HwClient::new(client_id, protocol.get(), nick);
- client.set_is_checker(data.is_checker);
#[cfg(not(feature = "official-server"))]
client.set_is_admin(data.is_local_admin);
--- a/rust/hedgewars-server/src/handlers.rs Thu Dec 26 21:55:51 2019 +0300
+++ b/rust/hedgewars-server/src/handlers.rs Fri Dec 27 22:36:19 2019 +0300
@@ -115,6 +115,10 @@
client_salt: String,
server_salt: String,
},
+ GetCheckerAccount {
+ nick: String,
+ password: String,
+ },
GetReplay {
id: u32,
},
@@ -133,6 +137,7 @@
pub enum IoResult {
AccountRegistered(bool),
Account(Option<AccountInfo>),
+ CheckerAccount { is_registered: bool },
Replay(Option<Replay>),
SaveRoom(RoomId, bool),
LoadRoom(RoomId, Option<String>),
@@ -410,13 +415,17 @@
response.add(Bye(REGISTRATION_REQUIRED.to_string()).send_self());
response.remove_client(client_id);
} else if is_registered {
- let salt = state.anteroom.clients[client_id].server_salt.clone();
- response.add(AskPassword(salt).send_self());
+ let client = &state.anteroom.clients[client_id];
+ response.add(AskPassword(client.server_salt.clone()).send_self());
} else if let Some(client) = state.anteroom.remove_client(client_id) {
state.server.add_client(client_id, client);
common::get_lobby_join_data(&state.server, response);
}
}
+ IoResult::Account(None) => {
+ response.add(Bye(AUTHENTICATION_FAILED.to_string()).send_self());
+ response.remove_client(client_id);
+ }
IoResult::Account(Some(info)) => {
response.add(ServerAuth(format!("{:x}", info.server_hash)).send_self());
if let Some(mut client) = state.anteroom.remove_client(client_id) {
@@ -427,9 +436,16 @@
common::get_lobby_join_data(&state.server, response);
}
}
- IoResult::Account(None) => {
- response.error(AUTHENTICATION_FAILED);
- response.remove_client(client_id);
+ IoResult::CheckerAccount { is_registered } => {
+ if is_registered {
+ if let Some(client) = state.anteroom.remove_client(client_id) {
+ state.server.add_client(client_id, client);
+ response.add(LogonPassed.send_self());
+ }
+ } else {
+ response.add(Bye(NO_CHECKER_RIGHTS.to_string()).send_self());
+ response.remove_client(client_id);
+ }
}
IoResult::Replay(Some(replay)) => {
let client = state.server.client(client_id);
--- a/rust/hedgewars-server/src/handlers/inanteroom.rs Thu Dec 26 21:55:51 2019 +0300
+++ b/rust/hedgewars-server/src/handlers/inanteroom.rs Fri Dec 27 22:36:19 2019 +0300
@@ -1,5 +1,6 @@
use mio;
+use super::strings::*;
use crate::{
core::{
anteroom::{HwAnteroom, HwAnteroomClient},
@@ -33,18 +34,12 @@
where
I: Iterator<Item = &'a HwClient>,
{
- let has_nick_clash =
- other_clients.any(|c| !c.is_checker() && c.nick == *client.nick.as_ref().unwrap());
+ let has_nick_clash = other_clients.any(|c| 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
- }
+ client.nick = None;
+ response.add(Notice("NickAlreadyInUse".to_string()).send_self());
+ LoginResult::Unchanged
} else {
#[cfg(feature = "official-server")]
{
@@ -76,10 +71,10 @@
let client = &mut server_state.anteroom.clients[client_id];
if client.nick.is_some() {
- response.add(Error("Nickname already provided.".to_string()).send_self());
+ response.error(NICKNAME_PROVIDED);
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());
+ response.add(Bye(ILLEGAL_CLIENT_NAME.to_string()).send_self());
LoginResult::Exit
} else {
client.nick = Some(nick.clone());
@@ -95,11 +90,11 @@
HwProtocolMessage::Proto(proto) => {
let client = &mut server_state.anteroom.clients[client_id];
if client.protocol_number.is_some() {
- response.add(Error("Protocol already known.".to_string()).send_self());
+ response.error(PROTOCOL_PROVIDED);
LoginResult::Unchanged
- } else if proto == 0 {
- response.add(Error("Bad number.".to_string()).send_self());
- LoginResult::Unchanged
+ } else if proto < 48 {
+ response.add(Bye(PROTOCOL_TOO_OLD.to_string()).send_self());
+ LoginResult::Exit
} else {
client.protocol_number = NonZeroU16::new(proto);
response.add(Proto(proto).send_self());
@@ -131,17 +126,29 @@
HwProtocolMessage::Checker(protocol, nick, password) => {
let client = &mut server_state.anteroom.clients[client_id];
if protocol == 0 {
- response.add(Error("Bad number.".to_string()).send_self());
+ response.error("Bad number.");
LoginResult::Unchanged
} else {
client.protocol_number = NonZeroU16::new(protocol);
- client.nick = Some(nick);
client.is_checker = true;
- LoginResult::Complete
+ #[cfg(not(feature = "official-server"))]
+ {
+ response.request_io(super::IoTask::GetCheckerAccount {
+ nick: nick,
+ password: password,
+ });
+ LoginResult::Unchanged
+ }
+
+ #[cfg(feature = "official-server")]
+ {
+ response.add(LogonPassed.send_self());
+ LoginResult::Complete
+ }
}
}
_ => {
- warn!("Incorrect command in logging-in state");
+ warn!("Incorrect command in anteroom");
LoginResult::Unchanged
}
}
--- a/rust/hedgewars-server/src/handlers/strings.rs Thu Dec 26 21:55:51 2019 +0300
+++ b/rust/hedgewars-server/src/handlers/strings.rs Fri Dec 27 22:36:19 2019 +0300
@@ -1,11 +1,17 @@
pub const ACCESS_DENIED: &str = "Access denied.";
-pub const AUTHENTICATION_FAILED: &str = "Authentication failed.";
+pub const AUTHENTICATION_FAILED: &str = "Authentication failed";
+pub const BAD_NUMBER: &str = "Bad number.";
+pub const ILLEGAL_CLIENT_NAME: &str = "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: $()*+?[]^{|}";
pub const ILLEGAL_ROOM_NAME: &str = "Illegal room name! A room name must be between 1-40 characters long, must not have a trailing or leading space and must not have any of these characters: $()*+?[]^{|}";
+pub const NICKNAME_PROVIDED: &str = "Nickname already provided.";
+pub const NO_CHECKER_RIGHTS: &str = "No checker rights";
pub const NO_ROOM: &str = "No such room.";
pub const NO_TEAM: &str = "No such team.";
pub const NO_TEAM_TO_REMOVE: &str = "Error: The team you tried to remove does not exist.";
pub const NO_USER: &str = "No such user.";
pub const NOT_MASTER: &str = "You're not the room master!";
+pub const PROTOCOL_PROVIDED: &str = "Protocol already known.";
+pub const PROTOCOL_TOO_OLD: &str = "Protocol version is too old";
pub const REPLAY_LOAD_FAILED: &str = "Could't load the replay";
pub const REPLAY_NOT_SUPPORTED: &str = "This server does not support replays!";
pub const REGISTRATION_REQUIRED: &str = "This server only allows registered users to join.";
--- a/rust/hedgewars-server/src/protocol/messages.rs Thu Dec 26 21:55:51 2019 +0300
+++ b/rust/hedgewars-server/src/protocol/messages.rs Fri Dec 27 22:36:19 2019 +0300
@@ -120,6 +120,7 @@
Proto(u16),
AskPassword(String),
ServerAuth(String),
+ LogonPassed,
LobbyLeft(String, String),
LobbyJoined(Vec<String>),
@@ -390,6 +391,7 @@
Proto(proto) => msg!["PROTO", proto],
AskPassword(salt) => msg!["ASKPASSWORD", salt],
ServerAuth(hash) => msg!["SERVER_AUTH", hash],
+ LogonPassed => msg!["LOGONPASSED"],
LobbyLeft(nick, msg) => msg!["LOBBY:LEFT", nick, msg],
LobbyJoined(nicks) => construct_message(&["LOBBY:JOINED"], &nicks),
ClientFlags(flags, nicks) => construct_message(&["CLIENT_FLAGS", flags], &nicks),
--- a/rust/hedgewars-server/src/server/database.rs Thu Dec 26 21:55:51 2019 +0300
+++ b/rust/hedgewars-server/src/server/database.rs Fri Dec 27 22:36:19 2019 +0300
@@ -86,6 +86,23 @@
}
}
+ pub fn get_checker_account(
+ &mut self,
+ nick: &str,
+ checker_password: &str,
+ ) -> Result<bool, Error> {
+ if let Some(pool) = &self.pool {
+ if let Some(row) = pool.first_exec(GET_ACCOUNT_QUERY, params! { "username" => nick })? {
+ let (mut password, _, _) = from_row_opt::<(String, i32, i32)>(row)?;
+ Ok(checker_password == password)
+ } else {
+ Ok(false)
+ }
+ } else {
+ Err(DriverError::SetupError.into())
+ }
+ }
+
pub fn store_stats(&mut self, stats: &ServerStatistics) -> Result<(), Error> {
if let Some(pool) = &self.pool {
for mut stmt in pool.prepare(STORE_STATS_QUERY).into_iter() {
--- a/rust/hedgewars-server/src/server/io.rs Thu Dec 26 21:55:51 2019 +0300
+++ b/rust/hedgewars-server/src/server/io.rs Fri Dec 27 22:36:19 2019 +0300
@@ -61,6 +61,18 @@
}
}
+ IoTask::GetCheckerAccount { nick, password } => {
+ match db.get_checker_account(&nick, &password) {
+ Ok(is_registered) => IoResult::CheckerAccount { is_registered },
+ Err(e) => {
+ warn!("Unable to get checker account data: {}", e);
+ IoResult::CheckerAccount {
+ is_registered: false,
+ }
+ }
+ }
+ }
+
IoTask::GetReplay { id } => {
let result = match db.get_replay_name(id) {
Ok(Some(filename)) => {