15521
|
1 |
use super::{indexslab::IndexSlab, types::ClientId};
|
|
2 |
use chrono::{offset, DateTime};
|
|
3 |
use std::{iter::Iterator, num::NonZeroU16};
|
|
4 |
|
|
5 |
pub struct HwAnteroomClient {
|
|
6 |
pub nick: Option<String>,
|
|
7 |
pub protocol_number: Option<NonZeroU16>,
|
|
8 |
pub server_salt: String,
|
|
9 |
pub is_checker: bool,
|
|
10 |
pub is_local_admin: bool,
|
|
11 |
pub is_registered: bool,
|
|
12 |
pub is_admin: bool,
|
|
13 |
pub is_contributor: bool,
|
|
14 |
}
|
|
15 |
|
|
16 |
struct Ipv4AddrRange {
|
|
17 |
min: [u8; 4],
|
|
18 |
max: [u8; 4],
|
|
19 |
}
|
|
20 |
|
|
21 |
impl Ipv4AddrRange {
|
|
22 |
fn contains(&self, addr: [u8; 4]) -> bool {
|
|
23 |
(0..4).all(|i| self.min[i] <= addr[i] && addr[i] <= self.max[i])
|
|
24 |
}
|
|
25 |
}
|
|
26 |
|
|
27 |
struct BanCollection {
|
|
28 |
ban_ips: Vec<Ipv4AddrRange>,
|
|
29 |
ban_timeouts: Vec<DateTime<offset::Utc>>,
|
|
30 |
ban_reasons: Vec<String>,
|
|
31 |
}
|
|
32 |
|
|
33 |
impl BanCollection {
|
|
34 |
fn new() -> Self {
|
|
35 |
Self {
|
|
36 |
ban_ips: vec![],
|
|
37 |
ban_timeouts: vec![],
|
|
38 |
ban_reasons: vec![],
|
|
39 |
}
|
|
40 |
}
|
|
41 |
|
|
42 |
fn find(&self, addr: [u8; 4]) -> Option<String> {
|
|
43 |
let time = offset::Utc::now();
|
|
44 |
self.ban_ips
|
|
45 |
.iter()
|
|
46 |
.enumerate()
|
|
47 |
.find(|(i, r)| r.contains(addr) && time < self.ban_timeouts[*i])
|
|
48 |
.map(|(i, _)| self.ban_reasons[i].clone())
|
|
49 |
}
|
|
50 |
}
|
|
51 |
|
|
52 |
pub struct HwAnteroom {
|
|
53 |
pub clients: IndexSlab<HwAnteroomClient>,
|
|
54 |
bans: BanCollection,
|
|
55 |
}
|
|
56 |
|
|
57 |
impl HwAnteroom {
|
|
58 |
pub fn new(clients_limit: usize) -> Self {
|
|
59 |
let clients = IndexSlab::with_capacity(clients_limit);
|
|
60 |
HwAnteroom {
|
|
61 |
clients,
|
|
62 |
bans: BanCollection::new(),
|
|
63 |
}
|
|
64 |
}
|
|
65 |
|
|
66 |
pub fn find_ip_ban(&self, addr: [u8; 4]) -> Option<String> {
|
|
67 |
self.bans.find(addr)
|
|
68 |
}
|
|
69 |
|
|
70 |
pub fn add_client(&mut self, client_id: ClientId, salt: String, is_local_admin: bool) {
|
|
71 |
let client = HwAnteroomClient {
|
|
72 |
nick: None,
|
|
73 |
protocol_number: None,
|
|
74 |
server_salt: salt,
|
|
75 |
is_checker: false,
|
|
76 |
is_local_admin,
|
|
77 |
is_registered: false,
|
|
78 |
is_admin: false,
|
|
79 |
is_contributor: false,
|
|
80 |
};
|
|
81 |
self.clients.insert(client_id, client);
|
|
82 |
}
|
|
83 |
|
|
84 |
pub fn remove_client(&mut self, client_id: ClientId) -> Option<HwAnteroomClient> {
|
|
85 |
let client = self.clients.remove(client_id);
|
|
86 |
client
|
|
87 |
}
|
|
88 |
}
|