use crate::get_date; 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, } } pub fn knows_bridge(&self, fingerprint: &[u8; 20]) -> bool { self.known_bridges.contains(fingerprint) } pub fn learn_bridge(&mut self, fingerprint: &[u8; 20]) { self.known_bridges.insert(*fingerprint); } pub fn has_lox_cred(&self, fingerprint: &[u8; 20]) -> bool { self.lox_credentials.contains_key(fingerprint) } pub fn give_lox_cred(&mut self, fingerprint: &[u8; 20], cred: &Lox) { // We only need one level 3+ credential per bridge. (This will // change if we restrict positive reports to one per bridge per // credential.) 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); } } } #[derive(PartialEq)] pub enum Speed { Fast, Lox, Random, } #[derive(PartialEq)] pub enum Hides { Overt, Hiding, Flooding, } #[derive(PartialEq)] pub enum Totality { Full, Partial, Throttling, }