Browse Source

Add support for verifying Troll Patrol's inferences

Vecna 3 months ago
parent
commit
ff3aa2d718
2 changed files with 76 additions and 2 deletions
  1. 65 0
      src/lib.rs
  2. 11 2
      src/main.rs

+ 65 - 0
src/lib.rs

@@ -837,6 +837,71 @@ pub fn guess_blockages(
     blockages
     blockages
 }
 }
 
 
+/// Verify bridges suspected of being blocked, return only the ones that are
+/// actually blocked
+pub async fn verify_blockages(
+    verify_blockages_url: &str,
+    suspected_blockages: HashMap<[u8; 20], HashSet<String>>,
+) -> HashMap<[u8; 20], HashSet<String>> {
+    // If we don't have a resource for checking if bridges are blocked, assume
+    // that Troll Patrol guessed correctly
+    if verify_blockages_url.is_empty() {
+        return suspected_blockages;
+    }
+
+    // Convert map keys from [u8; 20] to 40-character hex strings
+    let mut suspected_blockages_str = HashMap::<String, HashSet<String>>::new();
+    for (fingerprint, countries) in &suspected_blockages {
+        let fpr_string = array_bytes::bytes2hex("", fingerprint);
+        if !countries.is_empty() {
+            suspected_blockages_str.insert(fpr_string, countries.clone());
+        }
+    }
+
+    if !suspected_blockages_str.is_empty() {
+        // Send suspected blockages to verification endpoint for verification
+        let client = Client::new();
+        let req = Request::builder()
+            .method(Method::POST)
+            .uri(verify_blockages_url)
+            .body(Body::from(
+                serde_json::to_string(&suspected_blockages_str).unwrap(),
+            ))
+            .unwrap();
+        let resp = client.request(req).await.unwrap();
+        let buf = hyper::body::to_bytes(resp).await.unwrap();
+        let resp_str = String::from_utf8(buf.to_vec()).unwrap();
+
+        // Deserialize map
+        let blockages_str: HashMap<String, HashSet<String>> = match serde_json::from_str(&resp_str)
+        {
+            Ok(v) => v,
+            Err(e) => {
+                eprintln!(
+                    "Failed to deserialize response from verification endpoint: {:?}",
+                    e
+                );
+                HashMap::<String, HashSet<String>>::new()
+            }
+        };
+
+        // Convert map so it uses [u8; 20]s as keys again
+        let mut blockages = HashMap::<[u8; 20], HashSet<String>>::new();
+        for (fingerprint, countries) in blockages_str {
+            if let Ok(fpr) = array_bytes::hex2array(fingerprint) {
+                if !countries.is_empty() {
+                    blockages.insert(fpr, countries);
+                }
+            }
+        }
+
+        // Return map of confirmed blockages
+        blockages
+    } else {
+        suspected_blockages
+    }
+}
+
 /// Commit blocked bridges to database
 /// Commit blocked bridges to database
 pub fn commit_blockages(db: &Db, blockages: &HashMap<[u8; 20], HashSet<String>>) {
 pub fn commit_blockages(db: &Db, blockages: &HashMap<[u8; 20], HashSet<String>>) {
     // For each bridge:<set of countries>, mark the bridge as blocked in each country
     // For each bridge:<set of countries>, mark the bridge as blocked in each country

+ 11 - 2
src/main.rs

@@ -51,6 +51,7 @@ pub struct Config {
     // map of distributor name to IP:port to contact it
     // map of distributor name to IP:port to contact it
     pub distributors: BTreeMap<BridgeDistributor, String>,
     pub distributors: BTreeMap<BridgeDistributor, String>,
     extra_infos_base_url: String,
     extra_infos_base_url: String,
+    verify_blockages_url: String,
 
 
     // confidence required to consider a bridge blocked
     // confidence required to consider a bridge blocked
     confidence: f64,
     confidence: f64,
@@ -92,6 +93,7 @@ async fn update_daily_info(
     db: &Db,
     db: &Db,
     distributors: &BTreeMap<BridgeDistributor, String>,
     distributors: &BTreeMap<BridgeDistributor, String>,
     extra_infos_base_url: &str,
     extra_infos_base_url: &str,
+    verify_blockages_url: &str,
     confidence: f64,
     confidence: f64,
     max_threshold: u32,
     max_threshold: u32,
     scaling_factor: f64,
     scaling_factor: f64,
@@ -109,7 +111,10 @@ async fn update_daily_info(
         min_historical_days,
         min_historical_days,
         max_historical_days,
         max_historical_days,
     );
     );
-    // TODO: Verify the new blockages
+
+    // This implementation will vary based on scanning infrastructure
+    let new_blockages = verify_blockages(verify_blockages_url, new_blockages).await;
+
     commit_blockages(db, &new_blockages);
     commit_blockages(db, &new_blockages);
     report_blockages(distributors, new_blockages.clone()).await;
     report_blockages(distributors, new_blockages.clone()).await;
 
 
@@ -132,6 +137,7 @@ async fn create_context_manager(
     db_config: DbConfig,
     db_config: DbConfig,
     distributors: BTreeMap<BridgeDistributor, String>,
     distributors: BTreeMap<BridgeDistributor, String>,
     extra_infos_base_url: &str,
     extra_infos_base_url: &str,
+    verify_blockages_url: &str,
     confidence: f64,
     confidence: f64,
     max_threshold: u32,
     max_threshold: u32,
     scaling_factor: f64,
     scaling_factor: f64,
@@ -141,7 +147,7 @@ async fn create_context_manager(
     mut kill: broadcast::Receiver<()>,
     mut kill: broadcast::Receiver<()>,
 ) {
 ) {
     tokio::select! {
     tokio::select! {
-        create_context = context_manager(db_config, distributors, extra_infos_base_url, confidence, max_threshold, scaling_factor, min_historical_days, max_historical_days, context_rx) => create_context,
+        create_context = context_manager(db_config, distributors, extra_infos_base_url, verify_blockages_url, confidence, max_threshold, scaling_factor, min_historical_days, max_historical_days, context_rx) => create_context,
         _ = kill.recv() => {println!("Shut down manager");},
         _ = kill.recv() => {println!("Shut down manager");},
     }
     }
 }
 }
@@ -150,6 +156,7 @@ async fn context_manager(
     db_config: DbConfig,
     db_config: DbConfig,
     distributors: BTreeMap<BridgeDistributor, String>,
     distributors: BTreeMap<BridgeDistributor, String>,
     extra_infos_base_url: &str,
     extra_infos_base_url: &str,
+    verify_blockages_url: &str,
     confidence: f64,
     confidence: f64,
     max_threshold: u32,
     max_threshold: u32,
     scaling_factor: f64,
     scaling_factor: f64,
@@ -202,6 +209,7 @@ async fn context_manager(
                     &db,
                     &db,
                     &distributors,
                     &distributors,
                     extra_infos_base_url,
                     extra_infos_base_url,
+                    verify_blockages_url,
                     confidence,
                     confidence,
                     max_threshold,
                     max_threshold,
                     scaling_factor,
                     scaling_factor,
@@ -296,6 +304,7 @@ async fn main() {
             config.db,
             config.db,
             config.distributors,
             config.distributors,
             &config.extra_infos_base_url,
             &config.extra_infos_base_url,
+            &config.verify_blockages_url,
             config.confidence,
             config.confidence,
             config.max_threshold,
             config.max_threshold,
             config.scaling_factor,
             config.scaling_factor,