implement server vars
authoralfadur
Wed, 10 Apr 2019 18:12:30 +0300
changeset 14788 b3adc030104b
parent 14787 50fcef24003f
child 14789 8390d5e4e39c
implement server vars
rust/hedgewars-server/src/main.rs
rust/hedgewars-server/src/protocol/messages.rs
rust/hedgewars-server/src/protocol/parser.rs
rust/hedgewars-server/src/protocol/test.rs
rust/hedgewars-server/src/server/core.rs
rust/hedgewars-server/src/server/coretypes.rs
rust/hedgewars-server/src/server/handlers.rs
rust/hedgewars-server/src/server/handlers/common.rs
rust/hedgewars-server/src/server/handlers/lobby.rs
rust/hedgewars-server/src/utils.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();
--- 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<String>),
     ChatMsg { nick: String, msg: String },
@@ -142,6 +142,7 @@
     RoundFinished,
 
     ServerMessage(String),
+    ServerVars(Vec<String>),
     Notice(String),
     Warning(String),
     Error(String),
@@ -159,6 +160,16 @@
     }
 }
 
+impl ServerVar {
+    pub fn to_protocol(&self) -> Vec<String> {
+        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<String>) {
         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],
--- 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<HWProtocolMessage> {
+    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<HWProtocolMessage> {
     alt((
         |i| {
@@ -527,6 +550,7 @@
                     single_arg_message,
                     cmd_message,
                     config_message,
+                    server_var_message,
                     complex_message,
                 )),
                 end_of_message,
--- 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<TeamInfo>;
 }
 
+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<ServerVar>;
+}
+
 pub fn gen_proto_msg() -> BoxedStrategy<HWProtocolMessage> 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(),
--- 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<HWClient>,
     pub rooms: Slab<HWRoom>,
     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,
--- 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)]
--- 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) {
--- 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;
         }
--- 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());
         }
--- 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);