# HG changeset patch # User alfadur # Date 1577113735 -10800 # Node ID fd3a20e9d095d0ce0bf76e4d8fd1e075cdf5c71b # Parent b3157d218ae23432bb6770656329da28a1cbd045 move the anteroom out of the server diff -r b3157d218ae2 -r fd3a20e9d095 rust/hedgewars-server/src/core.rs --- a/rust/hedgewars-server/src/core.rs Sat Dec 21 23:33:50 2019 +0300 +++ b/rust/hedgewars-server/src/core.rs Mon Dec 23 18:08:55 2019 +0300 @@ -1,3 +1,4 @@ +pub mod anteroom; pub mod client; pub mod indexslab; pub mod room; diff -r b3157d218ae2 -r fd3a20e9d095 rust/hedgewars-server/src/core/server.rs --- a/rust/hedgewars-server/src/core/server.rs Sat Dec 21 23:33:50 2019 +0300 +++ b/rust/hedgewars-server/src/core/server.rs Mon Dec 23 18:08:55 2019 +0300 @@ -1,4 +1,5 @@ use super::{ + anteroom::HwAnteroomClient, client::HwClient, indexslab::IndexSlab, room::HwRoom, @@ -8,10 +9,9 @@ use bitflags::_core::hint::unreachable_unchecked; use bitflags::*; -use chrono::{offset, DateTime}; use log::*; use slab::Slab; -use std::{borrow::BorrowMut, collections::HashSet, iter, mem::replace, num::NonZeroU16}; +use std::{borrow::BorrowMut, collections::HashSet, iter, mem::replace}; #[derive(Debug)] pub enum CreateRoomError { @@ -106,91 +106,6 @@ #[derive(Debug)] pub struct AccessError(); -pub struct HwAnteClient { - pub nick: Option, - pub protocol_number: Option, - pub server_salt: String, - pub is_checker: bool, - pub is_local_admin: bool, - pub is_registered: bool, - pub is_admin: bool, - pub is_contributor: bool, -} - -struct Ipv4AddrRange { - min: [u8; 4], - max: [u8; 4], -} - -impl Ipv4AddrRange { - fn contains(&self, addr: [u8; 4]) -> bool { - (0..4).all(|i| self.min[i] <= addr[i] && addr[i] <= self.max[i]) - } -} - -struct BanCollection { - ban_ips: Vec, - ban_timeouts: Vec>, - ban_reasons: Vec, -} - -impl BanCollection { - fn new() -> Self { - Self { - ban_ips: vec![], - ban_timeouts: vec![], - ban_reasons: vec![], - } - } - - fn find(&self, addr: [u8; 4]) -> Option { - let time = offset::Utc::now(); - self.ban_ips - .iter() - .enumerate() - .find(|(i, r)| r.contains(addr) && time < self.ban_timeouts[*i]) - .map(|(i, _)| self.ban_reasons[i].clone()) - } -} - -pub struct HwAnteroom { - pub clients: IndexSlab, - bans: BanCollection, -} - -impl HwAnteroom { - pub fn new(clients_limit: usize) -> Self { - let clients = IndexSlab::with_capacity(clients_limit); - HwAnteroom { - clients, - bans: BanCollection::new(), - } - } - - pub fn find_ip_ban(&self, addr: [u8; 4]) -> Option { - self.bans.find(addr) - } - - pub fn add_client(&mut self, client_id: ClientId, salt: String, is_local_admin: bool) { - let client = HwAnteClient { - nick: None, - protocol_number: None, - server_salt: salt, - is_checker: false, - is_local_admin, - is_registered: false, - is_admin: false, - is_contributor: false, - }; - self.clients.insert(client_id, client); - } - - pub fn remove_client(&mut self, client_id: ClientId) -> Option { - let client = self.clients.remove(client_id); - client - } -} - pub struct ServerGreetings { pub for_latest_protocol: String, pub for_old_protocols: String, @@ -212,9 +127,8 @@ } pub struct HwServer { - pub clients: IndexSlab, + clients: IndexSlab, pub rooms: Slab, - pub anteroom: HwAnteroom, pub latest_protocol: u16, pub flags: ServerFlags, pub greetings: ServerGreetings, @@ -227,7 +141,6 @@ Self { clients, rooms, - anteroom: HwAnteroom::new(clients_limit), greetings: ServerGreetings::new(), latest_protocol: 58, flags: ServerFlags::empty(), @@ -286,7 +199,7 @@ .unwrap_or(false) } - pub fn add_client(&mut self, client_id: ClientId, data: HwAnteClient) { + pub fn add_client(&mut self, client_id: ClientId, data: HwAnteroomClient) { 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); diff -r b3157d218ae2 -r fd3a20e9d095 rust/hedgewars-server/src/handlers.rs --- a/rust/hedgewars-server/src/handlers.rs Sat Dec 21 23:33:50 2019 +0300 +++ b/rust/hedgewars-server/src/handlers.rs Mon Dec 23 18:08:55 2019 +0300 @@ -12,6 +12,7 @@ }; use crate::{ core::{ + anteroom::HwAnteroom, room::RoomSave, server::HwServer, types::{ClientId, GameCfg, Replay, RoomId, TeamInfo}, @@ -81,6 +82,20 @@ } } +pub struct ServerState { + pub server: HwServer, + pub anteroom: HwAnteroom, +} + +impl ServerState { + pub fn new(clients_limit: usize, rooms_limit: usize) -> Self { + Self { + server: HwServer::new(clients_limit, rooms_limit), + anteroom: HwAnteroom::new(clients_limit), + } + } +} + #[derive(Debug)] pub struct AccountInfo { pub is_registered: bool, @@ -236,7 +251,7 @@ } pub fn handle( - server: &mut HwServer, + state: &mut ServerState, client_id: ClientId, response: &mut Response, message: HwProtocolMessage, @@ -245,35 +260,39 @@ HwProtocolMessage::Ping => response.add(Pong.send_self()), HwProtocolMessage::Pong => (), _ => { - if server.anteroom.clients.contains(client_id) { - match inanteroom::handle(server, client_id, response, message) { + if state.anteroom.clients.contains(client_id) { + match inanteroom::handle(state, 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::get_lobby_join_data(server, response); + 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); } } LoginResult::Exit => { - server.anteroom.remove_client(client_id); + state.anteroom.remove_client(client_id); response.remove_client(client_id); } } - } else if server.has_client(client_id) { + } else if state.server.has_client(client_id) { match message { HwProtocolMessage::Quit(Some(msg)) => { - common::remove_client(server, response, "User quit: ".to_string() + &msg); + common::remove_client( + &mut state.server, + response, + "User quit: ".to_string() + &msg, + ); } HwProtocolMessage::Quit(None) => { - common::remove_client(server, response, "User quit".to_string()); + common::remove_client(&mut state.server, response, "User quit".to_string()); } HwProtocolMessage::Info(nick) => { - if let Some(client) = server.find_client(&nick) { + if let Some(client) = state.server.find_client(&nick) { let admin_sign = if client.is_admin() { "@" } else { "" }; let master_sign = if client.is_master() { "+" } else { "" }; let room_info = match client.room_id { Some(room_id) => { - let room = server.room(room_id); + let room = state.server.room(room_id); let status = match room.game_info { Some(_) if client.teams_in_game == 0 => "(spectating)", Some(_) => "(playing)", @@ -299,11 +318,13 @@ } } HwProtocolMessage::ToggleServerRegisteredOnly => { - if !server.is_admin(client_id) { + if !state.server.is_admin(client_id) { response.warn(ACCESS_DENIED); } else { - server.set_is_registered_only(!server.is_registered_only()); - let msg = if server.is_registered_only() { + state + .server + .set_is_registered_only(!state.server.is_registered_only()); + let msg = if state.server.is_registered_only() { REGISTERED_ONLY_ENABLED } else { REGISTERED_ONLY_DISABLED @@ -312,14 +333,14 @@ } } HwProtocolMessage::Global(msg) => { - if !server.is_admin(client_id) { + if !state.server.is_admin(client_id) { response.warn(ACCESS_DENIED); } else { response.add(global_chat(msg).send_all()) } } HwProtocolMessage::SuperPower => { - if server.enable_super_power(client_id) { + if state.server.enable_super_power(client_id) { response.add(server_chat(SUPER_POWER.to_string()).send_self()) } else { response.warn(ACCESS_DENIED); @@ -336,10 +357,10 @@ response.warn(REPLAY_NOT_SUPPORTED); } } - _ => match server.client(client_id).room_id { - None => inlobby::handle(server, client_id, response, message), + _ => match state.server.client(client_id).room_id { + None => inlobby::handle(&mut state.server, client_id, response, message), Some(room_id) => { - inroom::handle(server, client_id, response, room_id, message) + inroom::handle(&mut state.server, client_id, response, room_id, message) } }, } @@ -349,7 +370,7 @@ } pub fn handle_client_accept( - server: &mut HwServer, + state: &mut ServerState, client_id: ClientId, response: &mut Response, addr: [u8; 4], @@ -357,7 +378,7 @@ ) { let ban_reason = Some(addr) .filter(|_| !is_local) - .and_then(|a| server.anteroom.find_ip_ban(a)); + .and_then(|a| state.anteroom.find_ip_ban(a)); if let Some(reason) = ban_reason { response.add(HwServerMessage::Bye(reason).send_self()); response.remove_client(client_id); @@ -365,7 +386,7 @@ let mut salt = [0u8; 18]; thread_rng().fill_bytes(&mut salt); - server + state .anteroom .add_client(client_id, encode(&salt), is_local); @@ -373,39 +394,39 @@ } } -pub fn handle_client_loss(server: &mut HwServer, client_id: ClientId, response: &mut Response) { - if server.anteroom.remove_client(client_id).is_none() { - common::remove_client(server, response, "Connection reset".to_string()); +pub fn handle_client_loss(state: &mut ServerState, client_id: ClientId, response: &mut Response) { + if state.anteroom.remove_client(client_id).is_none() { + common::remove_client(&mut state.server, response, "Connection reset".to_string()); } } pub fn handle_io_result( - server: &mut HwServer, + state: &mut ServerState, client_id: ClientId, response: &mut Response, io_result: IoResult, ) { match io_result { IoResult::AccountRegistered(is_registered) => { - if !is_registered && server.is_registered_only() { + if !is_registered && state.server.is_registered_only() { response.add(Bye(REGISTRATION_REQUIRED.to_string()).send_self()); response.remove_client(client_id); } else if is_registered { - let salt = server.anteroom.clients[client_id].server_salt.clone(); + let salt = state.anteroom.clients[client_id].server_salt.clone(); response.add(AskPassword(salt).send_self()); - } else if let Some(client) = server.anteroom.remove_client(client_id) { - server.add_client(client_id, client); - common::get_lobby_join_data(server, response); + } 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(Some(info)) => { response.add(ServerAuth(format!("{:x}", info.server_hash)).send_self()); - if let Some(mut client) = server.anteroom.remove_client(client_id) { + if let Some(mut client) = state.anteroom.remove_client(client_id) { client.is_registered = info.is_registered; client.is_admin = info.is_admin; client.is_contributor = info.is_contributor; - server.add_client(client_id, client); - common::get_lobby_join_data(server, response); + state.server.add_client(client_id, client); + common::get_lobby_join_data(&state.server, response); } } IoResult::Account(None) => { @@ -413,7 +434,7 @@ response.remove_client(client_id); } IoResult::Replay(Some(replay)) => { - let client = server.client(client_id); + let client = state.server.client(client_id); let protocol = client.protocol_number; let start_msg = if protocol < 58 { RoomJoined(vec![client.nick.clone()]) @@ -441,7 +462,7 @@ response.warn(ROOM_CONFIG_SAVE_FAILED); } IoResult::LoadRoom(room_id, Some(contents)) => { - if let Some(ref mut room) = server.rooms.get_mut(room_id) { + if let Some(ref mut room) = state.server.rooms.get_mut(room_id) { match room.set_saves(&contents) { Ok(_) => response.add(server_chat(ROOM_CONFIG_LOADED.to_string()).send_self()), Err(e) => { diff -r b3157d218ae2 -r fd3a20e9d095 rust/hedgewars-server/src/handlers/inanteroom.rs --- a/rust/hedgewars-server/src/handlers/inanteroom.rs Sat Dec 21 23:33:50 2019 +0300 +++ b/rust/hedgewars-server/src/handlers/inanteroom.rs Mon Dec 23 18:08:55 2019 +0300 @@ -2,8 +2,9 @@ use crate::{ core::{ + anteroom::{HwAnteroom, HwAnteroomClient}, client::HwClient, - server::{HwAnteClient, HwAnteroom, HwServer}, + server::HwServer, types::ClientId, }, protocol::messages::{HwProtocolMessage, HwProtocolMessage::LoadRoom, HwServerMessage::*}, @@ -26,14 +27,14 @@ fn completion_result<'a, I>( mut other_clients: I, - client: &mut HwAnteClient, + client: &mut HwAnteroomClient, response: &mut super::Response, ) -> LoginResult where - I: Iterator, + I: Iterator, { let has_nick_clash = - other_clients.any(|(_, c)| !c.is_checker() && c.nick == *client.nick.as_ref().unwrap()); + 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 { @@ -61,7 +62,7 @@ } pub fn handle( - server: &mut HwServer, + server_state: &mut super::ServerState, client_id: ClientId, response: &mut super::Response, message: HwProtocolMessage, @@ -72,7 +73,7 @@ LoginResult::Exit } HwProtocolMessage::Nick(nick) => { - let client = &mut server.anteroom.clients[client_id]; + let client = &mut server_state.anteroom.clients[client_id]; if client.nick.is_some() { response.add(Error("Nickname already provided.".to_string()).send_self()); @@ -85,14 +86,14 @@ response.add(Nick(nick).send_self()); if client.protocol_number.is_some() { - completion_result(server.clients.iter(), client, response) + completion_result(server_state.server.iter_clients(), client, response) } else { LoginResult::Unchanged } } } HwProtocolMessage::Proto(proto) => { - let client = &mut server.anteroom.clients[client_id]; + 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()); LoginResult::Unchanged @@ -104,7 +105,7 @@ response.add(Proto(proto).send_self()); if client.nick.is_some() { - completion_result(server.clients.iter(), client, response) + completion_result(server_state.server.iter_clients(), client, response) } else { LoginResult::Unchanged } @@ -112,7 +113,7 @@ } #[cfg(feature = "official-server")] HwProtocolMessage::Password(hash, salt) => { - let client = &server.anteroom.clients[client_id]; + let client = &server_state.anteroom.clients[client_id]; if let (Some(nick), Some(protocol)) = (client.nick.as_ref(), client.protocol_number) { response.request_io(super::IoTask::GetAccount { @@ -128,7 +129,7 @@ } #[cfg(feature = "official-server")] HwProtocolMessage::Checker(protocol, nick, password) => { - let client = &mut server.anteroom.clients[client_id]; + let client = &mut server_state.anteroom.clients[client_id]; if protocol == 0 { response.add(Error("Bad number.".to_string()).send_self()); LoginResult::Unchanged diff -r b3157d218ae2 -r fd3a20e9d095 rust/hedgewars-server/src/server/network.rs --- a/rust/hedgewars-server/src/server/network.rs Sat Dec 21 23:33:50 2019 +0300 +++ b/rust/hedgewars-server/src/server/network.rs Mon Dec 23 18:08:55 2019 +0300 @@ -18,9 +18,9 @@ use slab::Slab; use crate::{ - core::{server::HwServer, types::ClientId}, + core::types::ClientId, handlers, - handlers::{IoResult, IoTask}, + handlers::{IoResult, IoTask, ServerState}, protocol::{messages::HwServerMessage::Redirect, messages::*, ProtocolDecoder}, utils, }; @@ -317,7 +317,7 @@ pub struct NetworkLayer { listener: TcpListener, - server: HwServer, + server_state: ServerState, clients: Slab, pending: HashSet<(ClientId, NetworkClientState)>, pending_cache: Vec<(ClientId, NetworkClientState)>, @@ -425,7 +425,7 @@ } debug!("{} pending server messages", response.len()); - let output = response.extract_messages(&mut self.server); + let output = response.extract_messages(&mut self.server_state.server); for (clients, message) in output { debug!("Message {:?} to {:?}", message, clients); let msg_string = message.to_raw_protocol(); @@ -525,7 +525,7 @@ if let IpAddr::V4(addr) = self.clients[client_id].peer_addr.ip() { handlers::handle_client_accept( - &mut self.server, + &mut self.server_state, client_id, &mut response, addr.octets(), @@ -594,7 +594,7 @@ Ok((messages, state)) => { for message in messages { debug!("Handling message {:?} for client {}", message, client_id); - handlers::handle(&mut self.server, client_id, &mut response, message); + handlers::handle(&mut self.server_state, client_id, &mut response, message); } match state { NetworkClientState::NeedsRead => { @@ -649,7 +649,7 @@ if !pending_close { let mut response = handlers::Response::new(client_id); - handlers::handle_client_loss(&mut self.server, client_id, &mut response); + handlers::handle_client_loss(&mut self.server_state, client_id, &mut response); self.handle_response(response, poll); } @@ -730,7 +730,8 @@ } pub fn build(self) -> NetworkLayer { - let server = HwServer::new(self.clients_capacity, self.rooms_capacity); + let server_state = ServerState::new(self.clients_capacity, self.rooms_capacity); + let clients = Slab::with_capacity(self.clients_capacity); let pending = HashSet::with_capacity(2 * self.clients_capacity); let pending_cache = Vec::with_capacity(2 * self.clients_capacity); @@ -738,7 +739,7 @@ NetworkLayer { listener: self.listener.expect("No listener provided"), - server, + server_state, clients, pending, pending_cache,