2024-05-24 20:09:24 -04:00
|
|
|
use crate::{
|
|
|
|
get_date,
|
|
|
|
simulation::{bridge::Bridge, state::State},
|
|
|
|
PositiveReport,
|
|
|
|
};
|
2024-05-24 17:32:10 -04:00
|
|
|
|
2024-05-24 20:09:24 -04:00
|
|
|
use lox_cli::{get_lox_pub, networking::Networking};
|
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
|
|
|
}
|
|
|
|
}
|
2024-05-24 20:09:24 -04:00
|
|
|
|
|
|
|
// Make a bunch of connections and submit positive reports if possible
|
|
|
|
async fn flood(&self, state: &State, bridges: &mut HashMap<[u8; 20], Bridge>) {
|
|
|
|
// Only do this if Flooding censor
|
|
|
|
if self.hides == Hides::Flooding {
|
|
|
|
for fingerprint in &self.known_bridges {
|
|
|
|
// Only do this if we're blocking the bridge
|
|
|
|
if self.speed == Speed::Fast
|
|
|
|
|| self.speed == Speed::Lox && self.has_lox_cred(fingerprint)
|
|
|
|
|| self.speed == Speed::Random && self.delay_date <= get_date()
|
|
|
|
{
|
|
|
|
let bridge = bridges.get_mut(fingerprint).unwrap();
|
|
|
|
let mut rng = rand::thread_rng();
|
|
|
|
let num_connections = rng.gen_range(1000..30000);
|
|
|
|
|
|
|
|
// Make a bunch of connections to the bridge
|
|
|
|
bridge.censor_flood(&self.country, num_connections);
|
|
|
|
|
|
|
|
// If we have a lv3+ credential, submit a bunch of
|
|
|
|
// positive reports
|
|
|
|
if self.has_lox_cred(fingerprint) {
|
|
|
|
let lox_pub = get_lox_pub(&state.la_pubkeys);
|
|
|
|
for _ in 0..num_connections {
|
|
|
|
let pr = PositiveReport::from_lox_credential(
|
|
|
|
bridge.fingerprint,
|
|
|
|
None,
|
|
|
|
&self.lox_credentials.get(&bridge.fingerprint).unwrap(),
|
|
|
|
lox_pub,
|
|
|
|
self.country.clone(),
|
|
|
|
)
|
|
|
|
.unwrap();
|
|
|
|
state
|
2024-05-24 22:55:29 -04:00
|
|
|
.tp_net
|
2024-05-24 20:09:24 -04:00
|
|
|
.request("/positivereport".to_string(), pr.to_json().into_bytes())
|
|
|
|
.await;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: How do we want to do this? We don't want to stop blocking
|
|
|
|
// bridges the day after we start.
|
|
|
|
fn recompute_delay(&mut self) {
|
|
|
|
// Only do this if Random censor
|
|
|
|
if self.speed == Speed::Random && self.delay_date <= get_date() {
|
|
|
|
// Compute new delay date
|
|
|
|
self.delay_date = {
|
|
|
|
let mut rng = rand::thread_rng();
|
|
|
|
let num: u32 = rng.gen_range(1..365);
|
|
|
|
get_date() + num
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub async fn end_of_day_tasks(
|
|
|
|
&mut self,
|
|
|
|
state: &State,
|
|
|
|
bridges: &mut HashMap<[u8; 20], Bridge>,
|
|
|
|
) {
|
|
|
|
if self.hides == Hides::Flooding
|
|
|
|
&& !(self.speed == Speed::Random && self.delay_date <= get_date())
|
|
|
|
{
|
|
|
|
self.flood(state, bridges).await;
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: recompute_delay sometimes
|
|
|
|
//self.recompute_delay();
|
|
|
|
}
|
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,
|
|
|
|
}
|