fix lobby joining
authoralfadur
Wed, 10 Apr 2019 01:13:29 +0300
changeset 14786 01f8ab45f806
parent 14785 65861ba8b4e8
child 14787 50fcef24003f
fix lobby joining
rust/hedgewars-server/src/server/core.rs
rust/hedgewars-server/src/server/handlers.rs
rust/hedgewars-server/src/server/handlers/common.rs
rust/hedgewars-server/src/server/handlers/inroom.rs
rust/hedgewars-server/src/server/handlers/loggingin.rs
rust/hedgewars-server/src/server/io.rs
rust/hedgewars-server/src/utils.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<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')