1 use super::{indexslab::IndexSlab, types::ClientId}; |
1 use super::{indexslab::IndexSlab, types::ClientId}; |
|
2 use crate::core::client::HwClient; |
|
3 use crate::core::digest::Sha1Digest; |
2 use chrono::{offset, DateTime}; |
4 use chrono::{offset, DateTime}; |
|
5 use std::collections::{HashMap, HashSet}; |
3 use std::{iter::Iterator, num::NonZeroU16}; |
6 use std::{iter::Iterator, num::NonZeroU16}; |
4 |
7 |
5 pub struct HwAnteroomClient { |
8 pub struct HwAnteroomClient { |
6 pub nick: Option<String>, |
9 pub nick: Option<String>, |
7 pub protocol_number: Option<NonZeroU16>, |
10 pub protocol_number: Option<NonZeroU16>, |
49 .map(|(i, _)| self.ban_reasons[i].clone()) |
52 .map(|(i, _)| self.ban_reasons[i].clone()) |
50 } |
53 } |
51 } |
54 } |
52 |
55 |
53 pub struct HwAnteroom { |
56 pub struct HwAnteroom { |
54 pub clients: IndexSlab<HwAnteroomClient>, |
57 clients: IndexSlab<HwAnteroomClient>, |
55 bans: BanCollection, |
58 bans: BanCollection, |
|
59 taken_nicks: HashSet<String>, |
|
60 reconnection_tokens: HashMap<String, String>, |
56 } |
61 } |
57 |
62 |
58 impl HwAnteroom { |
63 impl HwAnteroom { |
59 pub fn new(clients_limit: usize) -> Self { |
64 pub fn new(clients_limit: usize) -> Self { |
60 let clients = IndexSlab::with_capacity(clients_limit); |
65 let clients = IndexSlab::with_capacity(clients_limit); |
61 HwAnteroom { |
66 HwAnteroom { |
62 clients, |
67 clients, |
63 bans: BanCollection::new(), |
68 bans: BanCollection::new(), |
|
69 taken_nicks: Default::default(), |
|
70 reconnection_tokens: Default::default(), |
64 } |
71 } |
65 } |
72 } |
66 |
73 |
67 pub fn find_ip_ban(&self, addr: [u8; 4]) -> Option<String> { |
74 pub fn find_ip_ban(&self, addr: [u8; 4]) -> Option<String> { |
68 self.bans.find(addr) |
75 self.bans.find(addr) |
80 is_contributor: false, |
87 is_contributor: false, |
81 }; |
88 }; |
82 self.clients.insert(client_id, client); |
89 self.clients.insert(client_id, client); |
83 } |
90 } |
84 |
91 |
|
92 pub fn has_client(&self, id: ClientId) -> bool { |
|
93 self.clients.contains(id) |
|
94 } |
|
95 |
|
96 pub fn get_client(&mut self, id: ClientId) -> &HwAnteroomClient { |
|
97 &self.clients[id] |
|
98 } |
|
99 |
|
100 pub fn get_client_mut(&mut self, id: ClientId) -> &mut HwAnteroomClient { |
|
101 &mut self.clients[id] |
|
102 } |
|
103 |
85 pub fn remove_client(&mut self, client_id: ClientId) -> Option<HwAnteroomClient> { |
104 pub fn remove_client(&mut self, client_id: ClientId) -> Option<HwAnteroomClient> { |
86 let client = self.clients.remove(client_id); |
105 let client = self.clients.remove(client_id); |
|
106 if let Some(HwAnteroomClient { |
|
107 nick: Some(nick), .. |
|
108 }) = &client |
|
109 { |
|
110 self.taken_nicks.remove(nick); |
|
111 } |
87 client |
112 client |
88 } |
113 } |
|
114 |
|
115 pub fn nick_taken(&self, nick: &str) -> bool { |
|
116 self.taken_nicks.contains(nick) |
|
117 } |
|
118 |
|
119 pub fn remember_nick(&mut self, nick: String) { |
|
120 self.taken_nicks.insert(nick); |
|
121 } |
|
122 |
|
123 pub fn forget_nick(&mut self, nick: &str) { |
|
124 self.taken_nicks.remove(nick); |
|
125 } |
|
126 |
|
127 #[inline] |
|
128 pub fn get_nick_token(&self, nick: &str) -> Option<&str> { |
|
129 self.reconnection_tokens.get(nick).map(|s| &s[..]) |
|
130 } |
|
131 |
|
132 #[inline] |
|
133 pub fn register_nick_token(&mut self, nick: &str) -> Option<&str> { |
|
134 if self.reconnection_tokens.contains_key(nick) { |
|
135 None |
|
136 } else { |
|
137 let token = format!("{:x}", Sha1Digest::random()); |
|
138 self.reconnection_tokens.insert(nick.to_string(), token); |
|
139 Some(&self.reconnection_tokens[nick]) |
|
140 } |
|
141 } |
89 } |
142 } |