Kaynağa Gözat

Implement daily behavior for bridges and censors

Vecna 9 ay önce
ebeveyn
işleme
1cc9f7797b
2 değiştirilmiş dosya ile 110 ekleme ve 4 silme
  1. 34 3
      src/simulation/bridge.rs
  2. 76 1
      src/simulation/censor.rs

+ 34 - 3
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<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();
+    }
 }

+ 76 - 1
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)]