1 use super::{ |
1 use super::{ |
|
2 anteroom::HwAnteroomClient, |
2 client::HwClient, |
3 client::HwClient, |
3 indexslab::IndexSlab, |
4 indexslab::IndexSlab, |
4 room::HwRoom, |
5 room::HwRoom, |
5 types::{ClientId, RoomId, ServerVar, TeamInfo}, |
6 types::{ClientId, RoomId, ServerVar, TeamInfo}, |
6 }; |
7 }; |
7 use crate::{protocol::messages::HwProtocolMessage::Greeting, utils}; |
8 use crate::{protocol::messages::HwProtocolMessage::Greeting, utils}; |
8 |
9 |
9 use bitflags::_core::hint::unreachable_unchecked; |
10 use bitflags::_core::hint::unreachable_unchecked; |
10 use bitflags::*; |
11 use bitflags::*; |
11 use chrono::{offset, DateTime}; |
|
12 use log::*; |
12 use log::*; |
13 use slab::Slab; |
13 use slab::Slab; |
14 use std::{borrow::BorrowMut, collections::HashSet, iter, mem::replace, num::NonZeroU16}; |
14 use std::{borrow::BorrowMut, collections::HashSet, iter, mem::replace}; |
15 |
15 |
16 #[derive(Debug)] |
16 #[derive(Debug)] |
17 pub enum CreateRoomError { |
17 pub enum CreateRoomError { |
18 InvalidName, |
18 InvalidName, |
19 AlreadyExists, |
19 AlreadyExists, |
104 #[derive(Debug)] |
104 #[derive(Debug)] |
105 pub struct UninitializedError(); |
105 pub struct UninitializedError(); |
106 #[derive(Debug)] |
106 #[derive(Debug)] |
107 pub struct AccessError(); |
107 pub struct AccessError(); |
108 |
108 |
109 pub struct HwAnteClient { |
|
110 pub nick: Option<String>, |
|
111 pub protocol_number: Option<NonZeroU16>, |
|
112 pub server_salt: String, |
|
113 pub is_checker: bool, |
|
114 pub is_local_admin: bool, |
|
115 pub is_registered: bool, |
|
116 pub is_admin: bool, |
|
117 pub is_contributor: bool, |
|
118 } |
|
119 |
|
120 struct Ipv4AddrRange { |
|
121 min: [u8; 4], |
|
122 max: [u8; 4], |
|
123 } |
|
124 |
|
125 impl Ipv4AddrRange { |
|
126 fn contains(&self, addr: [u8; 4]) -> bool { |
|
127 (0..4).all(|i| self.min[i] <= addr[i] && addr[i] <= self.max[i]) |
|
128 } |
|
129 } |
|
130 |
|
131 struct BanCollection { |
|
132 ban_ips: Vec<Ipv4AddrRange>, |
|
133 ban_timeouts: Vec<DateTime<offset::Utc>>, |
|
134 ban_reasons: Vec<String>, |
|
135 } |
|
136 |
|
137 impl BanCollection { |
|
138 fn new() -> Self { |
|
139 Self { |
|
140 ban_ips: vec![], |
|
141 ban_timeouts: vec![], |
|
142 ban_reasons: vec![], |
|
143 } |
|
144 } |
|
145 |
|
146 fn find(&self, addr: [u8; 4]) -> Option<String> { |
|
147 let time = offset::Utc::now(); |
|
148 self.ban_ips |
|
149 .iter() |
|
150 .enumerate() |
|
151 .find(|(i, r)| r.contains(addr) && time < self.ban_timeouts[*i]) |
|
152 .map(|(i, _)| self.ban_reasons[i].clone()) |
|
153 } |
|
154 } |
|
155 |
|
156 pub struct HwAnteroom { |
|
157 pub clients: IndexSlab<HwAnteClient>, |
|
158 bans: BanCollection, |
|
159 } |
|
160 |
|
161 impl HwAnteroom { |
|
162 pub fn new(clients_limit: usize) -> Self { |
|
163 let clients = IndexSlab::with_capacity(clients_limit); |
|
164 HwAnteroom { |
|
165 clients, |
|
166 bans: BanCollection::new(), |
|
167 } |
|
168 } |
|
169 |
|
170 pub fn find_ip_ban(&self, addr: [u8; 4]) -> Option<String> { |
|
171 self.bans.find(addr) |
|
172 } |
|
173 |
|
174 pub fn add_client(&mut self, client_id: ClientId, salt: String, is_local_admin: bool) { |
|
175 let client = HwAnteClient { |
|
176 nick: None, |
|
177 protocol_number: None, |
|
178 server_salt: salt, |
|
179 is_checker: false, |
|
180 is_local_admin, |
|
181 is_registered: false, |
|
182 is_admin: false, |
|
183 is_contributor: false, |
|
184 }; |
|
185 self.clients.insert(client_id, client); |
|
186 } |
|
187 |
|
188 pub fn remove_client(&mut self, client_id: ClientId) -> Option<HwAnteClient> { |
|
189 let client = self.clients.remove(client_id); |
|
190 client |
|
191 } |
|
192 } |
|
193 |
|
194 pub struct ServerGreetings { |
109 pub struct ServerGreetings { |
195 pub for_latest_protocol: String, |
110 pub for_latest_protocol: String, |
196 pub for_old_protocols: String, |
111 pub for_old_protocols: String, |
197 } |
112 } |
198 |
113 |
210 const REGISTERED_ONLY = 0b0000_1000; |
125 const REGISTERED_ONLY = 0b0000_1000; |
211 } |
126 } |
212 } |
127 } |
213 |
128 |
214 pub struct HwServer { |
129 pub struct HwServer { |
215 pub clients: IndexSlab<HwClient>, |
130 clients: IndexSlab<HwClient>, |
216 pub rooms: Slab<HwRoom>, |
131 pub rooms: Slab<HwRoom>, |
217 pub anteroom: HwAnteroom, |
|
218 pub latest_protocol: u16, |
132 pub latest_protocol: u16, |
219 pub flags: ServerFlags, |
133 pub flags: ServerFlags, |
220 pub greetings: ServerGreetings, |
134 pub greetings: ServerGreetings, |
221 } |
135 } |
222 |
136 |
225 let rooms = Slab::with_capacity(rooms_limit); |
139 let rooms = Slab::with_capacity(rooms_limit); |
226 let clients = IndexSlab::with_capacity(clients_limit); |
140 let clients = IndexSlab::with_capacity(clients_limit); |
227 Self { |
141 Self { |
228 clients, |
142 clients, |
229 rooms, |
143 rooms, |
230 anteroom: HwAnteroom::new(clients_limit), |
|
231 greetings: ServerGreetings::new(), |
144 greetings: ServerGreetings::new(), |
232 latest_protocol: 58, |
145 latest_protocol: 58, |
233 flags: ServerFlags::empty(), |
146 flags: ServerFlags::empty(), |
234 } |
147 } |
235 } |
148 } |
284 .get(client_id) |
197 .get(client_id) |
285 .map(|c| c.is_admin()) |
198 .map(|c| c.is_admin()) |
286 .unwrap_or(false) |
199 .unwrap_or(false) |
287 } |
200 } |
288 |
201 |
289 pub fn add_client(&mut self, client_id: ClientId, data: HwAnteClient) { |
202 pub fn add_client(&mut self, client_id: ClientId, data: HwAnteroomClient) { |
290 if let (Some(protocol), Some(nick)) = (data.protocol_number, data.nick) { |
203 if let (Some(protocol), Some(nick)) = (data.protocol_number, data.nick) { |
291 let mut client = HwClient::new(client_id, protocol.get(), nick); |
204 let mut client = HwClient::new(client_id, protocol.get(), nick); |
292 client.set_is_checker(data.is_checker); |
205 client.set_is_checker(data.is_checker); |
293 #[cfg(not(feature = "official-server"))] |
206 #[cfg(not(feature = "official-server"))] |
294 client.set_is_admin(data.is_local_admin); |
207 client.set_is_admin(data.is_local_admin); |