Oregami
Repositories/oxedyne/fe2o3

oxedyne/fe2o3/fe2o3_net/src/guard/user.rs

3.6 KiB, 34 runs

created by r1870400018:870, which is this file's identity for as long as the history lasts, whatever it is later renamed to

download · who wrote it · its history

1use oxedyne_fe2o3_core::{
2 prelude::*,
3 map::MapMut,
4};
5use oxedyne_fe2o3_hash::map::ShardMap;
6use oxedyne_fe2o3_iop_hash::api::{
7 Hasher,
8 HashForm,
9};
10use oxedyne_fe2o3_jdat::id::NumIdDat;
11
12use std::{
13 clone::Clone,
14 fmt::Debug,
15 sync::RwLock,
16 //time::{
17 // Duration,
18 // SystemTime,
19 //},
20};
21
22/// Trust classification the server holds for a given user.
23#[derive(Clone, Debug)]
24pub enum UserState {
25 /// User has not yet been classified.
26 Unknown,
27 /// User is barred; their packets are dropped.
28 Blacklist, // No soup for you.
29 /// User is explicitly trusted and allowed through.
30 Whitelist, // Come on through.
31}
32
33impl Default for UserState {
34 fn default() -> Self {
35 Self::Unknown
36 }
37}
38
39/// Per-user record combining trust state with a caller-supplied data payload.
40#[derive(Clone, Debug, Default)]
41pub struct UserLog<
42 D: Clone + Debug + Default, // user supplied data container
43> {
44 /// Current trust classification for the user.
45 pub state: UserState,
46 // Data
47 /// Application-specific data associated with the user.
48 pub data: D,
49}
50
51/// Sharded, concurrent guard tracking per-user trust state.
52///
53/// User records are held in a [`ShardMap`] keyed by user identifier, giving
54/// concurrent access across `C` shards without a single global lock.
55#[derive(Debug)]
56pub struct UserGuard<
57 // ShardMap
58 const C: usize, // Capacity (maximum number of bins).
59 M: MapMut<HashForm, UserLog<D>> + Clone + Debug,
60 H: Hasher + Send + Sync + 'static, // Key hasher.
61 const S: usize, // Key hasher salt length.
62 // AddressData
63 D: Clone + Debug + Default, // user supplied data container
64> {
65 /// Sharded map from user key to that user's log.
66 pub umap: ShardMap<C, S, UserLog<D>, M, H>,
67}
68
69impl<
70 // ShardMap
71 const C: usize, // Capacity (maximum number of bins).
72 M: MapMut<HashForm, UserLog<D>> + Clone + Debug,
73 H: Hasher + Send + Sync + 'static, // Key hasher.
74 const S: usize, // Key hasher salt length.
75 // AddressData
76 D: Clone + Debug + Default, // user supplied data container
77>
78 UserGuard<C, M, H, S, D>
79{
80 /// Updates state for given address and returns whether the packet should be dropped.
81 pub fn drop_packet<
82 const UIDL: usize,
83 UID: NumIdDat<UIDL>,
84 >(
85 &self,
86 uid: &UID,
87 accept_unknown: bool,
88 )
89 -> Outcome<bool>
90 {
91 let (key, locked_map) = res!(self.get_locked_map(uid));
92 let mut unlocked_map = lock_write!(locked_map);
93 match unlocked_map.get_mut(&key) {
94 Some(_ulog) => {
95 // TODO examine user log
96 },
97 None => {
98 if accept_unknown {
99 let ulog = UserLog::default();
100 unlocked_map.insert(key, ulog);
101 } else {
102 return Ok(true);
103 }
104 },
105 }
106 Ok(false)
107 }
108
109 /// Resolves a user identifier to its shard key and the [`RwLock`] guarding
110 /// the shard that would hold that user's log.
111 pub fn get_locked_map<
112 const UIDL: usize,
113 UID: NumIdDat<UIDL>,
114 >(
115 &self,
116 uid: &UID,
117 )
118 -> Outcome<(HashForm, &RwLock<M>)>
119 {
120 let key = self.umap.key(&uid.to_byte_array());
121 let locked_map = res!(self.umap.get_shard_using_hash(&key));
122 Ok((key, locked_map))
123 }
124 //pub fn get_user_log<'a>(&'a self, uid: &'a U) -> Option<&'a UserLog<D>> {
125 // self.umap.get(uid)
126 //}
127
128 //pub fn get_user_log_mut<'a>(&'a mut self, uid: &'a U) -> Option<&'a mut UserLog<D>> {
129 // self.umap.get_mut(uid)
130 //}
131}