1 use mio; |
1 use mio; |
2 |
2 |
|
3 use super::common::rnd_reply; |
3 use crate::{ |
4 use crate::{ |
|
5 protocol::messages::{server_chat, HWProtocolMessage, HWServerMessage::*}, |
4 server::{ |
6 server::{ |
5 coretypes::{ |
7 actions::{Action, Action::*}, |
6 ClientId, RoomId, Voting, VoteType, GameCfg, |
|
7 MAX_HEDGEHOGS_PER_TEAM |
|
8 }, |
|
9 core::HWServer, |
8 core::HWServer, |
|
9 coretypes::{ClientId, GameCfg, RoomId, VoteType, Voting, MAX_HEDGEHOGS_PER_TEAM}, |
10 room::{HWRoom, RoomFlags}, |
10 room::{HWRoom, RoomFlags}, |
11 actions::{Action, Action::*} |
|
12 }, |
11 }, |
13 protocol::messages::{ |
12 utils::is_name_illegal, |
14 HWProtocolMessage, |
|
15 HWServerMessage::*, |
|
16 server_chat |
|
17 }, |
|
18 utils::is_name_illegal |
|
19 }; |
13 }; |
20 use std::{ |
14 use base64::{decode, encode}; |
21 mem::swap |
|
22 }; |
|
23 use base64::{encode, decode}; |
|
24 use super::common::rnd_reply; |
|
25 use log::*; |
15 use log::*; |
|
16 use std::mem::swap; |
26 |
17 |
27 #[derive(Clone)] |
18 #[derive(Clone)] |
28 struct ByMsg<'a> { |
19 struct ByMsg<'a> { |
29 messages: &'a[u8] |
20 messages: &'a [u8], |
30 } |
21 } |
31 |
22 |
32 impl <'a> Iterator for ByMsg<'a> { |
23 impl<'a> Iterator for ByMsg<'a> { |
33 type Item = &'a[u8]; |
24 type Item = &'a [u8]; |
34 |
25 |
35 fn next(&mut self) -> Option<<Self as Iterator>::Item> { |
26 fn next(&mut self) -> Option<<Self as Iterator>::Item> { |
36 if let Some(size) = self.messages.get(0) { |
27 if let Some(size) = self.messages.get(0) { |
37 let (msg, next) = self.messages.split_at(*size as usize + 1); |
28 let (msg, next) = self.messages.split_at(*size as usize + 1); |
38 self.messages = next; |
29 self.messages = next; |
42 } |
33 } |
43 } |
34 } |
44 } |
35 } |
45 |
36 |
46 fn by_msg(source: &[u8]) -> ByMsg { |
37 fn by_msg(source: &[u8]) -> ByMsg { |
47 ByMsg {messages: source} |
38 ByMsg { messages: source } |
48 } |
39 } |
49 |
40 |
50 const VALID_MESSAGES: &[u8] = |
41 const VALID_MESSAGES: &[u8] = |
51 b"M#+LlRrUuDdZzAaSjJ,NpPwtgfhbc12345\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A"; |
42 b"M#+LlRrUuDdZzAaSjJ,NpPwtgfhbc12345\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A"; |
52 const NON_TIMED_MESSAGES: &[u8] = b"M#hb"; |
43 const NON_TIMED_MESSAGES: &[u8] = b"M#hb"; |
53 |
44 |
54 #[cfg(canhazslicepatterns)] |
45 #[cfg(canhazslicepatterns)] |
55 fn is_msg_valid(msg: &[u8], team_indices: &[u8]) -> bool { |
46 fn is_msg_valid(msg: &[u8], team_indices: &[u8]) -> bool { |
56 match msg { |
47 match msg { |
57 [size, typ, body..] => VALID_MESSAGES.contains(typ) |
48 [size, typ, body..] => { |
58 && match body { |
49 VALID_MESSAGES.contains(typ) |
59 [1...MAX_HEDGEHOGS_PER_TEAM, team, ..] if *typ == b'h' => |
50 && match body { |
60 team_indices.contains(team), |
51 [1...MAX_HEDGEHOGS_PER_TEAM, team, ..] if *typ == b'h' => { |
61 _ => *typ != b'h' |
52 team_indices.contains(team) |
62 }, |
53 } |
63 _ => false |
54 _ => *typ != b'h', |
|
55 } |
|
56 } |
|
57 _ => false, |
64 } |
58 } |
65 } |
59 } |
66 |
60 |
67 fn is_msg_valid(msg: &[u8], _team_indices: &[u8]) -> bool { |
61 fn is_msg_valid(msg: &[u8], _team_indices: &[u8]) -> bool { |
68 if let Some(typ) = msg.get(1) { |
62 if let Some(typ) = msg.get(1) { |
75 fn is_msg_empty(msg: &[u8]) -> bool { |
69 fn is_msg_empty(msg: &[u8]) -> bool { |
76 msg.get(1).filter(|t| **t == b'+').is_some() |
70 msg.get(1).filter(|t| **t == b'+').is_some() |
77 } |
71 } |
78 |
72 |
79 fn is_msg_timed(msg: &[u8]) -> bool { |
73 fn is_msg_timed(msg: &[u8]) -> bool { |
80 msg.get(1).filter(|t| !NON_TIMED_MESSAGES.contains(t)).is_some() |
74 msg.get(1) |
|
75 .filter(|t| !NON_TIMED_MESSAGES.contains(t)) |
|
76 .is_some() |
81 } |
77 } |
82 |
78 |
83 fn voting_description(kind: &VoteType) -> String { |
79 fn voting_description(kind: &VoteType) -> String { |
84 format!("New voting started: {}", match kind { |
80 format!( |
85 VoteType::Kick(nick) => format!("kick {}", nick), |
81 "New voting started: {}", |
86 VoteType::Map(name) => format!("map {}", name.as_ref().unwrap()), |
82 match kind { |
87 VoteType::Pause => "pause".to_string(), |
83 VoteType::Kick(nick) => format!("kick {}", nick), |
88 VoteType::NewSeed => "new seed".to_string(), |
84 VoteType::Map(name) => format!("map {}", name.as_ref().unwrap()), |
89 VoteType::HedgehogsPerTeam(number) => format!("hedgehogs per team: {}", number) |
85 VoteType::Pause => "pause".to_string(), |
90 }) |
86 VoteType::NewSeed => "new seed".to_string(), |
|
87 VoteType::HedgehogsPerTeam(number) => format!("hedgehogs per team: {}", number), |
|
88 } |
|
89 ) |
91 } |
90 } |
92 |
91 |
93 fn room_message_flag(msg: &HWProtocolMessage) -> RoomFlags { |
92 fn room_message_flag(msg: &HWProtocolMessage) -> RoomFlags { |
94 use crate::protocol::messages::HWProtocolMessage::*; |
93 use crate::protocol::messages::HWProtocolMessage::*; |
95 match msg { |
94 match msg { |
96 ToggleRestrictJoin => RoomFlags::RESTRICTED_JOIN, |
95 ToggleRestrictJoin => RoomFlags::RESTRICTED_JOIN, |
97 ToggleRestrictTeams => RoomFlags::RESTRICTED_TEAM_ADD, |
96 ToggleRestrictTeams => RoomFlags::RESTRICTED_TEAM_ADD, |
98 ToggleRegisteredOnly => RoomFlags::RESTRICTED_UNREGISTERED_PLAYERS, |
97 ToggleRegisteredOnly => RoomFlags::RESTRICTED_UNREGISTERED_PLAYERS, |
99 _ => RoomFlags::empty() |
98 _ => RoomFlags::empty(), |
100 } |
99 } |
101 } |
100 } |
102 |
101 |
103 pub fn handle(server: &mut HWServer, client_id: ClientId, room_id: RoomId, message: HWProtocolMessage) { |
102 pub fn handle( |
|
103 server: &mut HWServer, |
|
104 client_id: ClientId, |
|
105 room_id: RoomId, |
|
106 message: HWProtocolMessage, |
|
107 ) { |
104 use crate::protocol::messages::HWProtocolMessage::*; |
108 use crate::protocol::messages::HWProtocolMessage::*; |
105 match message { |
109 match message { |
106 Part(None) => server.react(client_id, vec![ |
110 Part(None) => server.react(client_id, vec![ |
107 MoveToLobby("part".to_string())]), |
111 MoveToLobby("part".to_string())]), |
108 Part(Some(msg)) => server.react(client_id, vec![ |
112 Part(Some(msg)) => server.react(client_id, vec![ |