rust/hedgewars-server/src/core/anteroom.rs
changeset 15521 1fcce8feace4
child 15938 ce47259d5c86
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rust/hedgewars-server/src/core/anteroom.rs	Mon Dec 23 18:11:15 2019 +0300
@@ -0,0 +1,88 @@
+use super::{indexslab::IndexSlab, types::ClientId};
+use chrono::{offset, DateTime};
+use std::{iter::Iterator, num::NonZeroU16};
+
+pub struct HwAnteroomClient {
+    pub nick: Option<String>,
+    pub protocol_number: Option<NonZeroU16>,
+    pub server_salt: String,
+    pub is_checker: bool,
+    pub is_local_admin: bool,
+    pub is_registered: bool,
+    pub is_admin: bool,
+    pub is_contributor: bool,
+}
+
+struct Ipv4AddrRange {
+    min: [u8; 4],
+    max: [u8; 4],
+}
+
+impl Ipv4AddrRange {
+    fn contains(&self, addr: [u8; 4]) -> bool {
+        (0..4).all(|i| self.min[i] <= addr[i] && addr[i] <= self.max[i])
+    }
+}
+
+struct BanCollection {
+    ban_ips: Vec<Ipv4AddrRange>,
+    ban_timeouts: Vec<DateTime<offset::Utc>>,
+    ban_reasons: Vec<String>,
+}
+
+impl BanCollection {
+    fn new() -> Self {
+        Self {
+            ban_ips: vec![],
+            ban_timeouts: vec![],
+            ban_reasons: vec![],
+        }
+    }
+
+    fn find(&self, addr: [u8; 4]) -> Option<String> {
+        let time = offset::Utc::now();
+        self.ban_ips
+            .iter()
+            .enumerate()
+            .find(|(i, r)| r.contains(addr) && time < self.ban_timeouts[*i])
+            .map(|(i, _)| self.ban_reasons[i].clone())
+    }
+}
+
+pub struct HwAnteroom {
+    pub clients: IndexSlab<HwAnteroomClient>,
+    bans: BanCollection,
+}
+
+impl HwAnteroom {
+    pub fn new(clients_limit: usize) -> Self {
+        let clients = IndexSlab::with_capacity(clients_limit);
+        HwAnteroom {
+            clients,
+            bans: BanCollection::new(),
+        }
+    }
+
+    pub fn find_ip_ban(&self, addr: [u8; 4]) -> Option<String> {
+        self.bans.find(addr)
+    }
+
+    pub fn add_client(&mut self, client_id: ClientId, salt: String, is_local_admin: bool) {
+        let client = HwAnteroomClient {
+            nick: None,
+            protocol_number: None,
+            server_salt: salt,
+            is_checker: false,
+            is_local_admin,
+            is_registered: false,
+            is_admin: false,
+            is_contributor: false,
+        };
+        self.clients.insert(client_id, client);
+    }
+
+    pub fn remove_client(&mut self, client_id: ClientId) -> Option<HwAnteroomClient> {
+        let client = self.clients.remove(client_id);
+        client
+    }
+}