# HG changeset patch # User alfadur # Date 1554909150 -10800 # Node ID b3adc030104b557f3fa5783ee8b5be6c498077d7 # Parent 50fcef24003f338a6a04ff709e412943f3570d3b implement server vars diff -r 50fcef24003f -r b3adc030104b rust/hedgewars-server/src/main.rs --- a/rust/hedgewars-server/src/main.rs Wed Apr 10 16:14:33 2019 +0300 +++ b/rust/hedgewars-server/src/main.rs Wed Apr 10 18:12:30 2019 +0300 @@ -15,10 +15,7 @@ fn main() { env_logger::init(); - info!( - "Hedgewars game server, protocol {}", - utils::PROTOCOL_VERSION - ); + info!("Hedgewars game server, protocol {}", utils::SERVER_VERSION); let address = "0.0.0.0:46631".parse().unwrap(); let listener = TcpListener::bind(&address).unwrap(); diff -r 50fcef24003f -r b3adc030104b rust/hedgewars-server/src/protocol/messages.rs --- a/rust/hedgewars-server/src/protocol/messages.rs Wed Apr 10 16:14:33 2019 +0300 +++ b/rust/hedgewars-server/src/protocol/messages.rs Wed Apr 10 18:12:30 2019 +0300 @@ -118,8 +118,8 @@ Nick(String), Proto(u16), AskPassword(String), + ServerAuth(String), - ServerAuth(String), LobbyLeft(String, String), LobbyJoined(Vec), ChatMsg { nick: String, msg: String }, @@ -142,6 +142,7 @@ RoundFinished, ServerMessage(String), + ServerVars(Vec), Notice(String), Warning(String), Error(String), @@ -159,6 +160,16 @@ } } +impl ServerVar { + pub fn to_protocol(&self) -> Vec { + match self { + ServerVar::MOTDNew(s) => vec!["MOTD_NEW".to_string(), s.clone()], + ServerVar::MOTDOld(s) => vec!["MOTD_OLD".to_string(), s.clone()], + ServerVar::LatestProto(n) => vec!["LATEST_PROTO".to_string(), n.to_string()], + } + } +} + impl GameCfg { pub fn to_protocol(&self) -> (String, Vec) { use crate::server::coretypes::GameCfg::*; @@ -251,7 +262,7 @@ BanNick(nick, reason, time) => msg!("BAN_NICK", nick, reason, time), BanList => msg!["BANLIST"], Unban(name) => msg!["UNBAN", name], - //SetServerVar(ServerVar), ??? + SetServerVar(var) => construct_message(&["SET_SERVER_VAR"], &var.to_protocol()), GetServerVar => msg!["GET_SERVER_VAR"], RestartServer => msg!["CMD", "RESTART_SERVER YES"], Stats => msg!["CMD", "STATS"], @@ -351,6 +362,7 @@ RoundFinished => msg!["ROUND_FINISHED"], ChatMsg { nick, msg } => msg!["CHAT", nick, msg], ServerMessage(msg) => msg!["SERVER_MESSAGE", msg], + ServerVars(vars) => construct_message(&["SERVER_VARS"], &vars), Notice(msg) => msg!["NOTICE", msg], Warning(msg) => msg!["WARNING", msg], Error(msg) => msg!["ERROR", msg], diff -r 50fcef24003f -r b3adc030104b rust/hedgewars-server/src/protocol/parser.rs --- a/rust/hedgewars-server/src/protocol/parser.rs Wed Apr 10 16:14:33 2019 +0300 +++ b/rust/hedgewars-server/src/protocol/parser.rs Wed Apr 10 18:12:30 2019 +0300 @@ -15,7 +15,9 @@ }; use super::messages::{HWProtocolMessage, HWProtocolMessage::*}; -use crate::server::coretypes::{GameCfg, HedgehogInfo, TeamInfo, VoteType, MAX_HEDGEHOGS_PER_TEAM}; +use crate::server::coretypes::{ + GameCfg, HedgehogInfo, ServerVar, TeamInfo, VoteType, MAX_HEDGEHOGS_PER_TEAM, +}; #[derive(Debug, PartialEq)] pub struct HWProtocolError {} @@ -369,6 +371,27 @@ Ok((i, Cfg(cfg))) } +fn server_var_message(input: &[u8]) -> HWResult { + precededc( + input, + hw_tag("SET_SERVER_VAR\n"), + alt(( + |i| { + precededc(i, hw_tag("MOTD_NEW\n"), a_line) + .map(|(i, s)| (i, SetServerVar(ServerVar::MOTDNew(s)))) + }, + |i| { + precededc(i, hw_tag("MOTD_OLD\n"), a_line) + .map(|(i, s)| (i, SetServerVar(ServerVar::MOTDOld(s)))) + }, + |i| { + precededc(i, hw_tag("LATEST_PROTO\n"), u16_line) + .map(|(i, n)| (i, SetServerVar(ServerVar::LatestProto(n)))) + }, + )), + ) +} + fn complex_message(input: &[u8]) -> HWResult { alt(( |i| { @@ -527,6 +550,7 @@ single_arg_message, cmd_message, config_message, + server_var_message, complex_message, )), end_of_message, diff -r 50fcef24003f -r b3adc030104b rust/hedgewars-server/src/protocol/test.rs --- a/rust/hedgewars-server/src/protocol/test.rs Wed Apr 10 16:14:33 2019 +0300 +++ b/rust/hedgewars-server/src/protocol/test.rs Wed Apr 10 18:12:30 2019 +0300 @@ -4,7 +4,7 @@ test_runner::{Reason, TestRunner}, }; -use crate::server::coretypes::{GameCfg, HedgehogInfo, TeamInfo}; +use crate::server::coretypes::{GameCfg, HedgehogInfo, ServerVar, ServerVar::*, TeamInfo}; use super::messages::{HWProtocolMessage, HWProtocolMessage::*}; @@ -146,6 +146,25 @@ type Strategy = BoxedStrategy; } +impl Arbitrary for ServerVar { + type Parameters = (); + + fn arbitrary_with(args: Self::Parameters) -> Self::Strategy { + (0..2) + .no_shrink() + .prop_flat_map(|i| { + proto_msg_match!(i, def = ServerVar::LatestProto(0), + 0 => MOTDNew(Ascii), + 1 => MOTDOld(Ascii), + 2 => LatestProto(u16) + ) + }) + .boxed() + } + + type Strategy = BoxedStrategy; +} + pub fn gen_proto_msg() -> BoxedStrategy where { let res = (0..58).no_shrink().prop_flat_map(|i| { proto_msg_match!(i, def = Malformed, @@ -174,7 +193,7 @@ 22 => BanNick(Ascii, Ascii, u32), 23 => BanList(), 24 => Unban(Ascii), - //25 => SetServerVar(ServerVar), + 25 => SetServerVar(ServerVar), 26 => GetServerVar(), 27 => RestartServer(), 28 => Stats(), diff -r 50fcef24003f -r b3adc030104b rust/hedgewars-server/src/server/core.rs --- a/rust/hedgewars-server/src/server/core.rs Wed Apr 10 16:14:33 2019 +0300 +++ b/rust/hedgewars-server/src/server/core.rs Wed Apr 10 18:12:30 2019 +0300 @@ -6,6 +6,7 @@ }; use crate::utils; +use crate::protocol::messages::HWProtocolMessage::Greeting; use log::*; use slab; use std::{borrow::BorrowMut, iter, num::NonZeroU16}; @@ -45,10 +46,26 @@ } } +pub struct ServerGreetings { + pub for_latest_protocol: String, + pub for_old_protocols: String, +} + +impl ServerGreetings { + fn new() -> Self { + Self { + for_latest_protocol: "\u{1f994} is watching".to_string(), + for_old_protocols: "\u{1f994} is watching".to_string(), + } + } +} + pub struct HWServer { pub clients: IndexSlab, pub rooms: Slab, pub anteroom: HWAnteroom, + pub latest_protocol: u16, + pub greetings: ServerGreetings, } impl HWServer { @@ -59,6 +76,8 @@ clients, rooms, anteroom: HWAnteroom::new(clients_limit), + greetings: ServerGreetings::new(), + latest_protocol: 58, } } @@ -74,6 +93,14 @@ self.clients.remove(client_id); } + pub fn get_greetings(&self, client_id: ClientId) -> &str { + if self.clients[client_id].protocol_number < self.latest_protocol { + &self.greetings.for_old_protocols + } else { + &self.greetings.for_latest_protocol + } + } + #[inline] pub fn create_room( &mut self, diff -r 50fcef24003f -r b3adc030104b rust/hedgewars-server/src/server/coretypes.rs --- a/rust/hedgewars-server/src/server/coretypes.rs Wed Apr 10 16:14:33 2019 +0300 +++ b/rust/hedgewars-server/src/server/coretypes.rs Wed Apr 10 18:12:30 2019 +0300 @@ -7,7 +7,7 @@ pub enum ServerVar { MOTDNew(String), MOTDOld(String), - LatestProto(u32), + LatestProto(u16), } #[derive(PartialEq, Eq, Clone, Debug)] diff -r 50fcef24003f -r b3adc030104b rust/hedgewars-server/src/server/handlers.rs --- a/rust/hedgewars-server/src/server/handlers.rs Wed Apr 10 16:14:33 2019 +0300 +++ b/rust/hedgewars-server/src/server/handlers.rs Wed Apr 10 18:12:30 2019 +0300 @@ -233,7 +233,7 @@ server.anteroom.add_client(client_id, encode(&salt)); - response.add(HWServerMessage::Connected(utils::PROTOCOL_VERSION).send_self()); + response.add(HWServerMessage::Connected(utils::SERVER_VERSION).send_self()); } pub fn handle_client_loss(server: &mut HWServer, client_id: ClientId, response: &mut Response) { diff -r 50fcef24003f -r b3adc030104b rust/hedgewars-server/src/server/handlers/common.rs --- a/rust/hedgewars-server/src/server/handlers/common.rs Wed Apr 10 16:14:33 2019 +0300 +++ b/rust/hedgewars-server/src/server/handlers/common.rs Wed Apr 10 18:12:30 2019 +0300 @@ -47,7 +47,7 @@ add_flags(&[Flags::InRoom]), server.collect_nicks(|(_, c)| c.room_id.is_some()), ); - let server_msg = ServerMessage("\u{1f994} is watching".to_string()); + let server_msg = ServerMessage(server.get_greetings(client_id).to_string()); let rooms_msg = Rooms( server @@ -138,9 +138,12 @@ if client.is_master() && !room.is_fixed() { client.set_is_master(false); response.add( - ClientFlags(remove_flags(&[Flags::RoomMaster]), vec![client.nick.clone()]) - .send_all() - .in_room(room.id), + ClientFlags( + remove_flags(&[Flags::RoomMaster]), + vec![client.nick.clone()], + ) + .send_all() + .in_room(room.id), ); room.master_id = None; } diff -r 50fcef24003f -r b3adc030104b rust/hedgewars-server/src/server/handlers/lobby.rs --- a/rust/hedgewars-server/src/server/handlers/lobby.rs Wed Apr 10 16:14:33 2019 +0300 +++ b/rust/hedgewars-server/src/server/handlers/lobby.rs Wed Apr 10 18:12:30 2019 +0300 @@ -5,7 +5,10 @@ protocol::messages::{ add_flags, remove_flags, HWProtocolMessage, HWServerMessage::*, ProtocolFlags as Flags, }, - server::{core::HWServer, coretypes::ClientId}, + server::{ + core::HWServer, + coretypes::{ClientId, ServerVar}, + }, utils::is_name_illegal, }; use log::*; @@ -108,6 +111,32 @@ response.add(Warning("No such room.".to_string()).send_self()); } } + SetServerVar(var) => { + if !server.clients[client_id].is_admin() { + response.add(Warning("Access denied.".to_string()).send_self()); + } else { + match var { + ServerVar::MOTDNew(msg) => server.greetings.for_latest_protocol = msg, + ServerVar::MOTDOld(msg) => server.greetings.for_old_protocols = msg, + ServerVar::LatestProto(n) => server.latest_protocol = n, + } + } + } + GetServerVar => { + if !server.clients[client_id].is_admin() { + response.add(Warning("Access denied.".to_string()).send_self()); + } else { + let vars: Vec<_> = [ + ServerVar::MOTDNew(server.greetings.for_latest_protocol.clone()), + ServerVar::MOTDOld(server.greetings.for_old_protocols.clone()), + ServerVar::LatestProto(server.latest_protocol), + ] + .iter() + .flat_map(|v| v.to_protocol()) + .collect(); + response.add(ServerVars(vars).send_self()); + } + } Rnd(v) => { response.add(rnd_reply(&v).send_self()); } diff -r 50fcef24003f -r b3adc030104b rust/hedgewars-server/src/utils.rs --- a/rust/hedgewars-server/src/utils.rs Wed Apr 10 16:14:33 2019 +0300 +++ b/rust/hedgewars-server/src/utils.rs Wed Apr 10 18:12:30 2019 +0300 @@ -2,7 +2,7 @@ use mio; use std::iter::Iterator; -pub const PROTOCOL_VERSION: u32 = 3; +pub const SERVER_VERSION: u32 = 3; pub const SERVER_TOKEN: mio::Token = mio::Token(1_000_000_000); pub const IO_TOKEN: mio::Token = mio::Token(1_000_000_001);