direct_scan_server.rs 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. // Simulates direct scans by keeping a list of bridges blocked by the censor
  2. use hyper::{
  3. body::{self, Bytes},
  4. header::HeaderValue,
  5. server::conn::AddrStream,
  6. service::{make_service_fn, service_fn},
  7. Body, Method, Request, Response, Server, StatusCode,
  8. };
  9. use serde_json::json;
  10. use std::{
  11. collections::{HashMap, HashSet},
  12. convert::Infallible,
  13. net::SocketAddr,
  14. time::Duration,
  15. };
  16. use tokio::{
  17. spawn,
  18. sync::{mpsc, oneshot},
  19. time::sleep,
  20. };
  21. async fn serve_direct_scan_api(
  22. // We have to serialize our HashMap keys as Strings instead of [u8; 20]s,
  23. // so it's easier to just use Strings throughout.
  24. blocked_bridges: &mut HashSet<String>,
  25. guessed_bridges: &mut HashMap<String, HashSet<String>>,
  26. req: Request<Body>,
  27. ) -> Result<Response<Body>, Infallible> {
  28. match req.method() {
  29. &Method::OPTIONS => Ok(Response::builder()
  30. .header("Access-Control-Allow-Origin", HeaderValue::from_static("*"))
  31. .header("Access-Control-Allow-Headers", "accept, content-type")
  32. .header("Access-Control-Allow-Methods", "POST")
  33. .status(200)
  34. .body(Body::from("Allow POST"))
  35. .unwrap()),
  36. _ => match req.uri().path() {
  37. "/add_blocked_bridges" => Ok::<_, Infallible>({
  38. let bytes = body::to_bytes(req.into_body()).await.unwrap();
  39. add_blocked_bridges(blocked_bridges, bytes)
  40. }),
  41. "/verify_blocked_bridges" => Ok::<_, Infallible>({
  42. let bytes = body::to_bytes(req.into_body()).await.unwrap();
  43. verify_blocked_bridges(blocked_bridges, guessed_bridges, bytes)
  44. }),
  45. // Get the bridges Troll Patrol guessed were blocked today
  46. "/get_guessed_bridges" => Ok::<_, Infallible>({
  47. prepare_header(serde_json::to_string(&guessed_bridges).unwrap())
  48. }),
  49. // Reset guessed bridges at the beginning of the day
  50. "/reset_guessed_bridges" => Ok::<_, Infallible>({
  51. *guessed_bridges = HashMap::<String, HashSet<String>>::new();
  52. prepare_header("OK".to_string())
  53. }),
  54. _ => Ok::<_, Infallible>({
  55. Response::builder()
  56. .status(StatusCode::NOT_FOUND)
  57. .body(Body::from("Not found"))
  58. .unwrap()
  59. }),
  60. },
  61. }
  62. }
  63. pub async fn server() {
  64. let (context_tx, context_rx) = mpsc::channel(32);
  65. let request_tx = context_tx.clone();
  66. spawn(async move { create_context_manager(context_rx).await });
  67. let addr = SocketAddr::from(([127, 0, 0, 1], 8006));
  68. let make_svc = make_service_fn(move |_conn: &AddrStream| {
  69. let request_tx = request_tx.clone();
  70. let service = service_fn(move |req| {
  71. let request_tx = request_tx.clone();
  72. let (response_tx, response_rx) = oneshot::channel();
  73. let cmd = Command::Request {
  74. req,
  75. sender: response_tx,
  76. };
  77. async move {
  78. request_tx.send(cmd).await.unwrap();
  79. response_rx.await.unwrap()
  80. }
  81. });
  82. async move { Ok::<_, Infallible>(service) }
  83. });
  84. let server = Server::bind(&addr).serve(make_svc);
  85. println!("Listening on localhost:8006");
  86. if let Err(e) = server.await {
  87. eprintln!("server error: {}", e);
  88. }
  89. }
  90. async fn create_context_manager(context_rx: mpsc::Receiver<Command>) {
  91. tokio::select! {
  92. create_context = context_manager(context_rx) => create_context,
  93. }
  94. }
  95. async fn context_manager(mut context_rx: mpsc::Receiver<Command>) {
  96. let mut blocked_bridges = HashSet::<String>::new();
  97. let mut guessed_bridges = HashMap::<String, HashSet<String>>::new();
  98. while let Some(cmd) = context_rx.recv().await {
  99. use Command::*;
  100. match cmd {
  101. Request { req, sender } => {
  102. let response =
  103. serve_direct_scan_api(&mut blocked_bridges, &mut guessed_bridges, req).await;
  104. if let Err(e) = sender.send(response) {
  105. eprintln!("Server Response Error: {:?}", e);
  106. }
  107. sleep(Duration::from_millis(1)).await;
  108. }
  109. }
  110. }
  111. }
  112. #[derive(Debug)]
  113. enum Command {
  114. Request {
  115. req: Request<Body>,
  116. sender: oneshot::Sender<Result<Response<Body>, Infallible>>,
  117. },
  118. }
  119. fn add_blocked_bridges(blocked_bridges: &mut HashSet<String>, request: Bytes) -> Response<Body> {
  120. let new_blocked_bridges: HashSet<String> = match serde_json::from_slice(&request) {
  121. Ok(req) => req,
  122. Err(e) => {
  123. let response = json!({"error": e.to_string()});
  124. let val = serde_json::to_string(&response).unwrap();
  125. return prepare_header(val);
  126. }
  127. };
  128. blocked_bridges.extend(new_blocked_bridges);
  129. prepare_header("OK".to_string())
  130. }
  131. fn verify_blocked_bridges(
  132. blocked_bridges: &mut HashSet<String>,
  133. guessed_bridges: &mut HashMap<String, HashSet<String>>,
  134. request: Bytes,
  135. ) -> Response<Body> {
  136. let mut verified_blocked_bridges = HashMap::<String, HashSet<String>>::new();
  137. let possibly_blocked_bridges: HashMap<String, HashSet<String>> =
  138. match serde_json::from_slice(&request) {
  139. Ok(req) => req,
  140. Err(e) => {
  141. let response = json!({"error": e.to_string()});
  142. let val = serde_json::to_string(&response).unwrap();
  143. return prepare_header(val);
  144. }
  145. };
  146. *guessed_bridges = possibly_blocked_bridges.clone();
  147. for (fpr, countries) in possibly_blocked_bridges {
  148. if blocked_bridges.contains(&fpr) {
  149. verified_blocked_bridges.insert(fpr, countries);
  150. }
  151. }
  152. prepare_header(serde_json::to_string(&verified_blocked_bridges).unwrap())
  153. }
  154. // Prepare HTTP Response for successful Server Request
  155. fn prepare_header(response: String) -> Response<Body> {
  156. let mut resp = Response::new(Body::from(response));
  157. resp.headers_mut()
  158. .insert("Access-Control-Allow-Origin", HeaderValue::from_static("*"));
  159. resp
  160. }