--- a/rust/hedgewars-server/src/server/core.rs Tue Apr 09 23:03:12 2019 +0300
+++ b/rust/hedgewars-server/src/server/core.rs Wed Apr 10 01:13:29 2019 +0300
@@ -16,6 +16,7 @@
pub nick: Option<String>,
pub protocol_number: Option<NonZeroU16>,
pub server_salt: String,
+ pub is_checker: bool,
}
pub struct HWAnteroom {
@@ -33,6 +34,7 @@
nick: None,
protocol_number: None,
server_salt: salt,
+ is_checker: false,
};
self.clients.insert(client_id, client);
}
@@ -62,7 +64,8 @@
pub fn add_client(&mut self, client_id: ClientId, data: HWAnteClient) {
if let (Some(protocol), Some(nick)) = (data.protocol_number, data.nick) {
- let client = HWClient::new(client_id, protocol.get(), nick);
+ let mut client = HWClient::new(client_id, protocol.get(), nick);
+ client.set_is_checker(data.is_checker);
self.clients.insert(client_id, client);
}
}
@@ -119,28 +122,39 @@
.find_map(|(_, c)| Some(c).filter(|c| c.nick == nick))
}
- pub fn select_clients<F>(&self, f: F) -> Vec<ClientId>
+ pub fn collect_clients<F>(&self, f: F) -> Vec<ClientId>
where
F: Fn(&(usize, &HWClient)) -> bool,
{
self.clients.iter().filter(f).map(|(_, c)| c.id).collect()
}
- pub fn lobby_clients(&self) -> Vec<ClientId> {
- self.select_clients(|(_, c)| c.room_id == None)
+ pub fn collect_nicks<F>(&self, f: F) -> Vec<String>
+ where
+ F: Fn(&(usize, &HWClient)) -> bool,
+ {
+ self.clients
+ .iter()
+ .filter(f)
+ .map(|(_, c)| c.nick.clone())
+ .collect()
}
- pub fn room_clients(&self, room_id: RoomId) -> Vec<ClientId> {
- self.select_clients(|(_, c)| c.room_id == Some(room_id))
+ pub fn collect_lobby_clients(&self) -> Vec<ClientId> {
+ self.collect_clients(|(_, c)| c.room_id == None)
+ }
+
+ pub fn collect_room_clients(&self, room_id: RoomId) -> Vec<ClientId> {
+ self.collect_clients(|(_, c)| c.room_id == Some(room_id))
}
pub fn protocol_clients(&self, protocol: u16) -> Vec<ClientId> {
- self.select_clients(|(_, c)| c.protocol_number == protocol)
+ self.collect_clients(|(_, c)| c.protocol_number == protocol)
}
pub fn other_clients_in_room(&self, self_id: ClientId) -> Vec<ClientId> {
let room_id = self.clients[self_id].room_id;
- self.select_clients(|(id, c)| *id != self_id && c.room_id == room_id)
+ self.collect_clients(|(id, c)| *id != self_id && c.room_id == room_id)
}
}
--- a/rust/hedgewars-server/src/server/handlers.rs Tue Apr 09 23:03:12 2019 +0300
+++ b/rust/hedgewars-server/src/server/handlers.rs Wed Apr 10 01:13:29 2019 +0300
@@ -8,7 +8,7 @@
room::RoomSave,
};
use crate::{
- protocol::messages::{HWProtocolMessage, HWServerMessage, HWServerMessage::*, server_chat},
+ protocol::messages::{server_chat, HWProtocolMessage, HWServerMessage, HWServerMessage::*},
server::actions::PendingMessage,
utils,
};
@@ -65,14 +65,14 @@
},
LoadRoom {
room_id: RoomId,
- filename: String
- }
+ filename: String,
+ },
}
pub enum IoResult {
Account(Option<AccountInfo>),
SaveRoom(RoomId, bool),
- LoadRoom(RoomId, Option<String>)
+ LoadRoom(RoomId, Option<String>),
}
pub struct Response {
@@ -160,11 +160,11 @@
Destination::ToAll {
room_id: DestinationRoom::Lobby,
..
- } => server.lobby_clients(),
+ } => server.collect_lobby_clients(),
Destination::ToAll {
room_id: DestinationRoom::Room(id),
..
- } => server.room_clients(id),
+ } => server.collect_room_clients(id),
Destination::ToAll {
protocol: Some(proto),
..
@@ -194,11 +194,12 @@
HWProtocolMessage::Empty => warn!("Empty message"),
_ => {
if server.anteroom.clients.contains(client_id) {
- match loggingin::handle(&mut server.anteroom, client_id, response, message) {
+ match loggingin::handle(server, client_id, response, message) {
LoginResult::Unchanged => (),
LoginResult::Complete => {
if let Some(client) = server.anteroom.remove_client(client_id) {
server.add_client(client_id, client);
+ common::join_lobby(server, response);
}
}
LoginResult::Exit => {
@@ -265,16 +266,13 @@
response.add(server_chat("Room configs saved successfully.".to_string()).send_self());
}
IoResult::SaveRoom(_, false) => {
- response.add(
- Warning("Unable to save the room configs.".to_string()).send_self(),
- );
+ response.add(Warning("Unable to save the room configs.".to_string()).send_self());
}
IoResult::LoadRoom(room_id, Some(contents)) => {
if let Some(ref mut room) = server.rooms.get_mut(room_id) {
match room.set_saves(&contents) {
Ok(_) => response.add(
- server_chat("Room configs loaded successfully.".to_string())
- .send_self(),
+ server_chat("Room configs loaded successfully.".to_string()).send_self(),
),
Err(e) => {
warn!("Error while deserializing the room configs: {}", e);
@@ -286,10 +284,8 @@
}
}
}
- IoResult::LoadRoom(_,None) => {
- response.add(
- Warning("Unable to load the room configs.".to_string()).send_self(),
- );
+ IoResult::LoadRoom(_, None) => {
+ response.add(Warning("Unable to load the room configs.".to_string()).send_self());
}
}
}
--- a/rust/hedgewars-server/src/server/handlers/common.rs Tue Apr 09 23:03:12 2019 +0300
+++ b/rust/hedgewars-server/src/server/handlers/common.rs Wed Apr 10 01:13:29 2019 +0300
@@ -33,60 +33,33 @@
}
}
-pub fn process_login(server: &mut HWServer, response: &mut Response) {
+pub fn join_lobby(server: &mut HWServer, response: &mut Response) {
let client_id = response.client_id();
- let nick = server.clients[client_id].nick.clone();
- let has_nick_clash = server
- .clients
- .iter()
- .any(|(id, c)| id != client_id && c.nick == nick);
+ let lobby_nicks: Vec<_> = server.collect_nicks(|(_, c)| c.room_id.is_none());
- let client = &mut server.clients[client_id];
+ let joined_msg = LobbyJoined(lobby_nicks);
- if !client.is_checker() && has_nick_clash {
- if client.protocol_number < 38 {
- remove_client(server, response, "Nickname is already in use".to_string());
- } else {
- client.nick.clear();
- response.add(Notice("NickAlreadyInUse".to_string()).send_self());
- }
- } else {
- server.clients[client_id].room_id = None;
+ let everyone_msg = LobbyJoined(vec![server.clients[client_id].nick.clone()]);
+ let flags_msg = ClientFlags(
+ "+i".to_string(),
+ server.collect_nicks(|(_, c)| c.room_id.is_some()),
+ );
+ let server_msg = ServerMessage("\u{1f994} is watching".to_string());
- let lobby_nicks: Vec<_> = server
- .clients
+ let rooms_msg = Rooms(
+ server
+ .rooms
.iter()
- .filter_map(|(_, c)| c.room_id.and(Some(c.nick.clone())))
- .collect();
- let joined_msg = LobbyJoined(lobby_nicks);
+ .flat_map(|(_, r)| r.info(r.master_id.map(|id| &server.clients[id])))
+ .collect(),
+ );
- let everyone_msg = LobbyJoined(vec![server.clients[client_id].nick.clone()]);
- let flags_msg = ClientFlags(
- "+i".to_string(),
- server
- .clients
- .iter()
- .filter(|(_, c)| c.room_id.is_some())
- .map(|(_, c)| c.nick.clone())
- .collect(),
- );
- let server_msg = ServerMessage("\u{1f994} is watching".to_string());
-
- let rooms_msg = Rooms(
- server
- .rooms
- .iter()
- .flat_map(|(_, r)| r.info(r.master_id.map(|id| &server.clients[id])))
- .collect(),
- );
-
- response.add(everyone_msg.send_all().but_self());
- response.add(joined_msg.send_self());
- response.add(flags_msg.send_self());
- response.add(server_msg.send_self());
- response.add(rooms_msg.send_self());
- }
+ response.add(everyone_msg.send_all().but_self());
+ response.add(joined_msg.send_self());
+ response.add(flags_msg.send_self());
+ response.add(server_msg.send_self());
+ response.add(rooms_msg.send_self());
}
pub fn remove_teams(
@@ -192,7 +165,7 @@
remove_client_from_room(client, room, response, msg);
if !room.is_fixed() && room.master_id == None {
- if let Some(new_master_id) = server.room_clients(room_id).first().cloned() {
+ if let Some(new_master_id) = server.collect_room_clients(room_id).first().cloned() {
let new_master_nick = server.clients[new_master_id].nick.clone();
let room = &mut server.rooms[room_id];
room.master_id = Some(new_master_id);
--- a/rust/hedgewars-server/src/server/handlers/inroom.rs Tue Apr 09 23:03:12 2019 +0300
+++ b/rust/hedgewars-server/src/server/handlers/inroom.rs Wed Apr 10 01:13:29 2019 +0300
@@ -337,10 +337,11 @@
SaveRoom(filename) => {
if client.is_admin() {
match room.get_saves() {
- Ok(contents) =>
- response.request_io(super::IoTask::SaveRoom {
- room_id, filename, contents
- }),
+ Ok(contents) => response.request_io(super::IoTask::SaveRoom {
+ room_id,
+ filename,
+ contents,
+ }),
Err(e) => {
warn!("Error while serializing the room configs: {}", e);
response.add(
@@ -353,10 +354,7 @@
}
LoadRoom(filename) => {
if client.is_admin() {
- response.request_io(super::IoTask::LoadRoom {
- room_id,
- filename
- });
+ response.request_io(super::IoTask::LoadRoom { room_id, filename });
}
}
Delete(name) => {
@@ -420,7 +418,7 @@
match error {
None => {
let msg = voting_description(&kind);
- let voting = Voting::new(kind, server.room_clients(client_id));
+ let voting = Voting::new(kind, server.collect_room_clients(client_id));
let room = &mut server.rooms[room_id];
room.voting = Some(voting);
response.add(server_chat(msg).send_all().in_room(room_id));
--- a/rust/hedgewars-server/src/server/handlers/loggingin.rs Tue Apr 09 23:03:12 2019 +0300
+++ b/rust/hedgewars-server/src/server/handlers/loggingin.rs Wed Apr 10 01:13:29 2019 +0300
@@ -1,6 +1,8 @@
use mio;
use crate::protocol::messages::HWProtocolMessage::LoadRoom;
+use crate::server::client::HWClient;
+use crate::server::core::HWServer;
use crate::{
protocol::messages::{HWProtocolMessage, HWServerMessage::*},
server::{
@@ -23,21 +25,42 @@
Exit,
}
-fn completion_result(client: &HWAnteClient, response: &mut super::Response) -> LoginResult {
- #[cfg(feature = "official-server")]
- {
- response.add(AskPassword(client.server_salt.clone()).send_self());
- LoginResult::Unchanged
- }
+fn completion_result<'a, I>(
+ mut other_clients: I,
+ client: &mut HWAnteClient,
+ response: &mut super::Response,
+) -> LoginResult
+where
+ I: Iterator<Item = (ClientId, &'a HWClient)>,
+{
+ let has_nick_clash =
+ other_clients.any(|(_, c)| !c.is_checker() && c.nick == *client.nick.as_ref().unwrap());
- #[cfg(not(feature = "official-server"))]
- {
- LoginResult::Complete
+ 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(
- anteroom: &mut HWAnteroom,
+ server: &mut HWServer,
client_id: ClientId,
response: &mut super::Response,
message: HWProtocolMessage,
@@ -48,9 +71,9 @@
LoginResult::Exit
}
HWProtocolMessage::Nick(nick) => {
- let client = &mut anteroom.clients[client_id];
+ let client = &mut server.anteroom.clients[client_id];
debug!("{} {}", nick, is_name_illegal(&nick));
- if !client.nick.is_some() {
+ if client.nick.is_some() {
response.add(Error("Nickname already provided.".to_string()).send_self());
LoginResult::Unchanged
} else if is_name_illegal(&nick) {
@@ -61,14 +84,14 @@
response.add(Nick(nick).send_self());
if client.protocol_number.is_some() {
- completion_result(&client, response)
+ completion_result(server.clients.iter(), client, response)
} else {
LoginResult::Unchanged
}
}
}
HWProtocolMessage::Proto(proto) => {
- let client = &mut anteroom.clients[client_id];
+ 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
@@ -80,7 +103,7 @@
response.add(Proto(proto).send_self());
if client.nick.is_some() {
- completion_result(&client, response)
+ completion_result(server.clients.iter(), client, response)
} else {
LoginResult::Unchanged
}
@@ -88,7 +111,7 @@
}
#[cfg(feature = "official-server")]
HWProtocolMessage::Password(hash, salt) => {
- let client = &anteroom.clients[client_id];
+ 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 {
@@ -104,11 +127,16 @@
}
#[cfg(feature = "official-server")]
HWProtocolMessage::Checker(protocol, nick, password) => {
- let client = &mut anteroom.clients[client_id];
- client.protocol_number = NonZeroU16::new(protocol);
- client.nick = Some(nick);
- //client.set_is_checker(true);
- LoginResult::Complete
+ 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");
--- a/rust/hedgewars-server/src/server/io.rs Tue Apr 09 23:03:12 2019 +0300
+++ b/rust/hedgewars-server/src/server/io.rs Wed Apr 10 01:13:29 2019 +0300
@@ -9,9 +9,9 @@
database::Database,
handlers::{IoResult, IoTask},
};
+use log::*;
use mio::{Evented, Poll, PollOpt};
use mio_extras::channel;
-use log::*;
pub type RequestId = u32;
@@ -45,17 +45,19 @@
&client_salt,
&server_salt,
) {
- Ok(account) => {
- IoResult::Account(account)
- }
+ Ok(account) => IoResult::Account(account),
Err(..) => {
warn!("Unable to get account data: {}", 0);
IoResult::Account(None)
}
}
- },
+ }
- IoTask::SaveRoom { room_id, filename, contents} => {
+ IoTask::SaveRoom {
+ room_id,
+ filename,
+ contents,
+ } => {
let result = match save_file(&filename, &contents) {
Ok(()) => true,
Err(e) => {
@@ -64,12 +66,12 @@
filename, e
);
false
- }
+ }
};
IoResult::SaveRoom(room_id, result)
- },
+ }
- IoTask::LoadRoom {room_id, filename} => {
+ IoTask::LoadRoom { room_id, filename } => {
let result = match load_file(&filename) {
Ok(contents) => Some(contents),
Err(e) => {
@@ -118,4 +120,4 @@
let mut result = String::new();
reader.read_to_string(&mut result)?;
Ok(result)
-}
\ No newline at end of file
+}
--- a/rust/hedgewars-server/src/utils.rs Tue Apr 09 23:03:12 2019 +0300
+++ b/rust/hedgewars-server/src/utils.rs Wed Apr 10 01:13:29 2019 +0300
@@ -9,6 +9,7 @@
pub fn is_name_illegal(name: &str) -> bool {
name.len() > 40
|| name.trim().is_empty()
+ || name.trim() != name
|| name
.chars()
.any(|c| "$()*+?[]^{|}\x7F".contains(c) || '\x00' <= c && c <= '\x1F')