2024-05-24 18:16:30 -04:00
|
|
|
use crate::get_date;
|
2024-05-24 17:32:10 -04:00
|
|
|
|
|
|
|
use lox_library::{cred::Lox, scalar_u32};
|
|
|
|
use rand::Rng;
|
|
|
|
use std::collections::{HashMap, HashSet};
|
|
|
|
|
|
|
|
pub struct Censor {
|
|
|
|
pub country: String,
|
|
|
|
pub known_bridges: HashSet<[u8; 20]>,
|
|
|
|
pub lox_credentials: HashMap<[u8; 20], Lox>,
|
|
|
|
|
|
|
|
// How fast does this censor block bridges after learning about them?
|
|
|
|
pub speed: Speed,
|
|
|
|
// If censor implements random blocking, this is the date when it
|
|
|
|
// will start blocking all the bridges it knows.
|
|
|
|
pub delay_date: u32,
|
|
|
|
|
|
|
|
// Does the censor attempt to hide the fact that a bridge has been blocked?
|
|
|
|
pub hides: Hides,
|
|
|
|
|
|
|
|
// Does the censor block bridges uniformly across the country?
|
|
|
|
pub totality: Totality,
|
|
|
|
// If censor implements partial blocking, what percent of
|
|
|
|
// connections are blocked? If totality is not partial, this is set
|
|
|
|
// to 100%.
|
|
|
|
pub partial_blocking_percent: f64,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Censor {
|
|
|
|
pub fn new(country: String, speed: Speed, hides: Hides, totality: Totality) -> Self {
|
|
|
|
let mut rng = rand::thread_rng();
|
|
|
|
let delay_date = if speed == Speed::Random {
|
|
|
|
let num: u32 = rng.gen_range(1..365);
|
|
|
|
get_date() + num
|
|
|
|
} else {
|
|
|
|
0
|
|
|
|
};
|
|
|
|
let partial_blocking_percent = if totality == Totality::Partial {
|
|
|
|
let num: f64 = rng.gen_range(0.0..1.0);
|
|
|
|
num
|
|
|
|
} else {
|
|
|
|
1.0
|
|
|
|
};
|
|
|
|
Censor {
|
|
|
|
country: country,
|
|
|
|
known_bridges: HashSet::<[u8; 20]>::new(),
|
|
|
|
lox_credentials: HashMap::<[u8; 20], Lox>::new(),
|
|
|
|
speed: speed,
|
|
|
|
delay_date: delay_date,
|
|
|
|
hides: hides,
|
|
|
|
totality: totality,
|
|
|
|
partial_blocking_percent: partial_blocking_percent,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-05-24 18:16:30 -04:00
|
|
|
pub fn knows_bridge(&self, fingerprint: &[u8; 20]) -> bool {
|
|
|
|
self.known_bridges.contains(fingerprint)
|
2024-05-24 17:32:10 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn learn_bridge(&mut self, fingerprint: &[u8; 20]) {
|
|
|
|
self.known_bridges.insert(*fingerprint);
|
|
|
|
}
|
|
|
|
|
2024-05-24 18:16:30 -04:00
|
|
|
pub fn has_lox_cred(&self, fingerprint: &[u8; 20]) -> bool {
|
|
|
|
self.lox_credentials.contains_key(fingerprint)
|
2024-05-24 17:32:10 -04:00
|
|
|
}
|
|
|
|
|
2024-05-24 18:16:30 -04:00
|
|
|
pub fn give_lox_cred(&mut self, fingerprint: &[u8; 20], cred: &Lox) {
|
2024-05-24 17:32:10 -04:00
|
|
|
// We only need one level 3+ credential per bridge. (This will
|
|
|
|
// change if we restrict positive reports to one per bridge per
|
|
|
|
// credential.)
|
2024-05-24 18:16:30 -04:00
|
|
|
if !self.has_lox_cred(fingerprint) && scalar_u32(&cred.trust_level).unwrap() >= 3 {
|
|
|
|
// We want to clone the credential, but that's not allowed,
|
|
|
|
// so we're going to serialize it and then deserialize it.
|
|
|
|
let cloned_cred = bincode::deserialize(&bincode::serialize(&cred).unwrap()).unwrap();
|
|
|
|
self.lox_credentials.insert(*fingerprint, cloned_cred);
|
2024-05-24 17:32:10 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(PartialEq)]
|
|
|
|
pub enum Speed {
|
|
|
|
Fast,
|
|
|
|
Lox,
|
|
|
|
Random,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(PartialEq)]
|
|
|
|
pub enum Hides {
|
|
|
|
Overt,
|
|
|
|
Hiding,
|
|
|
|
Flooding,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(PartialEq)]
|
|
|
|
pub enum Totality {
|
|
|
|
Full,
|
|
|
|
Partial,
|
|
|
|
Throttling,
|
|
|
|
}
|