Implement daily behavior for bridges and censors

This commit is contained in:
Vecna 2024-05-24 20:09:24 -04:00
parent 690019f4c5
commit 1cc9f7797b
2 changed files with 110 additions and 4 deletions

View File

@ -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<String, u32>,
total_connections: HashMap<String, u32>,
total_connections: BTreeMap<String, u32>,
}
impl Bridge {
@ -12,7 +14,7 @@ impl Bridge {
Self {
fingerprint: *fingerprint,
real_connections: HashMap::<String, u32>::new(),
total_connections: HashMap::<String, u32>::new(),
total_connections: BTreeMap::<String, u32>::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::<String, u32>::new();
self.total_connections = BTreeMap::<String, u32>::new();
}
}

View File

@ -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)]