# HG changeset patch # User alfadur # Date 1554848009 -10800 # Node ID 01f8ab45f806155a79025008074df031774c9605 # Parent 65861ba8b4e809d9dc5cdaaae51652c214d608c1 fix lobby joining diff -r 65861ba8b4e8 -r 01f8ab45f806 rust/hedgewars-server/src/server/core.rs --- 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, pub protocol_number: Option, 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(&self, f: F) -> Vec + pub fn collect_clients(&self, f: F) -> Vec where F: Fn(&(usize, &HWClient)) -> bool, { self.clients.iter().filter(f).map(|(_, c)| c.id).collect() } - pub fn lobby_clients(&self) -> Vec { - self.select_clients(|(_, c)| c.room_id == None) + pub fn collect_nicks(&self, f: F) -> Vec + 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 { - self.select_clients(|(_, c)| c.room_id == Some(room_id)) + pub fn collect_lobby_clients(&self) -> Vec { + self.collect_clients(|(_, c)| c.room_id == None) + } + + pub fn collect_room_clients(&self, room_id: RoomId) -> Vec { + self.collect_clients(|(_, c)| c.room_id == Some(room_id)) } pub fn protocol_clients(&self, protocol: u16) -> Vec { - 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 { 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) } } diff -r 65861ba8b4e8 -r 01f8ab45f806 rust/hedgewars-server/src/server/handlers.rs --- 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), SaveRoom(RoomId, bool), - LoadRoom(RoomId, Option) + LoadRoom(RoomId, Option), } 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()); } } } diff -r 65861ba8b4e8 -r 01f8ab45f806 rust/hedgewars-server/src/server/handlers/common.rs --- 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); diff -r 65861ba8b4e8 -r 01f8ab45f806 rust/hedgewars-server/src/server/handlers/inroom.rs --- 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)); diff -r 65861ba8b4e8 -r 01f8ab45f806 rust/hedgewars-server/src/server/handlers/loggingin.rs --- 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, +{ + 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"); diff -r 65861ba8b4e8 -r 01f8ab45f806 rust/hedgewars-server/src/server/io.rs --- 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 +} diff -r 65861ba8b4e8 -r 01f8ab45f806 rust/hedgewars-server/src/utils.rs --- 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')