subspace_networking/constructor/
temporary_bans.rs1use backoff::ExponentialBackoff;
2use backoff::backoff::Backoff;
3use libp2p::PeerId;
4use schnellru::{ByLength, LruMap};
5use std::ops::Add;
6use std::time::Instant;
7
8#[derive(Debug)]
10struct TemporaryBan {
11 backoff: ExponentialBackoff,
12 next_release: Option<Instant>,
13}
14
15impl TemporaryBan {
16 fn new(backoff: ExponentialBackoff) -> Self {
18 let mut instance = Self {
19 backoff,
20 next_release: None,
21 };
22 instance.backoff.reset();
23 instance.next_release = instance
24 .backoff
25 .next_backoff()
26 .map(|duration| Instant::now().add(duration));
27 instance
28 }
29
30 fn is_active(&self) -> bool {
32 if let Some(next_release) = self.next_release {
33 next_release > Instant::now()
34 } else {
35 true
36 }
37 }
38
39 fn try_extend(&mut self) {
41 let now = Instant::now();
42
43 if let Some(next_release) = self.next_release {
44 if next_release > now {
45 return;
47 }
48 } else {
49 return;
51 }
52
53 self.next_release = self
54 .backoff
55 .next_backoff()
56 .map(|duration| now.add(duration));
57 }
58}
59
60#[derive(Debug)]
63pub(crate) struct TemporaryBans {
64 backoff: ExponentialBackoff,
65 list: LruMap<PeerId, TemporaryBan>,
66}
67
68impl TemporaryBans {
69 pub(super) fn new(capacity: u32, backoff: ExponentialBackoff) -> Self {
70 Self {
71 backoff,
72 list: LruMap::new(ByLength::new(capacity)),
73 }
74 }
75
76 pub(crate) fn is_banned(&self, peer_id: &PeerId) -> bool {
81 self.list
82 .peek(peer_id)
83 .map(TemporaryBan::is_active)
84 .unwrap_or_default()
85 }
86
87 pub(crate) fn create_or_extend(&mut self, peer_id: &PeerId) {
89 if let Some(ban) = self.list.get(peer_id) {
90 ban.try_extend();
91 } else {
92 self.list
93 .insert(*peer_id, TemporaryBan::new(self.backoff.clone()));
94 }
95 }
96
97 pub(crate) fn remove(&mut self, peer_id: &PeerId) -> bool {
101 self.list.remove(peer_id).is_some()
102 }
103}