--- a/rust/hedgewars-server/src/main.rs Sun Dec 16 00:09:20 2018 +0100
+++ b/rust/hedgewars-server/src/main.rs Sun Dec 16 00:12:29 2018 +0100
@@ -4,13 +4,13 @@
//use std::io::*;
//use rand::Rng;
//use std::cmp::Ordering;
+use log::*;
use mio::net::*;
use mio::*;
-use log::*;
+mod protocol;
+mod server;
mod utils;
-mod server;
-mod protocol;
use crate::server::network::NetworkLayer;
use std::time::Duration;
@@ -18,7 +18,10 @@
fn main() {
env_logger::init();
- info!("Hedgewars game server, protocol {}", utils::PROTOCOL_VERSION);
+ info!(
+ "Hedgewars game server, protocol {}",
+ utils::PROTOCOL_VERSION
+ );
let address = "0.0.0.0:46631".parse().unwrap();
let listener = TcpListener::bind(&address).unwrap();
@@ -50,12 +53,12 @@
Token(tok) => hw_network.client_writable(&poll, tok).unwrap(),
}
}
-// if event.kind().is_hup() || event.kind().is_error() {
-// match event.token() {
-// utils::SERVER => unreachable!(),
-// Token(tok) => server.client_error(&poll, tok).unwrap(),
-// }
-// }
+ // if event.kind().is_hup() || event.kind().is_error() {
+ // match event.token() {
+ // utils::SERVER => unreachable!(),
+ // Token(tok) => server.client_error(&poll, tok).unwrap(),
+ // }
+ // }
}
hw_network.on_idle(&poll).unwrap();
}
--- a/rust/hedgewars-server/src/protocol.rs Sun Dec 16 00:09:20 2018 +0100
+++ b/rust/hedgewars-server/src/protocol.rs Sun Dec 16 00:12:29 2018 +0100
@@ -1,15 +1,11 @@
use netbuf;
-use std::{
- io::{Read, Result}
-};
-use nom::{
- IResult, Err
-};
+use nom::{Err, IResult};
+use std::io::{Read, Result};
pub mod messages;
+mod parser;
#[cfg(test)]
pub mod test;
-mod parser;
pub struct ProtocolDecoder {
buf: netbuf::Buf,
@@ -34,7 +30,7 @@
Ok((tail, msgs)) => {
self.consumed = self.buf.len() - self.consumed - tail.len();
msgs
- },
+ }
Err(Err::Incomplete(_)) => unreachable!(),
Err(Err::Error(_)) | Err(Err::Failure(_)) => unreachable!(),
}
--- a/rust/hedgewars-server/src/protocol/messages.rs Sun Dec 16 00:09:20 2018 +0100
+++ b/rust/hedgewars-server/src/protocol/messages.rs Sun Dec 16 00:12:29 2018 +0100
@@ -1,8 +1,5 @@
-use crate::server::coretypes::{
- ServerVar, GameCfg, TeamInfo,
- HedgehogInfo, VoteType
-};
-use std::{ops, convert::From, iter::once};
+use crate::server::coretypes::{GameCfg, HedgehogInfo, ServerVar, TeamInfo, VoteType};
+use std::{convert::From, iter::once, ops};
#[derive(PartialEq, Eq, Clone, Debug)]
pub enum HWProtocolMessage {
@@ -80,7 +77,7 @@
ServerAuth(String),
LobbyLeft(String, String),
LobbyJoined(Vec<String>),
- ChatMsg {nick: String, msg: String},
+ ChatMsg { nick: String, msg: String },
ClientFlags(String, Vec<String>),
Rooms(Vec<String>),
RoomAdd(Vec<String>),
@@ -107,11 +104,14 @@
Unreachable,
//Deprecated messages
- LegacyReady(bool, Vec<String>)
+ LegacyReady(bool, Vec<String>),
}
-pub fn server_chat(msg: String) -> HWServerMessage {
- HWServerMessage::ChatMsg{ nick: "[server]".to_string(), msg }
+pub fn server_chat(msg: String) -> HWServerMessage {
+ HWServerMessage::ChatMsg {
+ nick: "[server]".to_string(),
+ msg,
+ }
}
impl GameCfg {
@@ -135,7 +135,7 @@
}),
Script(s) => ("SCRIPT".to_string(), vec![s.to_string()]),
Theme(t) => ("THEME".to_string(), vec![t.to_string()]),
- DrawnMap(m) => ("DRAWNMAP".to_string(), vec![m.to_string()])
+ DrawnMap(m) => ("DRAWNMAP".to_string(), vec![m.to_string()]),
}
}
@@ -147,7 +147,9 @@
}
macro_rules! const_braces {
- ($e: expr) => { "{}\n" }
+ ($e: expr) => {
+ "{}\n"
+ };
}
macro_rules! msg {
@@ -178,7 +180,7 @@
Global(msg) => msg!["CMD", format!("GLOBAL {}", msg)],
Watch(name) => msg!["CMD", format!("WATCH {}", name)],
ToggleServerRegisteredOnly => msg!["CMD", "REGISTERED_ONLY"],
- SuperPower => msg!["CMD", "SUPER_POWER"],
+ SuperPower => msg!["CMD", "SUPER_POWER"],
Info(info) => msg!["CMD", format!("INFO {}", info)],
Nick(nick) => msg!("NICK", nick),
Proto(version) => msg!["PROTO", version],
@@ -187,22 +189,21 @@
List => msg!["LIST"],
Chat(msg) => msg!["CHAT", msg],
CreateRoom(name, None) => msg!["CREATE_ROOM", name],
- CreateRoom(name, Some(password)) =>
- msg!["CREATE_ROOM", name, password],
+ CreateRoom(name, Some(password)) => msg!["CREATE_ROOM", name, password],
JoinRoom(name, None) => msg!["JOIN_ROOM", name],
- JoinRoom(name, Some(password)) =>
- msg!["JOIN_ROOM", name, password],
+ JoinRoom(name, Some(password)) => msg!["JOIN_ROOM", name, password],
Follow(name) => msg!["FOLLOW", name],
- Rnd(args) => if args.is_empty() {
- msg!["CMD", "RND"]
- } else {
- msg!["CMD", format!("RND {}", args.join(" "))]
- },
+ Rnd(args) => {
+ if args.is_empty() {
+ msg!["CMD", "RND"]
+ } else {
+ msg!["CMD", format!("RND {}", args.join(" "))]
+ }
+ }
Kick(name) => msg!["KICK", name],
Ban(name, reason, time) => msg!["BAN", name, reason, time],
BanIP(ip, reason, time) => msg!["BAN_IP", ip, reason, time],
- BanNick(nick, reason, time) =>
- msg!("BAN_NICK", nick, reason, time),
+ BanNick(nick, reason, time) => msg!("BAN_NICK", nick, reason, time),
BanList => msg!["BANLIST"],
Unban(name) => msg!["UNBAN", name],
//SetServerVar(ServerVar), ???
@@ -214,13 +215,22 @@
Cfg(config) => {
let (name, args) = config.to_protocol();
msg!["CFG", name, args.join("\n")]
- },
- AddTeam(info) =>
- msg!["ADD_TEAM", info.name, info.color, info.grave, info.fort,
- info.voice_pack, info.flag, info.difficulty,
- info.hedgehogs.iter()
- .flat_map(|h| several![&h.name[..], &h.hat[..]])
- .collect::<Vec<_>>().join("\n")],
+ }
+ AddTeam(info) => msg![
+ "ADD_TEAM",
+ info.name,
+ info.color,
+ info.grave,
+ info.fort,
+ info.voice_pack,
+ info.flag,
+ info.difficulty,
+ info.hedgehogs
+ .iter()
+ .flat_map(|h| several![&h.name[..], &h.hat[..]])
+ .collect::<Vec<_>>()
+ .join("\n")
+ ],
RemoveTeam(name) => msg!["REMOVE_TEAM", name],
SetHedgehogsNumber(team, number) => msg!["HH_NUM", team, number],
SetTeamColor(team, color) => msg!["TEAM_COLOR", team, color],
@@ -234,20 +244,20 @@
RoomName(name) => msg!["ROOM_NAME", name],
Delegate(name) => msg!["CMD", format!("DELEGATE {}", name)],
TeamChat(msg) => msg!["TEAMCHAT", msg],
- MaxTeams(count) => msg!["CMD", format!("MAXTEAMS {}", count)] ,
+ MaxTeams(count) => msg!["CMD", format!("MAXTEAMS {}", count)],
Fix => msg!["CMD", "FIX"],
Unfix => msg!["CMD", "UNFIX"],
Greeting(msg) => msg!["CMD", format!("GREETING {}", msg)],
//CallVote(Option<(String, Option<String>)>) =>, ??
- Vote(msg) => msg!["CMD", format!("VOTE {}", if *msg {"YES"} else {"NO"})],
- ForceVote(msg) => msg!["CMD", format!("FORCE {}", if *msg {"YES"} else {"NO"})],
+ Vote(msg) => msg!["CMD", format!("VOTE {}", if *msg { "YES" } else { "NO" })],
+ ForceVote(msg) => msg!["CMD", format!("FORCE {}", if *msg { "YES" } else { "NO" })],
Save(name, location) => msg!["CMD", format!("SAVE {} {}", name, location)],
Delete(name) => msg!["CMD", format!("DELETE {}", name)],
SaveRoom(name) => msg!["CMD", format!("SAVEROOM {}", name)],
LoadRoom(name) => msg!["CMD", format!("LOADROOM {}", name)],
Malformed => msg!["A", "QUICK", "BROWN", "HOG", "JUMPS", "OVER", "THE", "LAZY", "DOG"],
Empty => msg![""],
- _ => panic!("Protocol message not yet implemented")
+ _ => panic!("Protocol message not yet implemented"),
}
}
}
@@ -268,47 +278,40 @@
Connected(protocol_version) => msg![
"CONNECTED",
"Hedgewars server https://www.hedgewars.org/",
- protocol_version],
+ protocol_version
+ ],
Bye(msg) => msg!["BYE", msg],
Nick(nick) => msg!["NICK", nick],
Proto(proto) => msg!["PROTO", proto],
ServerAuth(hash) => msg!["SERVER_AUTH", hash],
LobbyLeft(nick, msg) => msg!["LOBBY:LEFT", nick, msg],
- LobbyJoined(nicks) =>
- construct_message(&["LOBBY:JOINED"], &nicks),
- ClientFlags(flags, nicks) =>
- construct_message(&["CLIENT_FLAGS", flags], &nicks),
- Rooms(info) =>
- construct_message(&["ROOMS"], &info),
- RoomAdd(info) =>
- construct_message(&["ROOM", "ADD"], &info),
- RoomJoined(nicks) =>
- construct_message(&["JOINED"], &nicks),
+ LobbyJoined(nicks) => construct_message(&["LOBBY:JOINED"], &nicks),
+ ClientFlags(flags, nicks) => construct_message(&["CLIENT_FLAGS", flags], &nicks),
+ Rooms(info) => construct_message(&["ROOMS"], &info),
+ RoomAdd(info) => construct_message(&["ROOM", "ADD"], &info),
+ RoomJoined(nicks) => construct_message(&["JOINED"], &nicks),
RoomLeft(nick, msg) => msg!["LEFT", nick, msg],
RoomRemove(name) => msg!["ROOM", "DEL", name],
- RoomUpdated(name, info) =>
- construct_message(&["ROOM", "UPD", name], &info),
- TeamAdd(info) =>
- construct_message(&["ADD_TEAM"], &info),
+ RoomUpdated(name, info) => construct_message(&["ROOM", "UPD", name], &info),
+ TeamAdd(info) => construct_message(&["ADD_TEAM"], &info),
TeamRemove(name) => msg!["REMOVE_TEAM", name],
TeamAccepted(name) => msg!["TEAM_ACCEPTED", name],
TeamColor(name, color) => msg!["TEAM_COLOR", name, color],
HedgehogsNumber(name, number) => msg!["HH_NUM", name, number],
- ConfigEntry(name, values) =>
- construct_message(&["CFG", name], &values),
+ ConfigEntry(name, values) => construct_message(&["CFG", name], &values),
Kicked => msg!["KICKED"],
RunGame => msg!["RUN_GAME"],
- ForwardEngineMessage(em) =>
- construct_message(&["EM"], &em),
+ ForwardEngineMessage(em) => construct_message(&["EM"], &em),
RoundFinished => msg!["ROUND_FINISHED"],
- ChatMsg {nick, msg} => msg!["CHAT", nick, msg],
+ ChatMsg { nick, msg } => msg!["CHAT", nick, msg],
ServerMessage(msg) => msg!["SERVER_MESSAGE", msg],
Notice(msg) => msg!["NOTICE", msg],
Warning(msg) => msg!["WARNING", msg],
Error(msg) => msg!["ERROR", msg],
- LegacyReady(is_ready, nicks) =>
- construct_message(&[if *is_ready {"READY"} else {"NOT_READY"}], &nicks),
+ LegacyReady(is_ready, nicks) => {
+ construct_message(&[if *is_ready { "READY" } else { "NOT_READY" }], &nicks)
+ }
_ => msg!["ERROR", "UNIMPLEMENTED"],
}
--- a/rust/hedgewars-server/src/protocol/parser.rs Sun Dec 16 00:09:20 2018 +0100
+++ b/rust/hedgewars-server/src/protocol/parser.rs Sun Dec 16 00:12:29 2018 +0100
@@ -6,23 +6,15 @@
* For example, a nullary command like PING will be actually sent as `PING\n\n`.
* A unary command, such as `START_GAME nick` will be actually sent as `START_GAME\nnick\n\n`.
*/
-
use nom::*;
-use std::{
- str, str::FromStr,
- ops::Range
-};
-use super::{
- messages::{HWProtocolMessage, HWProtocolMessage::*}
-};
+use super::messages::{HWProtocolMessage, HWProtocolMessage::*};
+use crate::server::coretypes::{GameCfg, HedgehogInfo, TeamInfo, VoteType, MAX_HEDGEHOGS_PER_TEAM};
+use std::{ops::Range, str, str::FromStr};
#[cfg(test)]
use {
super::test::gen_proto_msg,
- proptest::{proptest, proptest_helper}
-};
-use crate::server::coretypes::{
- HedgehogInfo, TeamInfo, GameCfg, VoteType, MAX_HEDGEHOGS_PER_TEAM
+ proptest::{proptest, proptest_helper},
};
named!(end_of_message, tag!("\n\n"));
@@ -257,17 +249,32 @@
#[test]
fn parse_test() {
- assert_eq!(message(b"PING\n\n"), Ok((&b""[..], Ping)));
- assert_eq!(message(b"START_GAME\n\n"), Ok((&b""[..], StartGame)));
- assert_eq!(message(b"NICK\nit's me\n\n"), Ok((&b""[..], Nick("it's me".to_string()))));
- assert_eq!(message(b"PROTO\n51\n\n"), Ok((&b""[..], Proto(51))));
- assert_eq!(message(b"QUIT\nbye-bye\n\n"), Ok((&b""[..], Quit(Some("bye-bye".to_string())))));
- assert_eq!(message(b"QUIT\n\n"), Ok((&b""[..], Quit(None))));
- assert_eq!(message(b"CMD\nwatch demo\n\n"), Ok((&b""[..], Watch("demo".to_string()))));
- assert_eq!(message(b"BAN\nme\nbad\n77\n\n"), Ok((&b""[..], Ban("me".to_string(), "bad".to_string(), 77))));
+ assert_eq!(message(b"PING\n\n"), Ok((&b""[..], Ping)));
+ assert_eq!(message(b"START_GAME\n\n"), Ok((&b""[..], StartGame)));
+ assert_eq!(
+ message(b"NICK\nit's me\n\n"),
+ Ok((&b""[..], Nick("it's me".to_string())))
+ );
+ assert_eq!(message(b"PROTO\n51\n\n"), Ok((&b""[..], Proto(51))));
+ assert_eq!(
+ message(b"QUIT\nbye-bye\n\n"),
+ Ok((&b""[..], Quit(Some("bye-bye".to_string()))))
+ );
+ assert_eq!(message(b"QUIT\n\n"), Ok((&b""[..], Quit(None))));
+ assert_eq!(
+ message(b"CMD\nwatch demo\n\n"),
+ Ok((&b""[..], Watch("demo".to_string())))
+ );
+ assert_eq!(
+ message(b"BAN\nme\nbad\n77\n\n"),
+ Ok((&b""[..], Ban("me".to_string(), "bad".to_string(), 77)))
+ );
- assert_eq!(message(b"CMD\nPART\n\n"), Ok((&b""[..], Part(None))));
- assert_eq!(message(b"CMD\nPART _msg_\n\n"), Ok((&b""[..], Part(Some("_msg_".to_string())))));
+ assert_eq!(message(b"CMD\nPART\n\n"), Ok((&b""[..], Part(None))));
+ assert_eq!(
+ message(b"CMD\nPART _msg_\n\n"),
+ Ok((&b""[..], Part(Some("_msg_".to_string()))))
+ );
assert_eq!(message(b"CMD\nRND\n\n"), Ok((&b""[..], Rnd(vec![]))));
assert_eq!(
@@ -275,10 +282,25 @@
Ok((&b""[..], Rnd(vec![String::from("A"), String::from("B")])))
);
- assert_eq!(extract_messages(b"QUIT\n1\n2\n\n"), Ok((&b""[..], vec![Malformed])));
+ assert_eq!(
+ extract_messages(b"QUIT\n1\n2\n\n"),
+ Ok((&b""[..], vec![Malformed]))
+ );
- assert_eq!(extract_messages(b"PING\n\nPING\n\nP"), Ok((&b"P"[..], vec![Ping, Ping])));
- assert_eq!(extract_messages(b"SING\n\nPING\n\n"), Ok((&b""[..], vec![Malformed, Ping])));
- assert_eq!(extract_messages(b"\n\n\n\nPING\n\n"), Ok((&b""[..], vec![Empty, Empty, Ping])));
- assert_eq!(extract_messages(b"\n\n\nPING\n\n"), Ok((&b""[..], vec![Empty, Empty, Ping])));
+ assert_eq!(
+ extract_messages(b"PING\n\nPING\n\nP"),
+ Ok((&b"P"[..], vec![Ping, Ping]))
+ );
+ assert_eq!(
+ extract_messages(b"SING\n\nPING\n\n"),
+ Ok((&b""[..], vec![Malformed, Ping]))
+ );
+ assert_eq!(
+ extract_messages(b"\n\n\n\nPING\n\n"),
+ Ok((&b""[..], vec![Empty, Empty, Ping]))
+ );
+ assert_eq!(
+ extract_messages(b"\n\n\nPING\n\n"),
+ Ok((&b""[..], vec![Empty, Empty, Ping]))
+ );
}
--- a/rust/hedgewars-server/src/protocol/test.rs Sun Dec 16 00:09:20 2018 +0100
+++ b/rust/hedgewars-server/src/protocol/test.rs Sun Dec 16 00:12:29 2018 +0100
@@ -1,37 +1,51 @@
use proptest::{
- test_runner::{TestRunner, Reason},
arbitrary::{any, any_with, Arbitrary, StrategyFor},
- strategy::{Strategy, BoxedStrategy, Just, Map}
+ strategy::{BoxedStrategy, Just, Map, Strategy},
+ test_runner::{Reason, TestRunner},
};
-use crate::server::coretypes::{GameCfg, TeamInfo, HedgehogInfo};
+use crate::server::coretypes::{GameCfg, HedgehogInfo, TeamInfo};
-use super::messages::{
- HWProtocolMessage, HWProtocolMessage::*
-};
+use super::messages::{HWProtocolMessage, HWProtocolMessage::*};
// Due to inability to define From between Options
-trait Into2<T>: Sized { fn into2(self) -> T; }
-impl <T> Into2<T> for T { fn into2(self) -> T { self } }
+trait Into2<T>: Sized {
+ fn into2(self) -> T;
+}
+impl<T> Into2<T> for T {
+ fn into2(self) -> T {
+ self
+ }
+}
impl Into2<Vec<String>> for Vec<Ascii> {
fn into2(self) -> Vec<String> {
self.into_iter().map(|x| x.0).collect()
}
}
-impl Into2<String> for Ascii { fn into2(self) -> String { self.0 } }
-impl Into2<Option<String>> for Option<Ascii>{
- fn into2(self) -> Option<String> { self.map(|x| {x.0}) }
+impl Into2<String> for Ascii {
+ fn into2(self) -> String {
+ self.0
+ }
+}
+impl Into2<Option<String>> for Option<Ascii> {
+ fn into2(self) -> Option<String> {
+ self.map(|x| x.0)
+ }
}
macro_rules! proto_msg_case {
- ($val: ident()) =>
- (Just($val));
- ($val: ident($arg: ty)) =>
- (any::<$arg>().prop_map(|v| {$val(v.into2())}));
- ($val: ident($arg1: ty, $arg2: ty)) =>
- (any::<($arg1, $arg2)>().prop_map(|v| {$val(v.0.into2(), v.1.into2())}));
- ($val: ident($arg1: ty, $arg2: ty, $arg3: ty)) =>
- (any::<($arg1, $arg2, $arg3)>().prop_map(|v| {$val(v.0.into2(), v.1.into2(), v.2.into2())}));
+ ($val: ident()) => {
+ Just($val)
+ };
+ ($val: ident($arg: ty)) => {
+ any::<$arg>().prop_map(|v| $val(v.into2()))
+ };
+ ($val: ident($arg1: ty, $arg2: ty)) => {
+ any::<($arg1, $arg2)>().prop_map(|v| $val(v.0.into2(), v.1.into2()))
+ };
+ ($val: ident($arg1: ty, $arg2: ty, $arg3: ty)) => {
+ any::<($arg1, $arg2, $arg3)>().prop_map(|v| $val(v.0.into2(), v.1.into2(), v.2.into2()))
+ };
}
macro_rules! proto_msg_match {
@@ -62,8 +76,10 @@
fn arbitrary_with(_args: <Self as Arbitrary>::Parameters) -> <Self as Arbitrary>::Strategy {
use crate::server::coretypes::GameCfg::*;
- (0..10).no_shrink().prop_flat_map(|i| {
- proto_msg_match!(i, def = FeatureSize(0),
+ (0..10)
+ .no_shrink()
+ .prop_flat_map(|i| {
+ proto_msg_match!(i, def = FeatureSize(0),
0 => FeatureSize(u32),
1 => MapType(Ascii),
2 => MapGenerator(u32),
@@ -75,7 +91,8 @@
8 => Script(Ascii),
9 => Theme(Ascii),
10 => DrawnMap(Ascii))
- }).boxed()
+ })
+ .boxed()
}
type Strategy = BoxedStrategy<GameCfg>;
@@ -85,18 +102,45 @@
type Parameters = ();
fn arbitrary_with(_args: <Self as Arbitrary>::Parameters) -> <Self as Arbitrary>::Strategy {
- ("[a-z]+", 0u8..127u8, "[a-z]+", "[a-z]+", "[a-z]+", "[a-z]+", 0u8..127u8)
+ (
+ "[a-z]+",
+ 0u8..127u8,
+ "[a-z]+",
+ "[a-z]+",
+ "[a-z]+",
+ "[a-z]+",
+ 0u8..127u8,
+ )
.prop_map(|(name, color, grave, fort, voice_pack, flag, difficulty)| {
fn hog(n: u8) -> HedgehogInfo {
- HedgehogInfo { name: format!("hog{}", n), hat: format!("hat{}", n)}
+ HedgehogInfo {
+ name: format!("hog{}", n),
+ hat: format!("hat{}", n),
+ }
}
- let hedgehogs = [hog(1), hog(2), hog(3), hog(4), hog(5), hog(6), hog(7), hog(8)];
+ let hedgehogs = [
+ hog(1),
+ hog(2),
+ hog(3),
+ hog(4),
+ hog(5),
+ hog(6),
+ hog(7),
+ hog(8),
+ ];
TeamInfo {
- name, color, grave, fort,
- voice_pack, flag,difficulty,
- hedgehogs, hedgehogs_number: 0
+ name,
+ color,
+ grave,
+ fort,
+ voice_pack,
+ flag,
+ difficulty,
+ hedgehogs,
+ hedgehogs_number: 0,
}
- }).boxed()
+ })
+ .boxed()
}
type Strategy = BoxedStrategy<TeamInfo>;
@@ -105,64 +149,65 @@
pub fn gen_proto_msg() -> BoxedStrategy<HWProtocolMessage> where {
let res = (0..58).no_shrink().prop_flat_map(|i| {
proto_msg_match!(i, def = Malformed,
- 0 => Ping(),
- 1 => Pong(),
- 2 => Quit(Option<Ascii>),
- //3 => Cmd
- 4 => Global(Ascii),
- 5 => Watch(Ascii),
- 6 => ToggleServerRegisteredOnly(),
- 7 => SuperPower(),
- 8 => Info(Ascii),
- 9 => Nick(Ascii),
- 10 => Proto(u16),
- 11 => Password(Ascii, Ascii),
- 12 => Checker(u16, Ascii, Ascii),
- 13 => List(),
- 14 => Chat(Ascii),
- 15 => CreateRoom(Ascii, Option<Ascii>),
- 16 => JoinRoom(Ascii, Option<Ascii>),
- 17 => Follow(Ascii),
- 18 => Rnd(Vec<Ascii>),
- 19 => Kick(Ascii),
- 20 => Ban(Ascii, Ascii, u32),
- 21 => BanIP(Ascii, Ascii, u32),
- 22 => BanNick(Ascii, Ascii, u32),
- 23 => BanList(),
- 24 => Unban(Ascii),
- //25 => SetServerVar(ServerVar),
- 26 => GetServerVar(),
- 27 => RestartServer(),
- 28 => Stats(),
- 29 => Part(Option<Ascii>),
- 30 => Cfg(GameCfg),
- 31 => AddTeam(Box<TeamInfo>),
- 32 => RemoveTeam(Ascii),
- 33 => SetHedgehogsNumber(Ascii, u8),
- 34 => SetTeamColor(Ascii, u8),
- 35 => ToggleReady(),
- 36 => StartGame(),
- 37 => EngineMessage(Ascii),
- 38 => RoundFinished(),
- 39 => ToggleRestrictJoin(),
- 40 => ToggleRestrictTeams(),
- 41 => ToggleRegisteredOnly(),
- 42 => RoomName(Ascii),
- 43 => Delegate(Ascii),
- 44 => TeamChat(Ascii),
- 45 => MaxTeams(u8),
- 46 => Fix(),
- 47 => Unfix(),
- 48 => Greeting(Ascii),
- //49 => CallVote(Option<(String, Option<String>)>),
- 50 => Vote(bool),
- 51 => ForceVote(bool),
- 52 => Save(Ascii, Ascii),
- 53 => Delete(Ascii),
- 54 => SaveRoom(Ascii),
- 55 => LoadRoom(Ascii),
- 56 => Malformed(),
- 57 => Empty()
- )});
+ 0 => Ping(),
+ 1 => Pong(),
+ 2 => Quit(Option<Ascii>),
+ //3 => Cmd
+ 4 => Global(Ascii),
+ 5 => Watch(Ascii),
+ 6 => ToggleServerRegisteredOnly(),
+ 7 => SuperPower(),
+ 8 => Info(Ascii),
+ 9 => Nick(Ascii),
+ 10 => Proto(u16),
+ 11 => Password(Ascii, Ascii),
+ 12 => Checker(u16, Ascii, Ascii),
+ 13 => List(),
+ 14 => Chat(Ascii),
+ 15 => CreateRoom(Ascii, Option<Ascii>),
+ 16 => JoinRoom(Ascii, Option<Ascii>),
+ 17 => Follow(Ascii),
+ 18 => Rnd(Vec<Ascii>),
+ 19 => Kick(Ascii),
+ 20 => Ban(Ascii, Ascii, u32),
+ 21 => BanIP(Ascii, Ascii, u32),
+ 22 => BanNick(Ascii, Ascii, u32),
+ 23 => BanList(),
+ 24 => Unban(Ascii),
+ //25 => SetServerVar(ServerVar),
+ 26 => GetServerVar(),
+ 27 => RestartServer(),
+ 28 => Stats(),
+ 29 => Part(Option<Ascii>),
+ 30 => Cfg(GameCfg),
+ 31 => AddTeam(Box<TeamInfo>),
+ 32 => RemoveTeam(Ascii),
+ 33 => SetHedgehogsNumber(Ascii, u8),
+ 34 => SetTeamColor(Ascii, u8),
+ 35 => ToggleReady(),
+ 36 => StartGame(),
+ 37 => EngineMessage(Ascii),
+ 38 => RoundFinished(),
+ 39 => ToggleRestrictJoin(),
+ 40 => ToggleRestrictTeams(),
+ 41 => ToggleRegisteredOnly(),
+ 42 => RoomName(Ascii),
+ 43 => Delegate(Ascii),
+ 44 => TeamChat(Ascii),
+ 45 => MaxTeams(u8),
+ 46 => Fix(),
+ 47 => Unfix(),
+ 48 => Greeting(Ascii),
+ //49 => CallVote(Option<(String, Option<String>)>),
+ 50 => Vote(bool),
+ 51 => ForceVote(bool),
+ 52 => Save(Ascii, Ascii),
+ 53 => Delete(Ascii),
+ 54 => SaveRoom(Ascii),
+ 55 => LoadRoom(Ascii),
+ 56 => Malformed(),
+ 57 => Empty()
+ )
+ });
res.boxed()
}
--- a/rust/hedgewars-server/src/server.rs Sun Dec 16 00:09:20 2018 +0100
+++ b/rust/hedgewars-server/src/server.rs Sun Dec 16 00:12:29 2018 +0100
@@ -1,10 +1,10 @@
-pub mod core;
+mod actions;
pub mod client;
-pub mod io;
-pub mod room;
-pub mod network;
+pub mod core;
pub mod coretypes;
-mod actions;
-mod handlers;
#[cfg(feature = "official-server")]
mod database;
+mod handlers;
+pub mod io;
+pub mod network;
+pub mod room;
--- a/rust/hedgewars-server/src/server/actions.rs Sun Dec 16 00:09:20 2018 +0100
+++ b/rust/hedgewars-server/src/server/actions.rs Sun Dec 16 00:12:29 2018 +0100
@@ -1,26 +1,17 @@
-use std::{
- io, io::Write,
- iter::once,
- mem::replace
-};
use super::{
+ client::HWClient,
core::HWServer,
+ coretypes::{ClientId, GameCfg, RoomId, VoteType},
+ handlers,
+ room::HWRoom,
room::{GameInfo, RoomFlags},
- client::HWClient,
- coretypes::{ClientId, RoomId, GameCfg, VoteType},
- room::HWRoom,
- handlers
};
use crate::{
- protocol::messages::{
- HWProtocolMessage,
- HWServerMessage,
- HWServerMessage::*,
- server_chat
- },
- utils::to_engine_msg
+ protocol::messages::{server_chat, HWProtocolMessage, HWServerMessage, HWServerMessage::*},
+ utils::to_engine_msg,
};
-use rand::{thread_rng, Rng, distributions::Uniform};
+use rand::{distributions::Uniform, thread_rng, Rng};
+use std::{io, io::Write, iter::once, mem::replace};
#[cfg(feature = "official-server")]
use super::database;
@@ -31,22 +22,28 @@
ToAll {
room_id: Option<RoomId>,
protocol: Option<u16>,
- skip_self: bool
- }
+ skip_self: bool,
+ },
}
pub struct PendingMessage {
pub destination: Destination,
- pub message: HWServerMessage
+ pub message: HWServerMessage,
}
impl PendingMessage {
pub fn send(message: HWServerMessage, client_id: ClientId) -> PendingMessage {
- PendingMessage{ destination: Destination::ToId(client_id), message}
+ PendingMessage {
+ destination: Destination::ToId(client_id),
+ message,
+ }
}
pub fn send_self(message: HWServerMessage) -> PendingMessage {
- PendingMessage{ destination: Destination::ToSelf, message }
+ PendingMessage {
+ destination: Destination::ToSelf,
+ message,
+ }
}
pub fn send_all(message: HWServerMessage) -> PendingMessage {
@@ -55,41 +52,63 @@
protocol: None,
skip_self: false,
};
- PendingMessage{ destination, message }
+ PendingMessage {
+ destination,
+ message,
+ }
}
pub fn in_room(mut self, clients_room_id: RoomId) -> PendingMessage {
- if let Destination::ToAll {ref mut room_id, ..} = self.destination {
+ if let Destination::ToAll {
+ ref mut room_id, ..
+ } = self.destination
+ {
*room_id = Some(clients_room_id)
}
self
}
pub fn with_protocol(mut self, protocol_number: u16) -> PendingMessage {
- if let Destination::ToAll {ref mut protocol, ..} = self.destination {
+ if let Destination::ToAll {
+ ref mut protocol, ..
+ } = self.destination
+ {
*protocol = Some(protocol_number)
}
self
}
pub fn but_self(mut self) -> PendingMessage {
- if let Destination::ToAll {ref mut skip_self, ..} = self.destination {
+ if let Destination::ToAll {
+ ref mut skip_self, ..
+ } = self.destination
+ {
*skip_self = true
}
self
}
- pub fn action(self) -> Action { Send(self) }
+ pub fn action(self) -> Action {
+ Send(self)
+ }
}
impl Into<Action> for PendingMessage {
- fn into(self) -> Action { self.action() }
+ fn into(self) -> Action {
+ self.action()
+ }
}
impl HWServerMessage {
- pub fn send(self, client_id: ClientId) -> PendingMessage { PendingMessage::send(self, client_id) }
- pub fn send_self(self) -> PendingMessage { PendingMessage::send_self(self) }
- pub fn send_all(self) -> PendingMessage { PendingMessage::send_all(self) }
+ pub fn send(self, client_id: ClientId) -> PendingMessage {
+ PendingMessage::send(self, client_id)
+ }
+ pub fn send_self(self) -> PendingMessage {
+ PendingMessage::send_self(self)
+ }
+ pub fn send_all(self) -> PendingMessage {
+ PendingMessage::send_all(self)
+ }
}
pub enum Action {
@@ -110,11 +129,19 @@
StartRoomGame(RoomId),
SendTeamRemovalMessage(String),
FinishRoomGame(RoomId),
- SendRoomData{to: ClientId, teams: bool, config: bool, flags: bool},
- AddVote{vote: bool, is_forced: bool},
+ SendRoomData {
+ to: ClientId,
+ teams: bool,
+ config: bool,
+ flags: bool,
+ },
+ AddVote {
+ vote: bool,
+ is_forced: bool,
+ },
ApplyVoting(VoteType, RoomId),
Warn(String),
- ProtocolError(String)
+ ProtocolError(String),
}
use self::Action::*;
@@ -126,31 +153,38 @@
let c = &server.clients[client_id];
let nick = c.nick.clone();
- if let Some(id) = c.room_id{
+ if let Some(id) = c.room_id {
if id != server.lobby_id {
- server.react(client_id, vec![
- MoveToLobby(format!("quit: {}", msg.clone()))]);
+ server.react(
+ client_id,
+ vec![MoveToLobby(format!("quit: {}", msg.clone()))],
+ );
}
}
- server.react(client_id, vec![
- LobbyLeft(nick, msg.clone()).send_all().action(),
- Bye(msg).send_self().action(),
- RemoveClient]);
- },
+ server.react(
+ client_id,
+ vec![
+ LobbyLeft(nick, msg.clone()).send_all().action(),
+ Bye(msg).send_self().action(),
+ RemoveClient,
+ ],
+ );
+ }
RemoveClient => {
server.removed_clients.push(client_id);
if server.clients.contains(client_id) {
server.clients.remove(client_id);
}
- },
- ReactProtocolMessage(msg) =>
- handlers::handle(server, client_id, msg),
+ }
+ ReactProtocolMessage(msg) => handlers::handle(server, client_id, msg),
CheckRegistered => {
let client = &server.clients[client_id];
if client.protocol_number > 0 && client.nick != "" {
- let has_nick_clash = server.clients.iter().any(
- |(id, c)| id != client_id && c.nick == client.nick);
+ let has_nick_clash = server
+ .clients
+ .iter()
+ .any(|(id, c)| id != client_id && c.nick == client.nick);
let actions = if !client.is_checker() && has_nick_clash {
if client.protocol_number < 38 {
@@ -164,7 +198,7 @@
};
server.react(client_id, actions);
}
- },
+ }
JoinLobby => {
server.clients[client_id].room_id = Some(server.lobby_id);
@@ -179,24 +213,33 @@
let everyone_msg = LobbyJoined(vec![server.clients[client_id].nick.clone()]);
let flags_msg = ClientFlags(
"+i".to_string(),
- server.clients.iter()
+ server
+ .clients
+ .iter()
.filter(|(_, c)| c.room_id.is_some())
.map(|(_, c)| c.nick.clone())
- .collect());
+ .collect(),
+ );
let server_msg = ServerMessage("\u{1f994} is watching".to_string());
- let rooms_msg = Rooms(server.rooms.iter()
- .filter(|(id, _)| *id != server.lobby_id)
- .flat_map(|(_, r)|
- r.info(r.master_id.map(|id| &server.clients[id])))
- .collect());
- server.react(client_id, vec![
- everyone_msg.send_all().but_self().action(),
- joined_msg.send_self().action(),
- flags_msg.send_self().action(),
- server_msg.send_self().action(),
- rooms_msg.send_self().action(),
- ]);
- },
+ let rooms_msg = Rooms(
+ server
+ .rooms
+ .iter()
+ .filter(|(id, _)| *id != server.lobby_id)
+ .flat_map(|(_, r)| r.info(r.master_id.map(|id| &server.clients[id])))
+ .collect(),
+ );
+ server.react(
+ client_id,
+ vec![
+ everyone_msg.send_all().but_self().action(),
+ joined_msg.send_self().action(),
+ flags_msg.send_self().action(),
+ server_msg.send_self().action(),
+ rooms_msg.send_self().action(),
+ ],
+ );
+ }
AddRoom(name, password) => {
let room_id = server.add_room();;
@@ -208,16 +251,21 @@
r.protocol_number = c.protocol_number;
let actions = vec![
- RoomAdd(r.info(Some(&c))).send_all()
- .with_protocol(r.protocol_number).action(),
- MoveToRoom(room_id)];
+ RoomAdd(r.info(Some(&c)))
+ .send_all()
+ .with_protocol(r.protocol_number)
+ .action(),
+ MoveToRoom(room_id),
+ ];
server.react(client_id, actions);
- },
+ }
RemoveRoom(room_id) => {
let r = &mut server.rooms[room_id];
- let actions = vec![RoomRemove(r.name.clone()).send_all()
- .with_protocol(r.protocol_number).action()];
+ let actions = vec![RoomRemove(r.name.clone())
+ .send_all()
+ .with_protocol(r.protocol_number)
+ .action()];
server.rooms.remove(room_id);
server.react(client_id, actions);
}
@@ -237,13 +285,25 @@
}
let mut v = vec![
- RoomJoined(vec![c.nick.clone()]).send_all().in_room(room_id).action(),
- ClientFlags("+i".to_string(), vec![c.nick.clone()]).send_all().action(),
- SendRoomUpdate(None)];
+ RoomJoined(vec![c.nick.clone()])
+ .send_all()
+ .in_room(room_id)
+ .action(),
+ ClientFlags("+i".to_string(), vec![c.nick.clone()])
+ .send_all()
+ .action(),
+ SendRoomUpdate(None),
+ ];
if !r.greeting.is_empty() {
- v.push(ChatMsg {nick: "[greeting]".to_string(), msg: r.greeting.clone()}
- .send_self().action());
+ v.push(
+ ChatMsg {
+ nick: "[greeting]".to_string(),
+ msg: r.greeting.clone(),
+ }
+ .send_self()
+ .action(),
+ );
}
if !c.is_master() {
@@ -260,49 +320,82 @@
}
if !team_names.is_empty() {
- info.left_teams.retain(|name|
- !team_names.contains(&name));
+ info.left_teams.retain(|name| !team_names.contains(&name));
info.teams_in_game += team_names.len() as u8;
- r.teams = info.teams_at_start.iter()
+ r.teams = info
+ .teams_at_start
+ .iter()
.filter(|(_, t)| !team_names.contains(&t.name))
- .cloned().collect();
+ .cloned()
+ .collect();
}
} else {
team_names = Vec::new();
}
- v.push(SendRoomData{ to: client_id, teams: true, config: true, flags: true});
+ v.push(SendRoomData {
+ to: client_id,
+ teams: true,
+ config: true,
+ flags: true,
+ });
if let Some(ref info) = r.game_info {
v.push(RunGame.send_self().action());
- v.push(ClientFlags("+g".to_string(), vec![c.nick.clone()])
- .send_all().in_room(r.id).action());
- v.push(ForwardEngineMessage(
- vec![to_engine_msg("e$spectate 1".bytes())])
- .send_self().action());
- v.push(ForwardEngineMessage(info.msg_log.clone())
- .send_self().action());
+ v.push(
+ ClientFlags("+g".to_string(), vec![c.nick.clone()])
+ .send_all()
+ .in_room(r.id)
+ .action(),
+ );
+ v.push(
+ ForwardEngineMessage(vec![to_engine_msg("e$spectate 1".bytes())])
+ .send_self()
+ .action(),
+ );
+ v.push(
+ ForwardEngineMessage(info.msg_log.clone())
+ .send_self()
+ .action(),
+ );
for name in &team_names {
- v.push(ForwardEngineMessage(
- vec![to_engine_msg(once(b'G').chain(name.bytes()))])
- .send_all().in_room(r.id).action());
+ v.push(
+ ForwardEngineMessage(vec![to_engine_msg(
+ once(b'G').chain(name.bytes()),
+ )])
+ .send_all()
+ .in_room(r.id)
+ .action(),
+ );
}
if info.is_paused {
- v.push(ForwardEngineMessage(vec![to_engine_msg(once(b'I'))])
- .send_all().in_room(r.id).action())
+ v.push(
+ ForwardEngineMessage(vec![to_engine_msg(once(b'I'))])
+ .send_all()
+ .in_room(r.id)
+ .action(),
+ )
}
}
}
server.react(client_id, v);
}
- SendRoomData {to, teams, config, flags} => {
+ SendRoomData {
+ to,
+ teams,
+ config,
+ flags,
+ } => {
let mut actions = Vec::new();
let room_id = server.clients[client_id].room_id;
if let Some(r) = room_id.and_then(|id| server.rooms.get(id)) {
if config {
- actions.push(ConfigEntry("FULLMAPCONFIG".to_string(), r.map_config())
- .send(to).action());
+ actions.push(
+ ConfigEntry("FULLMAPCONFIG".to_string(), r.map_config())
+ .send(to)
+ .action(),
+ );
for cfg in r.game_config() {
actions.push(cfg.to_server_msg().send(to).action());
}
@@ -310,41 +403,54 @@
if teams {
let current_teams = match r.game_info {
Some(ref info) => &info.teams_at_start,
- None => &r.teams
+ None => &r.teams,
};
for (owner_id, team) in current_teams.iter() {
- actions.push(TeamAdd(HWRoom::team_info(&server.clients[*owner_id], &team))
- .send(to).action());
- actions.push(TeamColor(team.name.clone(), team.color)
- .send(to).action());
- actions.push(HedgehogsNumber(team.name.clone(), team.hedgehogs_number)
- .send(to).action());
+ actions.push(
+ TeamAdd(HWRoom::team_info(&server.clients[*owner_id], &team))
+ .send(to)
+ .action(),
+ );
+ actions.push(TeamColor(team.name.clone(), team.color).send(to).action());
+ actions.push(
+ HedgehogsNumber(team.name.clone(), team.hedgehogs_number)
+ .send(to)
+ .action(),
+ );
}
}
if flags {
if let Some(id) = r.master_id {
- actions.push(ClientFlags("+h".to_string(), vec![server.clients[id].nick.clone()])
- .send(to).action());
+ actions.push(
+ ClientFlags("+h".to_string(), vec![server.clients[id].nick.clone()])
+ .send(to)
+ .action(),
+ );
}
- let nicks: Vec<_> = server.clients.iter()
+ let nicks: Vec<_> = server
+ .clients
+ .iter()
.filter(|(_, c)| c.room_id == Some(r.id) && c.is_ready())
- .map(|(_, c)| c.nick.clone()).collect();
+ .map(|(_, c)| c.nick.clone())
+ .collect();
if !nicks.is_empty() {
- actions.push(ClientFlags("+r".to_string(), nicks)
- .send(to).action());
+ actions.push(ClientFlags("+r".to_string(), nicks).send(to).action());
}
}
}
server.react(client_id, actions);
}
- AddVote{vote, is_forced} => {
+ AddVote { vote, is_forced } => {
let mut actions = Vec::new();
if let Some(r) = server.room(client_id) {
let mut result = None;
if let Some(ref mut voting) = r.voting {
if is_forced || voting.votes.iter().all(|(id, _)| client_id != *id) {
- actions.push(server_chat("Your vote has been counted.".to_string())
- .send_self().action());
+ actions.push(
+ server_chat("Your vote has been counted.".to_string())
+ .send_self()
+ .action(),
+ );
voting.votes.push((client_id, vote));
let i = voting.votes.iter();
let pro = i.clone().filter(|(_, v)| *v).count();
@@ -352,21 +458,32 @@
let success_quota = voting.voters.len() / 2 + 1;
if is_forced && vote || pro >= success_quota {
result = Some(true);
- } else if is_forced && !vote || contra > voting.voters.len() - success_quota {
+ } else if is_forced && !vote || contra > voting.voters.len() - success_quota
+ {
result = Some(false);
}
} else {
- actions.push(server_chat("You already have voted.".to_string())
- .send_self().action());
+ actions.push(
+ server_chat("You already have voted.".to_string())
+ .send_self()
+ .action(),
+ );
}
} else {
- actions.push(server_chat("There's no voting going on.".to_string())
- .send_self().action());
+ actions.push(
+ server_chat("There's no voting going on.".to_string())
+ .send_self()
+ .action(),
+ );
}
if let Some(res) = result {
- actions.push(server_chat("Voting closed.".to_string())
- .send_all().in_room(r.id).action());
+ actions.push(
+ server_chat("Voting closed.".to_string())
+ .send_all()
+ .in_room(r.id)
+ .action(),
+ );
let voting = replace(&mut r.voting, None).unwrap();
if res {
actions.push(ApplyVoting(voting.kind, r.id));
@@ -388,44 +505,62 @@
actions.push(MoveToLobby("kicked".to_string()));
}
}
- },
+ }
VoteType::Map(None) => (),
VoteType::Map(Some(name)) => {
if let Some(location) = server.rooms[room_id].load_config(&name) {
- actions.push(server_chat(location.to_string())
- .send_all().in_room(room_id).action());
+ actions.push(
+ server_chat(location.to_string())
+ .send_all()
+ .in_room(room_id)
+ .action(),
+ );
actions.push(SendRoomUpdate(None));
for (_, c) in server.clients.iter() {
if c.room_id == Some(room_id) {
- actions.push(SendRoomData{
- to: c.id, teams: false,
- config: true, flags: false})
+ actions.push(SendRoomData {
+ to: c.id,
+ teams: false,
+ config: true,
+ flags: false,
+ })
}
}
}
- },
+ }
VoteType::Pause => {
if let Some(ref mut info) = server.rooms[room_id].game_info {
info.is_paused = !info.is_paused;
- actions.push(server_chat("Pause toggled.".to_string())
- .send_all().in_room(room_id).action());
- actions.push(ForwardEngineMessage(vec![to_engine_msg(once(b'I'))])
- .send_all().in_room(room_id).action());
+ actions.push(
+ server_chat("Pause toggled.".to_string())
+ .send_all()
+ .in_room(room_id)
+ .action(),
+ );
+ actions.push(
+ ForwardEngineMessage(vec![to_engine_msg(once(b'I'))])
+ .send_all()
+ .in_room(room_id)
+ .action(),
+ );
}
- },
+ }
VoteType::NewSeed => {
let seed = thread_rng().gen_range(0, 1_000_000_000).to_string();
let cfg = GameCfg::Seed(seed);
actions.push(cfg.to_server_msg().send_all().in_room(room_id).action());
server.rooms[room_id].set_config(cfg);
- },
+ }
VoteType::HedgehogsPerTeam(number) => {
let r = &mut server.rooms[room_id];
let nicks = r.set_hedgehogs_number(number);
- actions.extend(nicks.into_iter().map(|n|
- HedgehogsNumber(n, number).send_all().in_room(room_id).action()
- ));
- },
+ actions.extend(nicks.into_iter().map(|n| {
+ HedgehogsNumber(n, number)
+ .send_all()
+ .in_room(room_id)
+ .action()
+ }));
+ }
}
server.react(id, actions);
}
@@ -440,8 +575,11 @@
if c.is_master() && (r.players_number > 0 || r.is_fixed()) {
actions.push(ChangeMaster(r.id, None));
}
- actions.push(ClientFlags("-i".to_string(), vec![c.nick.clone()])
- .send_all().action());
+ actions.push(
+ ClientFlags("-i".to_string(), vec![c.nick.clone()])
+ .send_all()
+ .action(),
+ );
}
server.react(client_id, actions);
actions = Vec::new();
@@ -452,8 +590,13 @@
actions.push(RemoveRoom(r.id));
} else {
actions.push(RemoveClientTeams);
- actions.push(RoomLeft(c.nick.clone(), msg)
- .send_all().in_room(r.id).but_self().action());
+ actions.push(
+ RoomLeft(c.nick.clone(), msg)
+ .send_all()
+ .in_room(r.id)
+ .but_self()
+ .action(),
+ );
actions.push(SendRoomUpdate(Some(r.name.clone())));
}
}
@@ -462,11 +605,14 @@
ChangeMaster(room_id, new_id) => {
let mut actions = Vec::new();
let room_client_ids = server.room_clients(room_id);
- let new_id = if server.room(client_id).map(|r| r.is_fixed()).unwrap_or(false) {
+ let new_id = if server
+ .room(client_id)
+ .map(|r| r.is_fixed())
+ .unwrap_or(false)
+ {
new_id
} else {
- new_id.or_else(||
- room_client_ids.iter().find(|id| **id != client_id).cloned())
+ new_id.or_else(|| room_client_ids.iter().find(|id| **id != client_id).cloned())
};
let new_nick = new_id.map(|id| server.clients[id].nick.clone());
@@ -475,23 +621,32 @@
Some(id) if id == c.id => {
c.set_is_master(false);
r.master_id = None;
- actions.push(ClientFlags("-h".to_string(), vec![c.nick.clone()])
- .send_all().in_room(r.id).action());
+ actions.push(
+ ClientFlags("-h".to_string(), vec![c.nick.clone()])
+ .send_all()
+ .in_room(r.id)
+ .action(),
+ );
}
Some(_) => unreachable!(),
None => {}
}
r.master_id = new_id;
if !r.is_fixed() && c.protocol_number < 42 {
- r.name.replace_range(.., new_nick.as_ref().map_or("[]", String::as_str));
+ r.name
+ .replace_range(.., new_nick.as_ref().map_or("[]", String::as_str));
}
r.set_join_restriction(false);
r.set_team_add_restriction(false);
let is_fixed = r.is_fixed();
r.set_unregistered_players_restriction(is_fixed);
if let Some(nick) = new_nick {
- actions.push(ClientFlags("+h".to_string(), vec![nick])
- .send_all().in_room(r.id).action());
+ actions.push(
+ ClientFlags("+h".to_string(), vec![nick])
+ .send_all()
+ .in_room(r.id)
+ .action(),
+ );
}
}
if let Some(id) = new_id {
@@ -513,10 +668,13 @@
}
}
server.react(client_id, actions);
- },
+ }
RemoveClientTeams => {
if let (c, Some(r)) = server.client_and_room(client_id) {
- let actions = r.client_teams(c.id).map(|t| RemoveTeam(t.name.clone())).collect();
+ let actions = r
+ .client_teams(c.id)
+ .map(|t| RemoveTeam(t.name.clone()))
+ .collect();
server.react(client_id, actions);
}
}
@@ -524,19 +682,28 @@
if let (c, Some(r)) = server.client_and_room(client_id) {
let name = old_name.unwrap_or_else(|| r.name.clone());
let actions = vec![RoomUpdated(name, r.info(Some(&c)))
- .send_all().with_protocol(r.protocol_number).action()];
+ .send_all()
+ .with_protocol(r.protocol_number)
+ .action()];
server.react(client_id, actions);
}
- },
+ }
StartRoomGame(room_id) => {
let actions = {
- let (room_clients, room_nicks): (Vec<_>, Vec<_>) = server.clients.iter()
- .map(|(id, c)| (id, c.nick.clone())).unzip();
+ let (room_clients, room_nicks): (Vec<_>, Vec<_>) = server
+ .clients
+ .iter()
+ .map(|(id, c)| (id, c.nick.clone()))
+ .unzip();
let room = &mut server.rooms[room_id];
if !room.has_multiple_clans() {
- vec![Warn("The game can't be started with less than two clans!".to_string())]
- } else if room.protocol_number <= 43 && room.players_number != room.ready_players_number {
+ vec![Warn(
+ "The game can't be started with less than two clans!".to_string(),
+ )]
+ } else if room.protocol_number <= 43
+ && room.players_number != room.ready_players_number
+ {
vec![Warn("Not all players are ready".to_string())]
} else if room.game_info.is_some() {
vec![Warn("The game is already in progress".to_string())]
@@ -547,10 +714,14 @@
c.set_is_in_game(false);
c.team_indices = room.client_team_indices(c.id);
}
- vec![RunGame.send_all().in_room(room.id).action(),
- SendRoomUpdate(None),
- ClientFlags("+g".to_string(), room_nicks)
- .send_all().in_room(room.id).action()]
+ vec![
+ RunGame.send_all().in_room(room.id).action(),
+ SendRoomUpdate(None),
+ ClientFlags("+g".to_string(), room_nicks)
+ .send_all()
+ .in_room(room.id)
+ .action(),
+ ]
}
};
server.react(client_id, actions);
@@ -560,8 +731,13 @@
if let Some(r) = server.room(client_id) {
if let Some(ref mut info) = r.game_info {
let msg = once(b'F').chain(team_name.bytes());
- actions.push(ForwardEngineMessage(vec![to_engine_msg(msg)]).
- send_all().in_room(r.id).but_self().action());
+ actions.push(
+ ForwardEngineMessage(vec![to_engine_msg(msg)])
+ .send_all()
+ .in_room(r.id)
+ .but_self()
+ .action(),
+ );
info.teams_in_game -= 1;
if info.teams_in_game == 0 {
actions.push(FinishRoomGame(r.id));
@@ -574,8 +750,13 @@
info.sync_msg = None
}
info.msg_log.push(remove_msg.clone());
- actions.push(ForwardEngineMessage(vec![remove_msg])
- .send_all().in_room(r.id).but_self().action());
+ actions.push(
+ ForwardEngineMessage(vec![remove_msg])
+ .send_all()
+ .in_room(r.id)
+ .but_self()
+ .action(),
+ );
}
}
server.react(client_id, actions);
@@ -591,28 +772,36 @@
if let Some(info) = replace(&mut r.game_info, None) {
for (_, c) in server.clients.iter() {
if c.room_id == Some(room_id) && c.is_joined_mid_game() {
- actions.push(SendRoomData{
- to: c.id, teams: false,
- config: true, flags: false});
+ actions.push(SendRoomData {
+ to: c.id,
+ teams: false,
+ config: true,
+ flags: false,
+ });
for name in &info.left_teams {
- actions.push(TeamRemove(name.clone())
- .send(c.id).action());
+ actions.push(TeamRemove(name.clone()).send(c.id).action());
}
}
}
}
- let nicks: Vec<_> = server.clients.iter_mut()
+ let nicks: Vec<_> = server
+ .clients
+ .iter_mut()
.filter(|(_, c)| c.room_id == Some(room_id))
.map(|(_, c)| {
c.set_is_ready(c.is_master());
c.set_is_joined_mid_game(false);
c
- }).filter_map(|c| if !c.is_master() {
- Some(c.nick.clone())
- } else {
- None
- }).collect();
+ })
+ .filter_map(|c| {
+ if !c.is_master() {
+ Some(c.nick.clone())
+ } else {
+ None
+ }
+ })
+ .collect();
if !nicks.is_empty() {
let msg = if r.protocol_number < 38 {
@@ -627,8 +816,6 @@
Warn(msg) => {
run_action(server, client_id, Warning(msg).send_self().action());
}
- ProtocolError(msg) => {
- run_action(server, client_id, Error(msg).send_self().action())
- }
+ ProtocolError(msg) => run_action(server, client_id, Error(msg).send_self().action()),
}
}
--- a/rust/hedgewars-server/src/server/client.rs Sun Dec 16 00:09:20 2018 +0100
+++ b/rust/hedgewars-server/src/server/client.rs Sun Dec 16 00:12:29 2018 +0100
@@ -1,7 +1,7 @@
use super::coretypes::ClientId;
use bitflags::*;
-bitflags!{
+bitflags! {
pub struct ClientFlags: u8 {
const IS_ADMIN = 0b0000_0001;
const IS_MASTER = 0b0000_0010;
@@ -25,7 +25,7 @@
pub flags: ClientFlags,
pub teams_in_game: u8,
pub team_indices: Vec<u8>,
- pub clan: Option<u8>
+ pub clan: Option<u8>,
}
impl HWClient {
@@ -44,7 +44,7 @@
}
}
- fn contains(& self, mask: ClientFlags) -> bool {
+ fn contains(&self, mask: ClientFlags) -> bool {
self.flags.contains(mask)
}
@@ -52,17 +52,41 @@
self.flags.set(mask, value);
}
- pub fn is_admin(&self)-> bool { self.contains(ClientFlags::IS_ADMIN) }
- pub fn is_master(&self)-> bool { self.contains(ClientFlags::IS_MASTER) }
- pub fn is_ready(&self)-> bool { self.contains(ClientFlags::IS_READY) }
- pub fn is_in_game(&self)-> bool { self.contains(ClientFlags::IS_IN_GAME) }
- pub fn is_joined_mid_game(&self)-> bool { self.contains(ClientFlags::IS_JOINED_MID_GAME) }
- pub fn is_checker(&self)-> bool { self.contains(ClientFlags::IS_CHECKER) }
+ pub fn is_admin(&self) -> bool {
+ self.contains(ClientFlags::IS_ADMIN)
+ }
+ pub fn is_master(&self) -> bool {
+ self.contains(ClientFlags::IS_MASTER)
+ }
+ pub fn is_ready(&self) -> bool {
+ self.contains(ClientFlags::IS_READY)
+ }
+ pub fn is_in_game(&self) -> bool {
+ self.contains(ClientFlags::IS_IN_GAME)
+ }
+ pub fn is_joined_mid_game(&self) -> bool {
+ self.contains(ClientFlags::IS_JOINED_MID_GAME)
+ }
+ pub fn is_checker(&self) -> bool {
+ self.contains(ClientFlags::IS_CHECKER)
+ }
- pub fn set_is_admin(&mut self, value: bool) { self.set(ClientFlags::IS_ADMIN, value) }
- pub fn set_is_master(&mut self, value: bool) { self.set(ClientFlags::IS_MASTER, value) }
- pub fn set_is_ready(&mut self, value: bool) { self.set(ClientFlags::IS_READY, value) }
- pub fn set_is_in_game(&mut self, value: bool) { self.set(ClientFlags::IS_IN_GAME, value) }
- pub fn set_is_joined_mid_game(&mut self, value: bool) { self.set(ClientFlags::IS_JOINED_MID_GAME, value) }
- pub fn set_is_checker(&mut self, value: bool) { self.set(ClientFlags::IS_CHECKER, value) }
-}
\ No newline at end of file
+ pub fn set_is_admin(&mut self, value: bool) {
+ self.set(ClientFlags::IS_ADMIN, value)
+ }
+ pub fn set_is_master(&mut self, value: bool) {
+ self.set(ClientFlags::IS_MASTER, value)
+ }
+ pub fn set_is_ready(&mut self, value: bool) {
+ self.set(ClientFlags::IS_READY, value)
+ }
+ pub fn set_is_in_game(&mut self, value: bool) {
+ self.set(ClientFlags::IS_IN_GAME, value)
+ }
+ pub fn set_is_joined_mid_game(&mut self, value: bool) {
+ self.set(ClientFlags::IS_JOINED_MID_GAME, value)
+ }
+ pub fn set_is_checker(&mut self, value: bool) {
+ self.set(ClientFlags::IS_CHECKER, value)
+ }
+}
--- a/rust/hedgewars-server/src/server/core.rs Sun Dec 16 00:09:20 2018 +0100
+++ b/rust/hedgewars-server/src/server/core.rs Sun Dec 16 00:12:29 2018 +0100
@@ -1,15 +1,18 @@
-use slab;
-use crate::utils;
use super::{
+ actions,
+ actions::{Destination, PendingMessage},
+ client::HWClient,
+ coretypes::{ClientId, RoomId},
+ handlers,
io::HWServerIO,
- client::HWClient, room::HWRoom, actions, handlers,
- coretypes::{ClientId, RoomId},
- actions::{Destination, PendingMessage}
+ room::HWRoom,
};
use crate::protocol::messages::*;
-use rand::{RngCore, thread_rng};
-use base64::{encode};
+use crate::utils;
+use base64::encode;
use log::*;
+use rand::{thread_rng, RngCore};
+use slab;
type Slab<T> = slab::Slab<T>;
@@ -19,7 +22,7 @@
pub lobby_id: RoomId,
pub output: Vec<(Vec<ClientId>, HWServerMessage)>,
pub removed_clients: Vec<ClientId>,
- pub io: Box<dyn HWServerIO>
+ pub io: Box<dyn HWServerIO>,
}
impl HWServer {
@@ -27,11 +30,12 @@
let rooms = Slab::with_capacity(rooms_limit);
let clients = Slab::with_capacity(clients_limit);
let mut server = HWServer {
- clients, rooms,
+ clients,
+ rooms,
lobby_id: 0,
output: vec![],
removed_clients: vec![],
- io
+ io,
};
server.lobby_id = server.add_room();
server
@@ -48,13 +52,20 @@
let client = HWClient::new(entry.key(), encode(&salt));
entry.insert(client);
}
- self.send(key, &Destination::ToSelf, HWServerMessage::Connected(utils::PROTOCOL_VERSION));
+ self.send(
+ key,
+ &Destination::ToSelf,
+ HWServerMessage::Connected(utils::PROTOCOL_VERSION),
+ );
key
}
pub fn client_lost(&mut self, client_id: ClientId) {
- actions::run_action(self, client_id,
- actions::Action::ByeClient("Connection reset".to_string()));
+ actions::run_action(
+ self,
+ client_id,
+ actions::Action::ByeClient("Connection reset".to_string()),
+ );
}
pub fn add_room(&mut self) -> RoomId {
@@ -76,14 +87,19 @@
let mut ids = match *destination {
Destination::ToSelf => vec![client_id],
Destination::ToId(id) => vec![id],
- Destination::ToAll {room_id: Some(id), ..} =>
- self.room_clients(id),
- Destination::ToAll {protocol: Some(proto), ..} =>
- self.protocol_clients(proto),
- Destination::ToAll {..} =>
- self.clients.iter().map(|(id, _)| id).collect::<Vec<_>>()
+ Destination::ToAll {
+ room_id: Some(id), ..
+ } => self.room_clients(id),
+ Destination::ToAll {
+ protocol: Some(proto),
+ ..
+ } => self.protocol_clients(proto),
+ Destination::ToAll { .. } => self.clients.iter().map(|(id, _)| id).collect::<Vec<_>>(),
};
- if let Destination::ToAll {skip_self: true, ..} = destination {
+ if let Destination::ToAll {
+ skip_self: true, ..
+ } = destination
+ {
if let Some(index) = ids.iter().position(|id| *id == client_id) {
ids.remove(index);
}
@@ -91,7 +107,12 @@
ids
}
- pub fn send(&mut self, client_id: ClientId, destination: &Destination, message: HWServerMessage) {
+ pub fn send(
+ &mut self,
+ client_id: ClientId,
+ destination: &Destination,
+ message: HWServerMessage,
+ ) {
let ids = self.get_recipients(client_id, &destination);
self.output.push((ids, message));
}
@@ -102,32 +123,43 @@
}
}
- pub fn lobby(&self) -> &HWRoom { &self.rooms[self.lobby_id] }
+ pub fn lobby(&self) -> &HWRoom {
+ &self.rooms[self.lobby_id]
+ }
pub fn has_room(&self, name: &str) -> bool {
self.rooms.iter().any(|(_, r)| r.name == name)
}
pub fn find_room(&self, name: &str) -> Option<&HWRoom> {
- self.rooms.iter().find_map(|(_, r)| Some(r).filter(|r| r.name == name))
+ self.rooms
+ .iter()
+ .find_map(|(_, r)| Some(r).filter(|r| r.name == name))
}
pub fn find_room_mut(&mut self, name: &str) -> Option<&mut HWRoom> {
- self.rooms.iter_mut().find_map(|(_, r)| Some(r).filter(|r| r.name == name))
+ self.rooms
+ .iter_mut()
+ .find_map(|(_, r)| Some(r).filter(|r| r.name == name))
}
pub fn find_client(&self, nick: &str) -> Option<&HWClient> {
- self.clients.iter().find_map(|(_, c)| Some(c).filter(|c| c.nick == nick))
+ self.clients
+ .iter()
+ .find_map(|(_, c)| Some(c).filter(|c| c.nick == nick))
}
pub fn find_client_mut(&mut self, nick: &str) -> Option<&mut HWClient> {
- self.clients.iter_mut().find_map(|(_, c)| Some(c).filter(|c| c.nick == nick))
+ self.clients
+ .iter_mut()
+ .find_map(|(_, c)| Some(c).filter(|c| c.nick == nick))
}
pub fn select_clients<F>(&self, f: F) -> Vec<ClientId>
- where F: Fn(&(usize, &HWClient)) -> bool {
- self.clients.iter().filter(f)
- .map(|(_, c)| c.id).collect()
+ where
+ F: Fn(&(usize, &HWClient)) -> bool,
+ {
+ self.clients.iter().filter(f).map(|(_, c)| c.id).collect()
}
pub fn room_clients(&self, room_id: RoomId) -> Vec<ClientId> {
@@ -140,7 +172,7 @@
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.select_clients(|(id, c)| *id != self_id && c.room_id == room_id)
}
pub fn client_and_room(&mut self, client_id: ClientId) -> (&mut HWClient, Option<&mut HWRoom>) {
--- a/rust/hedgewars-server/src/server/coretypes.rs Sun Dec 16 00:09:20 2018 +0100
+++ b/rust/hedgewars-server/src/server/coretypes.rs Sun Dec 16 00:12:29 2018 +0100
@@ -23,7 +23,7 @@
Scheme(String, Vec<String>),
Script(String),
Theme(String),
- DrawnMap(String)
+ DrawnMap(String),
}
#[derive(PartialEq, Eq, Clone, Debug)]
@@ -51,7 +51,7 @@
Map(Option<String>),
Pause,
NewSeed,
- HedgehogsPerTeam(u8)
+ HedgehogsPerTeam(u8),
}
#[derive(Clone, Debug)]
@@ -59,14 +59,16 @@
pub ttl: u32,
pub voters: Vec<ClientId>,
pub votes: Vec<(ClientId, bool)>,
- pub kind: VoteType
+ pub kind: VoteType,
}
impl Voting {
pub fn new(kind: VoteType, voters: Vec<ClientId>) -> Voting {
Voting {
- kind, voters, ttl: 2,
- votes: Vec::new()
+ kind,
+ voters,
+ ttl: 2,
+ votes: Vec::new(),
}
}
-}
\ No newline at end of file
+}
--- a/rust/hedgewars-server/src/server/database.rs Sun Dec 16 00:09:20 2018 +0100
+++ b/rust/hedgewars-server/src/server/database.rs Sun Dec 16 00:12:29 2018 +0100
@@ -1,5 +1,5 @@
use mysql;
-use mysql::{params, error::Error, error::DriverError};
+use mysql::{error::DriverError, error::Error, params};
struct AccountInfo {
is_registered: bool,
@@ -46,17 +46,24 @@
fn store_stats(&mut self, stats: &ServerStatistics) -> Result<(), Error> {
if let Some(pool) = &self.pool {
- for mut stmt in pool.prepare(r"INSERT INTO gameserver_stats (players, rooms, last_update) VALUES (:players, :rooms, UNIX_TIMESTAMP())").into_iter() {
- stmt.execute(params!{
- "players" => stats.players,
- "rooms" => stats.rooms,
- })?;
- }
+ for mut stmt in pool
+ .prepare(
+ r"INSERT INTO gameserver_stats
+ (players, rooms, last_update)
+ VALUES
+ (:players, :rooms, UNIX_TIMESTAMP())",
+ )
+ .into_iter()
+ {
+ stmt.execute(params! {
+ "players" => stats.players,
+ "rooms" => stats.rooms,
+ })?;
+ }
Ok(())
} else {
Err(DriverError::SetupError.into())
}
-
}
fn store_achievements(&mut self, achievements: &Achievements) -> Result<(), ()> {
--- a/rust/hedgewars-server/src/server/handlers.rs Sun Dec 16 00:09:20 2018 +0100
+++ b/rust/hedgewars-server/src/server/handlers.rs Sun Dec 16 00:12:29 2018 +0100
@@ -2,43 +2,34 @@
use std::{io, io::Write};
use super::{
+ actions::{Action, Action::*},
core::HWServer,
- actions::{Action, Action::*},
- coretypes::ClientId
+ coretypes::ClientId,
};
-use crate::{
- protocol::messages::{
- HWProtocolMessage,
- HWServerMessage::*
- }
-};
+use crate::protocol::messages::{HWProtocolMessage, HWServerMessage::*};
use log::*;
-mod loggingin;
-mod lobby;
+mod checker;
+mod common;
mod inroom;
-mod common;
-mod checker;
+mod lobby;
+mod loggingin;
pub fn handle(server: &mut HWServer, client_id: ClientId, message: HWProtocolMessage) {
match message {
- HWProtocolMessage::Ping =>
- server.react(client_id, vec![Pong.send_self().action()]),
- HWProtocolMessage::Quit(Some(msg)) =>
- server.react(client_id, vec![ByeClient("User quit: ".to_string() + &msg)]),
- HWProtocolMessage::Quit(None) =>
- server.react(client_id, vec![ByeClient("User quit".to_string())]),
+ HWProtocolMessage::Ping => server.react(client_id, vec![Pong.send_self().action()]),
+ HWProtocolMessage::Quit(Some(msg)) => {
+ server.react(client_id, vec![ByeClient("User quit: ".to_string() + &msg)])
+ }
+ HWProtocolMessage::Quit(None) => {
+ server.react(client_id, vec![ByeClient("User quit".to_string())])
+ }
HWProtocolMessage::Malformed => warn!("Malformed/unknown message"),
HWProtocolMessage::Empty => warn!("Empty message"),
- _ => {
- match server.clients[client_id].room_id {
- None =>
- loggingin::handle(server, client_id, message),
- Some(id) if id == server.lobby_id =>
- lobby::handle(server, client_id, message),
- Some(id) =>
- inroom::handle(server, client_id, id, message)
- }
+ _ => match server.clients[client_id].room_id {
+ None => loggingin::handle(server, client_id, message),
+ Some(id) if id == server.lobby_id => lobby::handle(server, client_id, message),
+ Some(id) => inroom::handle(server, client_id, id, message),
},
}
}
--- a/rust/hedgewars-server/src/server/handlers/checker.rs Sun Dec 16 00:09:20 2018 +0100
+++ b/rust/hedgewars-server/src/server/handlers/checker.rs Sun Dec 16 00:12:29 2018 +0100
@@ -1,17 +1,12 @@
+use log::*;
use mio;
-use log::*;
use crate::{
- server::{
- core::HWServer,
- coretypes::ClientId,
- },
- protocol::messages::{
- HWProtocolMessage
- },
+ protocol::messages::HWProtocolMessage,
+ server::{core::HWServer, coretypes::ClientId},
};
-pub fn handle(server: & mut HWServer, client_id: ClientId, message: HWProtocolMessage) {
+pub fn handle(server: &mut HWServer, client_id: ClientId, message: HWProtocolMessage) {
match message {
_ => warn!("Unknown command"),
}
--- a/rust/hedgewars-server/src/server/handlers/common.rs Sun Dec 16 00:09:20 2018 +0100
+++ b/rust/hedgewars-server/src/server/handlers/common.rs Sun Dec 16 00:12:29 2018 +0100
@@ -1,10 +1,11 @@
use crate::{
- server::{actions::Action, core::HWServer},
protocol::messages::{
- HWProtocolMessage::{self, Rnd}, HWServerMessage::{self, ChatMsg},
- }
+ HWProtocolMessage::{self, Rnd},
+ HWServerMessage::{self, ChatMsg},
+ },
+ server::{actions::Action, core::HWServer},
};
-use rand::{self, Rng, thread_rng};
+use rand::{self, thread_rng, Rng};
pub fn rnd_reply(options: &[String]) -> HWServerMessage {
let mut rng = thread_rng();
@@ -25,7 +26,8 @@
use super::*;
use crate::protocol::messages::HWServerMessage::ChatMsg;
use crate::server::actions::{
- Action::{self, Send}, PendingMessage,
+ Action::{self, Send},
+ PendingMessage,
};
fn reply2string(r: HWServerMessage) -> String {
--- a/rust/hedgewars-server/src/server/handlers/inroom.rs Sun Dec 16 00:09:20 2018 +0100
+++ b/rust/hedgewars-server/src/server/handlers/inroom.rs Sun Dec 16 00:12:29 2018 +0100
@@ -1,36 +1,27 @@
use mio;
+use super::common::rnd_reply;
use crate::{
+ protocol::messages::{server_chat, HWProtocolMessage, HWServerMessage::*},
server::{
- coretypes::{
- ClientId, RoomId, Voting, VoteType, GameCfg,
- MAX_HEDGEHOGS_PER_TEAM
- },
+ actions::{Action, Action::*},
core::HWServer,
+ coretypes::{ClientId, GameCfg, RoomId, VoteType, Voting, MAX_HEDGEHOGS_PER_TEAM},
room::{HWRoom, RoomFlags},
- actions::{Action, Action::*}
},
- protocol::messages::{
- HWProtocolMessage,
- HWServerMessage::*,
- server_chat
- },
- utils::is_name_illegal
+ utils::is_name_illegal,
};
-use std::{
- mem::swap
-};
-use base64::{encode, decode};
-use super::common::rnd_reply;
+use base64::{decode, encode};
use log::*;
+use std::mem::swap;
#[derive(Clone)]
struct ByMsg<'a> {
- messages: &'a[u8]
+ messages: &'a [u8],
}
-impl <'a> Iterator for ByMsg<'a> {
- type Item = &'a[u8];
+impl<'a> Iterator for ByMsg<'a> {
+ type Item = &'a [u8];
fn next(&mut self) -> Option<<Self as Iterator>::Item> {
if let Some(size) = self.messages.get(0) {
@@ -44,7 +35,7 @@
}
fn by_msg(source: &[u8]) -> ByMsg {
- ByMsg {messages: source}
+ ByMsg { messages: source }
}
const VALID_MESSAGES: &[u8] =
@@ -54,13 +45,16 @@
#[cfg(canhazslicepatterns)]
fn is_msg_valid(msg: &[u8], team_indices: &[u8]) -> bool {
match msg {
- [size, typ, body..] => VALID_MESSAGES.contains(typ)
- && match body {
- [1...MAX_HEDGEHOGS_PER_TEAM, team, ..] if *typ == b'h' =>
- team_indices.contains(team),
- _ => *typ != b'h'
- },
- _ => false
+ [size, typ, body..] => {
+ VALID_MESSAGES.contains(typ)
+ && match body {
+ [1...MAX_HEDGEHOGS_PER_TEAM, team, ..] if *typ == b'h' => {
+ team_indices.contains(team)
+ }
+ _ => *typ != b'h',
+ }
+ }
+ _ => false,
}
}
@@ -77,17 +71,22 @@
}
fn is_msg_timed(msg: &[u8]) -> bool {
- msg.get(1).filter(|t| !NON_TIMED_MESSAGES.contains(t)).is_some()
+ msg.get(1)
+ .filter(|t| !NON_TIMED_MESSAGES.contains(t))
+ .is_some()
}
fn voting_description(kind: &VoteType) -> String {
- format!("New voting started: {}", match kind {
- VoteType::Kick(nick) => format!("kick {}", nick),
- VoteType::Map(name) => format!("map {}", name.as_ref().unwrap()),
- VoteType::Pause => "pause".to_string(),
- VoteType::NewSeed => "new seed".to_string(),
- VoteType::HedgehogsPerTeam(number) => format!("hedgehogs per team: {}", number)
- })
+ format!(
+ "New voting started: {}",
+ match kind {
+ VoteType::Kick(nick) => format!("kick {}", nick),
+ VoteType::Map(name) => format!("map {}", name.as_ref().unwrap()),
+ VoteType::Pause => "pause".to_string(),
+ VoteType::NewSeed => "new seed".to_string(),
+ VoteType::HedgehogsPerTeam(number) => format!("hedgehogs per team: {}", number),
+ }
+ )
}
fn room_message_flag(msg: &HWProtocolMessage) -> RoomFlags {
@@ -96,11 +95,16 @@
ToggleRestrictJoin => RoomFlags::RESTRICTED_JOIN,
ToggleRestrictTeams => RoomFlags::RESTRICTED_TEAM_ADD,
ToggleRegisteredOnly => RoomFlags::RESTRICTED_UNREGISTERED_PLAYERS,
- _ => RoomFlags::empty()
+ _ => RoomFlags::empty(),
}
}
-pub fn handle(server: &mut HWServer, client_id: ClientId, room_id: RoomId, message: HWProtocolMessage) {
+pub fn handle(
+ server: &mut HWServer,
+ client_id: ClientId,
+ room_id: RoomId,
+ message: HWProtocolMessage,
+) {
use crate::protocol::messages::HWProtocolMessage::*;
match message {
Part(None) => server.react(client_id, vec![
--- a/rust/hedgewars-server/src/server/handlers/lobby.rs Sun Dec 16 00:09:20 2018 +0100
+++ b/rust/hedgewars-server/src/server/handlers/lobby.rs Sun Dec 16 00:12:29 2018 +0100
@@ -1,47 +1,53 @@
use mio;
+use super::common::rnd_reply;
use crate::{
+ protocol::messages::{HWProtocolMessage, HWServerMessage::*},
server::{
+ actions::{Action, Action::*},
core::HWServer,
coretypes::ClientId,
- actions::{Action, Action::*}
},
- protocol::messages::{
- HWProtocolMessage,
- HWServerMessage::*
- },
- utils::is_name_illegal
+ utils::is_name_illegal,
};
-use super::common::rnd_reply;
use log::*;
pub fn handle(server: &mut HWServer, client_id: ClientId, message: HWProtocolMessage) {
use crate::protocol::messages::HWProtocolMessage::*;
match message {
CreateRoom(name, password) => {
- let actions =
- if is_name_illegal(&name) {
- vec![Warn("Illegal room name! A room name must be between 1-40 characters long, must not have a trailing or leading space and must not have any of these characters: $()*+?[]^{|}".to_string())]
- } else if server.has_room(&name) {
- vec![Warn("A room with the same name already exists.".to_string())]
- } else {
- let flags_msg = ClientFlags(
- "+hr".to_string(),
- vec![server.clients[client_id].nick.clone()]);
- vec![AddRoom(name, password),
- flags_msg.send_self().action()]
- };
+ let actions = if is_name_illegal(&name) {
+ vec![Warn("Illegal room name! A room name must be between 1-40 characters long, must not have a trailing or leading space and must not have any of these characters: $()*+?[]^{|}".to_string())]
+ } else if server.has_room(&name) {
+ vec![Warn(
+ "A room with the same name already exists.".to_string(),
+ )]
+ } else {
+ let flags_msg = ClientFlags(
+ "+hr".to_string(),
+ vec![server.clients[client_id].nick.clone()],
+ );
+ vec![AddRoom(name, password), flags_msg.send_self().action()]
+ };
server.react(client_id, actions);
- },
+ }
Chat(msg) => {
- let actions = vec![ChatMsg {nick: server.clients[client_id].nick.clone(), msg}
- .send_all().in_room(server.lobby_id).but_self().action()];
+ let actions = vec![ChatMsg {
+ nick: server.clients[client_id].nick.clone(),
+ msg,
+ }
+ .send_all()
+ .in_room(server.lobby_id)
+ .but_self()
+ .action()];
server.react(client_id, actions);
- },
+ }
JoinRoom(name, _password) => {
let room = server.rooms.iter().find(|(_, r)| r.name == name);
let room_id = room.map(|(_, r)| r.id);
- let nicks = server.clients.iter()
+ let nicks = server
+ .clients
+ .iter()
.filter(|(_, c)| c.room_id == room_id)
.map(|(_, c)| c.nick.clone())
.collect();
@@ -49,23 +55,26 @@
let actions = if let Some((_, r)) = room {
if c.protocol_number != r.protocol_number {
- vec![Warn("Room version incompatible to your Hedgewars version!".to_string())]
+ vec![Warn(
+ "Room version incompatible to your Hedgewars version!".to_string(),
+ )]
} else if r.is_join_restricted() {
- vec![Warn("Access denied. This room currently doesn't allow joining.".to_string())]
+ vec![Warn(
+ "Access denied. This room currently doesn't allow joining.".to_string(),
+ )]
} else if r.players_number == u8::max_value() {
vec![Warn("This room is already full".to_string())]
} else {
- vec![MoveToRoom(r.id),
- RoomJoined(nicks).send_self().action()]
+ vec![MoveToRoom(r.id), RoomJoined(nicks).send_self().action()]
}
} else {
vec![Warn("No such room.".to_string())]
};
server.react(client_id, actions);
- },
+ }
Rnd(v) => {
server.react(client_id, vec![rnd_reply(&v).send_self().action()]);
- },
+ }
List => warn!("Deprecated LIST message received"),
_ => warn!("Incorrect command in lobby state"),
}
--- a/rust/hedgewars-server/src/server/handlers/loggingin.rs Sun Dec 16 00:09:20 2018 +0100
+++ b/rust/hedgewars-server/src/server/handlers/loggingin.rs Sun Dec 16 00:12:29 2018 +0100
@@ -1,21 +1,19 @@
use mio;
use crate::{
+ protocol::messages::{HWProtocolMessage, HWServerMessage::*},
server::{
+ actions::{Action, Action::*},
client::HWClient,
core::HWServer,
coretypes::ClientId,
- actions::{Action, Action::*}
},
- protocol::messages::{
- HWProtocolMessage, HWServerMessage::*
- },
- utils::is_name_illegal
+ utils::is_name_illegal,
};
+use log::*;
#[cfg(feature = "official-server")]
use openssl::sha::sha1;
use std::fmt::{Formatter, LowerHex};
-use log::*;
#[derive(PartialEq)]
struct Sha1Digest([u8; 20]);
@@ -31,29 +29,27 @@
#[cfg(feature = "official-server")]
fn get_hash(client: &HWClient, salt1: &str, salt2: &str) -> Sha1Digest {
- let s = format!("{}{}{}{}{}", salt1, salt2,
- client.web_password, client.protocol_number, "!hedgewars");
+ let s = format!(
+ "{}{}{}{}{}",
+ salt1, salt2, client.web_password, client.protocol_number, "!hedgewars"
+ );
Sha1Digest(sha1(s.as_bytes()))
}
-pub fn handle(server: & mut HWServer, client_id: ClientId, message: HWProtocolMessage) {
+pub fn handle(server: &mut HWServer, client_id: ClientId, message: HWProtocolMessage) {
match message {
HWProtocolMessage::Nick(nick) => {
let client = &mut server.clients[client_id];
debug!("{} {}", nick, is_name_illegal(&nick));
let actions = if client.room_id != None {
unreachable!()
- }
- else if !client.nick.is_empty() {
+ } else if !client.nick.is_empty() {
vec![ProtocolError("Nickname already provided.".to_string())]
- }
- else if is_name_illegal(&nick) {
+ } else if is_name_illegal(&nick) {
vec![ByeClient("Illegal nickname! Nicknames must be between 1-40 characters long, must not have a trailing or leading space and must not have any of these characters: $()*+?[]^{|}".to_string())]
- }
- else {
+ } else {
client.nick = nick.clone();
- vec![Nick(nick).send_self().action(),
- CheckRegistered]
+ vec![Nick(nick).send_self().action(), CheckRegistered]
};
server.react(client_id, actions);
@@ -62,14 +58,11 @@
let client = &mut server.clients[client_id];
let actions = if client.protocol_number != 0 {
vec![ProtocolError("Protocol already known.".to_string())]
- }
- else if proto == 0 {
+ } else if proto == 0 {
vec![ProtocolError("Bad number.".to_string())]
- }
- else {
+ } else {
client.protocol_number = proto;
- vec![Proto(proto).send_self().action(),
- CheckRegistered]
+ vec![Proto(proto).send_self().action(), CheckRegistered]
};
server.react(client_id, actions);
}
@@ -80,8 +73,12 @@
let client_hash = get_hash(c, &salt, &c.server_salt);
let server_hash = get_hash(c, &c.server_salt, &salt);
let actions = if client_hash == server_hash {
- vec![ServerAuth(format!("{:x}", server_hash)).send_self().action(),
- JoinLobby]
+ vec![
+ ServerAuth(format!("{:x}", server_hash))
+ .send_self()
+ .action(),
+ JoinLobby,
+ ]
} else {
vec![ByeClient("Authentication failed".to_string())]
};
--- a/rust/hedgewars-server/src/server/io.rs Sun Dec 16 00:09:20 2018 +0100
+++ b/rust/hedgewars-server/src/server/io.rs Sun Dec 16 00:12:29 2018 +0100
@@ -1,6 +1,6 @@
use std::{
fs::{File, OpenOptions},
- io::{Read, Write, Result, Error, ErrorKind}
+ io::{Error, ErrorKind, Read, Result, Write},
};
pub trait HWServerIO {
@@ -46,4 +46,4 @@
reader.read_to_string(&mut result)?;
Ok(result)
}
-}
\ No newline at end of file
+}
--- a/rust/hedgewars-server/src/server/network.rs Sun Dec 16 00:09:20 2018 +0100
+++ b/rust/hedgewars-server/src/server/network.rs Sun Dec 16 00:12:29 2018 +0100
@@ -1,37 +1,33 @@
extern crate slab;
use std::{
- io, io::{Error, ErrorKind, Read, Write},
- net::{SocketAddr, IpAddr, Ipv4Addr},
collections::HashSet,
- mem::{swap, replace}
+ io,
+ io::{Error, ErrorKind, Read, Write},
+ mem::{replace, swap},
+ net::{IpAddr, Ipv4Addr, SocketAddr},
};
+use log::*;
use mio::{
- net::{TcpStream, TcpListener},
- Poll, PollOpt, Ready, Token
+ net::{TcpListener, TcpStream},
+ Poll, PollOpt, Ready, Token,
};
use netbuf;
use slab::Slab;
-use log::*;
+use super::{core::HWServer, coretypes::ClientId, io::FileServerIO};
use crate::{
+ protocol::{messages::*, ProtocolDecoder},
utils,
- protocol::{ProtocolDecoder, messages::*}
-};
-use super::{
- io::FileServerIO,
- core::{HWServer},
- coretypes::ClientId
};
#[cfg(feature = "tls-connections")]
use openssl::{
+ error::ErrorStack,
ssl::{
- SslMethod, SslContext, Ssl, SslContextBuilder,
- SslVerifyMode, SslFiletype, SslOptions,
- SslStreamBuilder, HandshakeError, MidHandshakeSslStream, SslStream
+ HandshakeError, MidHandshakeSslStream, Ssl, SslContext, SslContextBuilder, SslFiletype,
+ SslMethod, SslOptions, SslStream, SslStreamBuilder, SslVerifyMode,
},
- error::ErrorStack
};
const MAX_BYTES_PER_READ: usize = 2048;
@@ -48,13 +44,13 @@
#[cfg(not(feature = "tls-connections"))]
pub enum ClientSocket {
- Plain(TcpStream)
+ Plain(TcpStream),
}
#[cfg(feature = "tls-connections")]
pub enum ClientSocket {
SslHandshake(Option<MidHandshakeSslStream<TcpStream>>),
- SslStream(SslStream<TcpStream>)
+ SslStream(SslStream<TcpStream>),
}
impl ClientSocket {
@@ -68,7 +64,7 @@
match self {
ClientSocket::SslHandshake(Some(builder)) => builder.get_ref(),
ClientSocket::SslHandshake(None) => unreachable!(),
- ClientSocket::SslStream(ssl_stream) => ssl_stream.get_ref()
+ ClientSocket::SslStream(ssl_stream) => ssl_stream.get_ref(),
}
}
}
@@ -78,24 +74,32 @@
socket: ClientSocket,
peer_addr: SocketAddr,
decoder: ProtocolDecoder,
- buf_out: netbuf::Buf
+ buf_out: netbuf::Buf,
}
impl NetworkClient {
pub fn new(id: ClientId, socket: ClientSocket, peer_addr: SocketAddr) -> NetworkClient {
NetworkClient {
- id, socket, peer_addr,
+ id,
+ socket,
+ peer_addr,
decoder: ProtocolDecoder::new(),
- buf_out: netbuf::Buf::new()
+ buf_out: netbuf::Buf::new(),
}
}
#[cfg(feature = "tls-connections")]
- fn handshake_impl(&mut self, handshake: MidHandshakeSslStream<TcpStream>) -> io::Result<NetworkClientState> {
+ fn handshake_impl(
+ &mut self,
+ handshake: MidHandshakeSslStream<TcpStream>,
+ ) -> io::Result<NetworkClientState> {
match handshake.handshake() {
Ok(stream) => {
self.socket = ClientSocket::SslStream(stream);
- debug!("TLS handshake with {} ({}) completed", self.id, self.peer_addr);
+ debug!(
+ "TLS handshake with {} ({}) completed",
+ self.id, self.peer_addr
+ );
Ok(NetworkClientState::Idle)
}
Err(HandshakeError::WouldBlock(new_handshake)) => {
@@ -107,12 +111,16 @@
debug!("TLS handshake with {} ({}) failed", self.id, self.peer_addr);
Err(Error::new(ErrorKind::Other, "Connection failure"))
}
- Err(HandshakeError::SetupFailure(_)) => unreachable!()
+ Err(HandshakeError::SetupFailure(_)) => unreachable!(),
}
}
- fn read_impl<R: Read>(decoder: &mut ProtocolDecoder, source: &mut R,
- id: ClientId, addr: &SocketAddr) -> NetworkResult<Vec<HWProtocolMessage>> {
+ fn read_impl<R: Read>(
+ decoder: &mut ProtocolDecoder,
+ source: &mut R,
+ id: ClientId,
+ addr: &SocketAddr,
+ ) -> NetworkResult<Vec<HWProtocolMessage>> {
let mut bytes_read = 0;
let result = loop {
match decoder.read_from(source) {
@@ -127,21 +135,19 @@
(decoder.extract_messages(), NetworkClientState::NeedsRead)
};
break Ok(result);
- }
- else if bytes_read >= MAX_BYTES_PER_READ {
- break Ok((decoder.extract_messages(), NetworkClientState::NeedsRead))
+ } else if bytes_read >= MAX_BYTES_PER_READ {
+ break Ok((decoder.extract_messages(), NetworkClientState::NeedsRead));
}
}
Err(ref error) if error.kind() == ErrorKind::WouldBlock => {
- let messages = if bytes_read == 0 {
+ let messages = if bytes_read == 0 {
Vec::new()
} else {
decoder.extract_messages()
};
break Ok((messages, NetworkClientState::Idle));
}
- Err(error) =>
- break Err(error)
+ Err(error) => break Err(error),
}
};
decoder.sweep();
@@ -151,8 +157,9 @@
pub fn read(&mut self) -> NetworkResult<Vec<HWProtocolMessage>> {
#[cfg(not(feature = "tls-connections"))]
match self.socket {
- ClientSocket::Plain(ref mut stream) =>
- NetworkClient::read_impl(&mut self.decoder, stream, self.id, &self.peer_addr),
+ ClientSocket::Plain(ref mut stream) => {
+ NetworkClient::read_impl(&mut self.decoder, stream, self.id, &self.peer_addr)
+ }
}
#[cfg(feature = "tls-connections")]
@@ -160,24 +167,27 @@
ClientSocket::SslHandshake(ref mut handshake_opt) => {
let handshake = std::mem::replace(handshake_opt, None).unwrap();
Ok((Vec::new(), self.handshake_impl(handshake)?))
- },
- ClientSocket::SslStream(ref mut stream) =>
+ }
+ ClientSocket::SslStream(ref mut stream) => {
NetworkClient::read_impl(&mut self.decoder, stream, self.id, &self.peer_addr)
+ }
}
}
fn write_impl<W: Write>(buf_out: &mut netbuf::Buf, destination: &mut W) -> NetworkResult<()> {
let result = loop {
match buf_out.write_to(destination) {
- Ok(bytes) if buf_out.is_empty() || bytes == 0 =>
- break Ok(((), NetworkClientState::Idle)),
+ Ok(bytes) if buf_out.is_empty() || bytes == 0 => {
+ break Ok(((), NetworkClientState::Idle))
+ }
Ok(_) => (),
- Err(ref error) if error.kind() == ErrorKind::Interrupted
- || error.kind() == ErrorKind::WouldBlock => {
+ Err(ref error)
+ if error.kind() == ErrorKind::Interrupted
+ || error.kind() == ErrorKind::WouldBlock =>
+ {
break Ok(((), NetworkClientState::NeedsWrite));
- },
- Err(error) =>
- break Err(error)
+ }
+ Err(error) => break Err(error),
}
};
result
@@ -187,18 +197,21 @@
let result = {
#[cfg(not(feature = "tls-connections"))]
match self.socket {
- ClientSocket::Plain(ref mut stream) =>
+ ClientSocket::Plain(ref mut stream) => {
NetworkClient::write_impl(&mut self.buf_out, stream)
+ }
}
- #[cfg(feature = "tls-connections")] {
+ #[cfg(feature = "tls-connections")]
+ {
match self.socket {
ClientSocket::SslHandshake(ref mut handshake_opt) => {
let handshake = std::mem::replace(handshake_opt, None).unwrap();
Ok(((), self.handshake_impl(handshake)?))
}
- ClientSocket::SslStream(ref mut stream) =>
+ ClientSocket::SslStream(ref mut stream) => {
NetworkClient::write_impl(&mut self.buf_out, stream)
+ }
}
}
};
@@ -222,7 +235,7 @@
#[cfg(feature = "tls-connections")]
struct ServerSsl {
- context: SslContext
+ context: SslContext,
}
pub struct NetworkLayer {
@@ -232,7 +245,7 @@
pending: HashSet<(ClientId, NetworkClientState)>,
pending_cache: Vec<(ClientId, NetworkClientState)>,
#[cfg(feature = "tls-connections")]
- ssl: ServerSsl
+ ssl: ServerSsl,
}
impl NetworkLayer {
@@ -243,9 +256,13 @@
let pending_cache = Vec::with_capacity(2 * clients_limit);
NetworkLayer {
- listener, server, clients, pending, pending_cache,
+ listener,
+ server,
+ clients,
+ pending,
+ pending_cache,
#[cfg(feature = "tls-connections")]
- ssl: NetworkLayer::create_ssl_context()
+ ssl: NetworkLayer::create_ssl_context(),
}
}
@@ -254,16 +271,26 @@
let mut builder = SslContextBuilder::new(SslMethod::tls()).unwrap();
builder.set_verify(SslVerifyMode::NONE);
builder.set_read_ahead(true);
- builder.set_certificate_file("ssl/cert.pem", SslFiletype::PEM).unwrap();
- builder.set_private_key_file("ssl/key.pem", SslFiletype::PEM).unwrap();
+ builder
+ .set_certificate_file("ssl/cert.pem", SslFiletype::PEM)
+ .unwrap();
+ builder
+ .set_private_key_file("ssl/key.pem", SslFiletype::PEM)
+ .unwrap();
builder.set_options(SslOptions::NO_COMPRESSION);
builder.set_cipher_list("DEFAULT:!LOW:!RC4:!EXP").unwrap();
- ServerSsl { context: builder.build() }
+ ServerSsl {
+ context: builder.build(),
+ }
}
pub fn register_server(&self, poll: &Poll) -> io::Result<()> {
- poll.register(&self.listener, utils::SERVER, Ready::readable(),
- PollOpt::edge())
+ poll.register(
+ &self.listener,
+ utils::SERVER,
+ Ready::readable(),
+ PollOpt::edge(),
+ )
}
fn deregister_client(&mut self, poll: &Poll, id: ClientId) {
@@ -279,11 +306,20 @@
}
}
- fn register_client(&mut self, poll: &Poll, id: ClientId, client_socket: ClientSocket, addr: SocketAddr) {
- poll.register(client_socket.inner(), Token(id),
- Ready::readable() | Ready::writable(),
- PollOpt::edge())
- .expect("could not register socket with event loop");
+ fn register_client(
+ &mut self,
+ poll: &Poll,
+ id: ClientId,
+ client_socket: ClientSocket,
+ addr: SocketAddr,
+ ) {
+ poll.register(
+ client_socket.inner(),
+ Token(id),
+ Ready::readable() | Ready::writable(),
+ PollOpt::edge(),
+ )
+ .expect("could not register socket with event loop");
let entry = self.clients.vacant_entry();
let client = NetworkClient::new(id, client_socket, addr);
@@ -299,26 +335,29 @@
for client_id in clients {
if let Some(client) = self.clients.get_mut(client_id) {
client.send_string(&msg_string);
- self.pending.insert((client_id, NetworkClientState::NeedsWrite));
+ self.pending
+ .insert((client_id, NetworkClientState::NeedsWrite));
}
}
}
}
fn create_client_socket(&self, socket: TcpStream) -> io::Result<ClientSocket> {
- #[cfg(not(feature = "tls-connections"))] {
+ #[cfg(not(feature = "tls-connections"))]
+ {
Ok(ClientSocket::Plain(socket))
}
- #[cfg(feature = "tls-connections")] {
+ #[cfg(feature = "tls-connections")]
+ {
let ssl = Ssl::new(&self.ssl.context).unwrap();
let mut builder = SslStreamBuilder::new(ssl, socket);
builder.set_accept_state();
match builder.handshake() {
- Ok(stream) =>
- Ok(ClientSocket::SslStream(stream)),
- Err(HandshakeError::WouldBlock(stream)) =>
- Ok(ClientSocket::SslHandshake(Some(stream))),
+ Ok(stream) => Ok(ClientSocket::SslStream(stream)),
+ Err(HandshakeError::WouldBlock(stream)) => {
+ Ok(ClientSocket::SslHandshake(Some(stream)))
+ }
Err(e) => {
debug!("OpenSSL handshake failed: {}", e);
Err(Error::new(ErrorKind::Other, "Connection failure"))
@@ -332,13 +371,24 @@
info!("Connected: {}", addr);
let client_id = self.server.add_client();
- self.register_client(poll, client_id, self.create_client_socket(client_socket)?, addr);
+ self.register_client(
+ poll,
+ client_id,
+ self.create_client_socket(client_socket)?,
+ addr,
+ );
self.flush_server_messages();
Ok(())
}
- fn operation_failed(&mut self, poll: &Poll, client_id: ClientId, error: &Error, msg: &str) -> io::Result<()> {
+ fn operation_failed(
+ &mut self,
+ poll: &Poll,
+ client_id: ClientId,
+ error: &Error,
+ msg: &str,
+ ) -> io::Result<()> {
let addr = if let Some(ref mut client) = self.clients.get_mut(client_id) {
client.peer_addr
} else {
@@ -348,15 +398,13 @@
self.client_error(poll, client_id)
}
- pub fn client_readable(&mut self, poll: &Poll,
- client_id: ClientId) -> io::Result<()> {
- let messages =
- if let Some(ref mut client) = self.clients.get_mut(client_id) {
- client.read()
- } else {
- warn!("invalid readable client: {}", client_id);
- Ok((Vec::new(), NetworkClientState::Idle))
- };
+ pub fn client_readable(&mut self, poll: &Poll, client_id: ClientId) -> io::Result<()> {
+ let messages = if let Some(ref mut client) = self.clients.get_mut(client_id) {
+ client.read()
+ } else {
+ warn!("invalid readable client: {}", client_id);
+ Ok((Vec::new(), NetworkClientState::Idle))
+ };
match messages {
Ok((messages, state)) => {
@@ -366,15 +414,17 @@
match state {
NetworkClientState::NeedsRead => {
self.pending.insert((client_id, state));
- },
- NetworkClientState::Closed =>
- self.client_error(&poll, client_id)?,
+ }
+ NetworkClientState::Closed => self.client_error(&poll, client_id)?,
_ => {}
};
}
Err(e) => self.operation_failed(
- poll, client_id, &e,
- "Error while reading from client socket")?
+ poll,
+ client_id,
+ &e,
+ "Error while reading from client socket",
+ )?,
}
self.flush_server_messages();
@@ -389,31 +439,28 @@
Ok(())
}
- pub fn client_writable(&mut self, poll: &Poll,
- client_id: ClientId) -> io::Result<()> {
- let result =
- if let Some(ref mut client) = self.clients.get_mut(client_id) {
- client.write()
- } else {
- warn!("invalid writable client: {}", client_id);
- Ok(((), NetworkClientState::Idle))
- };
+ pub fn client_writable(&mut self, poll: &Poll, client_id: ClientId) -> io::Result<()> {
+ let result = if let Some(ref mut client) = self.clients.get_mut(client_id) {
+ client.write()
+ } else {
+ warn!("invalid writable client: {}", client_id);
+ Ok(((), NetworkClientState::Idle))
+ };
match result {
Ok(((), state)) if state == NetworkClientState::NeedsWrite => {
self.pending.insert((client_id, state));
- },
+ }
Ok(_) => {}
- Err(e) => self.operation_failed(
- poll, client_id, &e,
- "Error while writing to client socket")?
+ Err(e) => {
+ self.operation_failed(poll, client_id, &e, "Error while writing to client socket")?
+ }
}
Ok(())
}
- pub fn client_error(&mut self, poll: &Poll,
- client_id: ClientId) -> io::Result<()> {
+ pub fn client_error(&mut self, poll: &Poll, client_id: ClientId) -> io::Result<()> {
self.deregister_client(poll, client_id);
self.server.client_lost(client_id);
@@ -430,10 +477,8 @@
cache.extend(self.pending.drain());
for (id, state) in cache.drain(..) {
match state {
- NetworkClientState::NeedsRead =>
- self.client_readable(poll, id)?,
- NetworkClientState::NeedsWrite =>
- self.client_writable(poll, id)?,
+ NetworkClientState::NeedsRead => self.client_readable(poll, id)?,
+ NetworkClientState::NeedsWrite => self.client_writable(poll, id)?,
_ => {}
}
}
--- a/rust/hedgewars-server/src/server/room.rs Sun Dec 16 00:09:20 2018 +0100
+++ b/rust/hedgewars-server/src/server/room.rs Sun Dec 16 00:12:29 2018 +0100
@@ -1,32 +1,26 @@
-use std::{
- iter, collections::HashMap
-};
use crate::server::{
- coretypes::{
- ClientId, RoomId, TeamInfo, GameCfg, GameCfg::*, Voting,
- MAX_HEDGEHOGS_PER_TEAM
- },
- client::{HWClient}
+ client::HWClient,
+ coretypes::{ClientId, GameCfg, GameCfg::*, RoomId, TeamInfo, Voting, MAX_HEDGEHOGS_PER_TEAM},
};
use bitflags::*;
-use serde::{Serialize, Deserialize};
-use serde_derive::{Serialize, Deserialize};
+use serde::{Deserialize, Serialize};
+use serde_derive::{Deserialize, Serialize};
use serde_yaml;
+use std::{collections::HashMap, iter};
const MAX_TEAMS_IN_ROOM: u8 = 8;
-const MAX_HEDGEHOGS_IN_ROOM: u8 =
- MAX_HEDGEHOGS_PER_TEAM * MAX_HEDGEHOGS_PER_TEAM;
+const MAX_HEDGEHOGS_IN_ROOM: u8 = MAX_HEDGEHOGS_PER_TEAM * MAX_HEDGEHOGS_PER_TEAM;
#[derive(Clone, Serialize, Deserialize)]
struct Ammo {
name: String,
- settings: Option<String>
+ settings: Option<String>,
}
#[derive(Clone, Serialize, Deserialize)]
struct Scheme {
name: String,
- settings: Vec<String>
+ settings: Vec<String>,
}
#[derive(Clone, Serialize, Deserialize)]
@@ -42,7 +36,7 @@
scheme: Scheme,
script: String,
theme: String,
- drawn_map: Option<String>
+ drawn_map: Option<String>,
}
impl RoomConfig {
@@ -55,25 +49,40 @@
seed: "seed".to_string(),
template: 0,
- ammo: Ammo {name: "Default".to_string(), settings: None },
- scheme: Scheme {name: "Default".to_string(), settings: Vec::new() },
+ ammo: Ammo {
+ name: "Default".to_string(),
+ settings: None,
+ },
+ scheme: Scheme {
+ name: "Default".to_string(),
+ settings: Vec::new(),
+ },
script: "Normal".to_string(),
theme: "\u{1f994}".to_string(),
- drawn_map: None
+ drawn_map: None,
}
}
}
-fn client_teams_impl(teams: &[(ClientId, TeamInfo)], client_id: ClientId)
- -> impl Iterator<Item = &TeamInfo> + Clone
-{
- teams.iter().filter(move |(id, _)| *id == client_id).map(|(_, t)| t)
+fn client_teams_impl(
+ teams: &[(ClientId, TeamInfo)],
+ client_id: ClientId,
+) -> impl Iterator<Item = &TeamInfo> + Clone {
+ teams
+ .iter()
+ .filter(move |(id, _)| *id == client_id)
+ .map(|(_, t)| t)
}
fn map_config_from(c: &RoomConfig) -> Vec<String> {
- vec![c.feature_size.to_string(), c.map_type.to_string(),
- c.map_generator.to_string(), c.maze_size.to_string(),
- c.seed.to_string(), c.template.to_string()]
+ vec![
+ c.feature_size.to_string(),
+ c.map_type.to_string(),
+ c.map_generator.to_string(),
+ c.maze_size.to_string(),
+ c.seed.to_string(),
+ c.template.to_string(),
+ ]
}
fn game_config_from(c: &RoomConfig) -> Vec<GameCfg> {
@@ -82,7 +91,8 @@
Ammo(c.ammo.name.to_string(), c.ammo.settings.clone()),
Scheme(c.scheme.name.to_string(), c.scheme.settings.clone()),
Script(c.script.to_string()),
- Theme(c.theme.to_string())];
+ Theme(c.theme.to_string()),
+ ];
if let Some(ref m) = c.drawn_map {
v.push(DrawnMap(m.to_string()))
}
@@ -96,7 +106,7 @@
pub msg_log: Vec<String>,
pub sync_msg: Option<String>,
pub is_paused: bool,
- config: RoomConfig
+ config: RoomConfig,
}
impl GameInfo {
@@ -108,7 +118,7 @@
is_paused: false,
teams_in_game: teams.len() as u8,
teams_at_start: teams,
- config
+ config,
}
}
@@ -120,10 +130,10 @@
#[derive(Serialize, Deserialize)]
pub struct RoomSave {
pub location: String,
- config: RoomConfig
+ config: RoomConfig,
}
-bitflags!{
+bitflags! {
pub struct RoomFlags: u8 {
const FIXED = 0b0000_0001;
const RESTRICTED_JOIN = 0b0000_0010;
@@ -149,7 +159,7 @@
config: RoomConfig,
pub voting: Option<Voting>,
pub saves: HashMap<String, RoomSave>,
- pub game_info: Option<GameInfo>
+ pub game_info: Option<GameInfo>,
}
impl HWRoom {
@@ -170,7 +180,7 @@
config: RoomConfig::new(),
voting: None,
saves: HashMap::new(),
- game_info: None
+ game_info: None,
}
}
@@ -182,17 +192,27 @@
MAX_HEDGEHOGS_IN_ROOM - self.hedgehogs_number()
}
- pub fn add_team(&mut self, owner_id: ClientId, mut team: TeamInfo, preserve_color: bool) -> &TeamInfo {
+ pub fn add_team(
+ &mut self,
+ owner_id: ClientId,
+ mut team: TeamInfo,
+ preserve_color: bool,
+ ) -> &TeamInfo {
if !preserve_color {
- team.color = iter::repeat(()).enumerate()
- .map(|(i, _)| i as u8).take(u8::max_value() as usize + 1)
+ team.color = iter::repeat(())
+ .enumerate()
+ .map(|(i, _)| i as u8)
+ .take(u8::max_value() as usize + 1)
.find(|i| self.teams.iter().all(|(_, t)| t.color != *i))
.unwrap_or(0u8)
};
team.hedgehogs_number = if self.teams.is_empty() {
self.default_hedgehog_number
} else {
- self.teams[0].1.hedgehogs_number.min(self.addable_hedgehogs())
+ self.teams[0]
+ .1
+ .hedgehogs_number
+ .min(self.addable_hedgehogs())
};
self.teams.push((owner_id, team));
&self.teams.last().unwrap().1
@@ -208,27 +228,36 @@
let mut names = Vec::new();
let teams = match self.game_info {
Some(ref mut info) => &mut info.teams_at_start,
- None => &mut self.teams
+ None => &mut self.teams,
};
if teams.len() as u8 * n <= MAX_HEDGEHOGS_IN_ROOM {
for (_, team) in teams.iter_mut() {
team.hedgehogs_number = n;
names.push(team.name.clone())
- };
+ }
self.default_hedgehog_number = n;
}
names
}
pub fn find_team_and_owner_mut<F>(&mut self, f: F) -> Option<(ClientId, &mut TeamInfo)>
- where F: Fn(&TeamInfo) -> bool {
- self.teams.iter_mut().find(|(_, t)| f(t)).map(|(id, t)| (*id, t))
+ where
+ F: Fn(&TeamInfo) -> bool,
+ {
+ self.teams
+ .iter_mut()
+ .find(|(_, t)| f(t))
+ .map(|(id, t)| (*id, t))
}
pub fn find_team<F>(&self, f: F) -> Option<&TeamInfo>
- where F: Fn(&TeamInfo) -> bool {
- self.teams.iter().find_map(|(_, t)| Some(t).filter(|t| f(&t)))
+ where
+ F: Fn(&TeamInfo) -> bool,
+ {
+ self.teams
+ .iter()
+ .find_map(|(_, t)| Some(t).filter(|t| f(&t)))
}
pub fn client_teams(&self, client_id: ClientId) -> impl Iterator<Item = &TeamInfo> {
@@ -236,13 +265,18 @@
}
pub fn client_team_indices(&self, client_id: ClientId) -> Vec<u8> {
- self.teams.iter().enumerate()
+ self.teams
+ .iter()
+ .enumerate()
.filter(move |(_, (id, _))| *id == client_id)
- .map(|(i, _)| i as u8).collect()
+ .map(|(i, _)| i as u8)
+ .collect()
}
pub fn find_team_owner(&self, team_name: &str) -> Option<(ClientId, &str)> {
- self.teams.iter().find(|(_, t)| t.name == team_name)
+ self.teams
+ .iter()
+ .find(|(_, t)| t.name == team_name)
.map(|(id, t)| (*id, &t.name[..]))
}
@@ -251,8 +285,8 @@
}
pub fn has_multiple_clans(&self) -> bool {
- self.teams.iter().min_by_key(|(_, t)| t.color) !=
- self.teams.iter().max_by_key(|(_, t)| t.color)
+ self.teams.iter().min_by_key(|(_, t)| t.color)
+ != self.teams.iter().max_by_key(|(_, t)| t.color)
}
pub fn set_config(&mut self, cfg: GameCfg) {
@@ -265,18 +299,27 @@
Seed(s) => c.seed = s,
Template(t) => c.template = t,
- Ammo(n, s) => c.ammo = Ammo {name: n, settings: s},
- Scheme(n, s) => c.scheme = Scheme {name: n, settings: s},
+ Ammo(n, s) => {
+ c.ammo = Ammo {
+ name: n,
+ settings: s,
+ }
+ }
+ Scheme(n, s) => {
+ c.scheme = Scheme {
+ name: n,
+ settings: s,
+ }
+ }
Script(s) => c.script = s,
Theme(t) => c.theme = t,
- DrawnMap(m) => c.drawn_map = Some(m)
+ DrawnMap(m) => c.drawn_map = Some(m),
};
}
pub fn start_round(&mut self) {
if self.game_info.is_none() {
- self.game_info = Some(GameInfo::new(
- self.teams.clone(), self.config.clone()));
+ self.game_info = Some(GameInfo::new(self.teams.clone(), self.config.clone()));
}
}
@@ -290,7 +333,8 @@
self.flags.contains(RoomFlags::RESTRICTED_TEAM_ADD)
}
pub fn are_unregistered_players_restricted(&self) -> bool {
- self.flags.contains(RoomFlags::RESTRICTED_UNREGISTERED_PLAYERS)
+ self.flags
+ .contains(RoomFlags::RESTRICTED_UNREGISTERED_PLAYERS)
}
pub fn set_is_fixed(&mut self, value: bool) {
@@ -303,14 +347,21 @@
self.flags.set(RoomFlags::RESTRICTED_TEAM_ADD, value)
}
pub fn set_unregistered_players_restriction(&mut self, value: bool) {
- self.flags.set(RoomFlags::RESTRICTED_UNREGISTERED_PLAYERS, value)
+ self.flags
+ .set(RoomFlags::RESTRICTED_UNREGISTERED_PLAYERS, value)
}
fn flags_string(&self) -> String {
let mut result = "-".to_string();
- if self.game_info.is_some() { result += "g" }
- if self.password.is_some() { result += "p" }
- if self.is_join_restricted() { result += "j" }
+ if self.game_info.is_some() {
+ result += "g"
+ }
+ if self.password.is_some() {
+ result += "p"
+ }
+ if self.is_join_restricted() {
+ result += "j"
+ }
if self.are_unregistered_players_restricted() {
result += "r"
}
@@ -328,26 +379,32 @@
c.map_type.to_string(),
c.script.to_string(),
c.scheme.name.to_string(),
- c.ammo.name.to_string()
+ c.ammo.name.to_string(),
]
}
pub fn map_config(&self) -> Vec<String> {
match self.game_info {
Some(ref info) => map_config_from(&info.config),
- None => map_config_from(&self.config)
+ None => map_config_from(&self.config),
}
}
pub fn game_config(&self) -> Vec<GameCfg> {
match self.game_info {
Some(ref info) => game_config_from(&info.config),
- None => game_config_from(&self.config)
+ None => game_config_from(&self.config),
}
}
pub fn save_config(&mut self, name: String, location: String) {
- self.saves.insert(name, RoomSave { location, config: self.config.clone() });
+ self.saves.insert(
+ name,
+ RoomSave {
+ location,
+ config: self.config.clone(),
+ },
+ );
}
pub fn load_config(&mut self, name: &str) -> Option<&str> {
@@ -368,10 +425,12 @@
}
pub fn set_saves(&mut self, text: &str) -> Result<(), serde_yaml::Error> {
- serde_yaml::from_str::<(String, HashMap<String, RoomSave>)>(text).map(|(greeting, saves)| {
- self.greeting = greeting;
- self.saves = saves;
- })
+ serde_yaml::from_str::<(String, HashMap<String, RoomSave>)>(text).map(
+ |(greeting, saves)| {
+ self.greeting = greeting;
+ self.saves = saves;
+ },
+ )
}
pub fn team_info(owner: &HWClient, team: &TeamInfo) -> Vec<String> {
@@ -382,10 +441,13 @@
team.voice_pack.clone(),
team.flag.clone(),
owner.nick.clone(),
- team.difficulty.to_string()];
- let hogs = team.hedgehogs.iter().flat_map(|h|
- iter::once(h.name.clone()).chain(iter::once(h.hat.clone())));
+ team.difficulty.to_string(),
+ ];
+ let hogs = team
+ .hedgehogs
+ .iter()
+ .flat_map(|h| iter::once(h.name.clone()).chain(iter::once(h.hat.clone())));
info.extend(hogs);
info
}
-}
\ No newline at end of file
+}
--- a/rust/hedgewars-server/src/utils.rs Sun Dec 16 00:09:20 2018 +0100
+++ b/rust/hedgewars-server/src/utils.rs Sun Dec 16 00:12:29 2018 +0100
@@ -1,20 +1,21 @@
-use std::iter::Iterator;
+use base64::encode;
use mio;
-use base64::{encode};
+use std::iter::Iterator;
-pub const PROTOCOL_VERSION : u32 = 3;
+pub const PROTOCOL_VERSION: u32 = 3;
pub const SERVER: mio::Token = mio::Token(1_000_000_000);
-pub fn is_name_illegal(name: &str ) -> bool{
- name.len() > 40 ||
- name.trim().is_empty() ||
- name.chars().any(|c|
- "$()*+?[]^{|}\x7F".contains(c) ||
- '\x00' <= c && c <= '\x1F')
+pub fn is_name_illegal(name: &str) -> bool {
+ name.len() > 40
+ || name.trim().is_empty()
+ || name
+ .chars()
+ .any(|c| "$()*+?[]^{|}\x7F".contains(c) || '\x00' <= c && c <= '\x1F')
}
pub fn to_engine_msg<T>(msg: T) -> String
- where T: Iterator<Item = u8> + Clone
+where
+ T: Iterator<Item = u8> + Clone,
{
let mut tmp = Vec::new();
tmp.push(msg.clone().count() as u8);
@@ -64,6 +65,6 @@
56 => "0.9.25-dev",
57 => "0.9.25",
58 => "1.0.0-dev",
- _ => "Unknown"
+ _ => "Unknown",
}
}