From 1cc9f7797b7817a0286573d63351e2d272cfb827 Mon Sep 17 00:00:00 2001 From: Vecna Date: Fri, 24 May 2024 20:09:24 -0400 Subject: [PATCH] Implement daily behavior for bridges and censors --- src/simulation/bridge.rs | 37 +++++++++++++++++-- src/simulation/censor.rs | 77 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 110 insertions(+), 4 deletions(-) diff --git a/src/simulation/bridge.rs b/src/simulation/bridge.rs index 1b6c4b1..9ece496 100644 --- a/src/simulation/bridge.rs +++ b/src/simulation/bridge.rs @@ -1,10 +1,12 @@ +use crate::{extra_info::ExtraInfo, get_date}; use lox_library::bridge_table::BridgeLine; -use std::collections::HashMap; +use std::collections::{BTreeMap, HashMap}; +// The Bridge struct only tracks data for today pub struct Bridge { pub fingerprint: [u8; 20], real_connections: HashMap, - total_connections: HashMap, + total_connections: BTreeMap, } impl Bridge { @@ -12,7 +14,7 @@ impl Bridge { Self { fingerprint: *fingerprint, real_connections: HashMap::::new(), - total_connections: HashMap::::new(), + total_connections: BTreeMap::::new(), } } @@ -46,4 +48,33 @@ impl Bridge { .unwrap(); } } + + // Let the censor simulate a bunch of connections at once + pub fn censor_flood(&mut self, country: &str, num_connections: u32) { + if self.total_connections.contains_key(country) { + let prev = self.total_connections.get(country).unwrap(); + self.total_connections + .insert(country.to_string(), prev + num_connections) + .unwrap(); + } else { + self.total_connections + .insert(country.to_string(), num_connections) + .unwrap(); + } + } + + // Generate an extra-info report for today + pub fn gen_extra_info(&self) -> ExtraInfo { + ExtraInfo { + nickname: String::default(), + fingerprint: self.fingerprint, + date: get_date(), + bridge_ips: self.total_connections.clone(), + } + } + + fn reset_for_tomorrow(&mut self) { + self.real_connections = HashMap::::new(); + self.total_connections = BTreeMap::::new(); + } } diff --git a/src/simulation/censor.rs b/src/simulation/censor.rs index d0f15b9..36716fa 100644 --- a/src/simulation/censor.rs +++ b/src/simulation/censor.rs @@ -1,5 +1,10 @@ -use crate::get_date; +use crate::{ + get_date, + simulation::{bridge::Bridge, state::State}, + PositiveReport, +}; +use lox_cli::{get_lox_pub, networking::Networking}; use lox_library::{cred::Lox, scalar_u32}; use rand::Rng; use std::collections::{HashMap, HashSet}; @@ -76,6 +81,76 @@ impl Censor { self.lox_credentials.insert(*fingerprint, cloned_cred); } } + + // 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 + .net_tp + .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(); + } } #[derive(PartialEq)]