lox/crates/lox-distributor/src/request_handler.rs

181 lines
6.9 KiB
Rust
Raw Normal View History

use hyper::{body, header::HeaderValue, Body, Method, Request, Response, StatusCode};
use std::convert::Infallible;
use crate::lox_context;
use crate::lox_context::LoxServerContext;
// Lox Request handling logic for each Lox request/protocol
pub async fn handle(
cloned_context: LoxServerContext,
req: Request<Body>,
) -> Result<Response<Body>, Infallible> {
println!("Request: {:?}", req);
match req.method() {
&Method::OPTIONS => Ok(Response::builder()
.header("Access-Control-Allow-Origin", HeaderValue::from_static("*"))
.header("Access-Control-Allow-Headers", "accept, content-type")
.header("Access-Control-Allow-Methods", "POST")
.status(200)
.body(Body::from("Allow POST"))
.unwrap()),
_ => match (req.method(), req.uri().path()) {
(&Method::POST, "/invite") => {
Ok::<_, Infallible>(lox_context::generate_invite(cloned_context))
}
(&Method::POST, "/reachability") => {
Ok::<_, Infallible>(lox_context::send_reachability_cred(cloned_context))
}
(&Method::POST, "/pubkeys") => {
Ok::<_, Infallible>(lox_context::send_keys(cloned_context))
}
(&Method::POST, "/openreq") => Ok::<_, Infallible>({
let bytes = body::to_bytes(req.into_body()).await.unwrap();
lox_context::verify_and_send_open_cred(bytes, cloned_context)
}),
(&Method::POST, "/trustpromo") => Ok::<_, Infallible>({
let bytes = body::to_bytes(req.into_body()).await.unwrap();
lox_context::verify_and_send_trust_promo(bytes, cloned_context)
}),
(&Method::POST, "/trustmig") => Ok::<_, Infallible>({
let bytes = body::to_bytes(req.into_body()).await.unwrap();
lox_context::verify_and_send_trust_migration(bytes, cloned_context)
}),
(&Method::POST, "/levelup") => Ok::<_, Infallible>({
let bytes = body::to_bytes(req.into_body()).await.unwrap();
lox_context::verify_and_send_level_up(bytes, cloned_context)
}),
(&Method::POST, "/issueinvite") => Ok::<_, Infallible>({
let bytes = body::to_bytes(req.into_body()).await.unwrap();
lox_context::verify_and_send_issue_invite(bytes, cloned_context)
}),
(&Method::POST, "/redeem") => Ok::<_, Infallible>({
let bytes = body::to_bytes(req.into_body()).await.unwrap();
lox_context::verify_and_send_redeem_invite(bytes, cloned_context)
}),
(&Method::POST, "/checkblockage") => Ok::<_, Infallible>({
let bytes = body::to_bytes(req.into_body()).await.unwrap();
// TEST ONLY: Block all existing bridges and add new ones for migration
lox_context::verify_and_send_check_blockage(bytes, cloned_context)
}),
(&Method::POST, "/blockagemigration") => Ok::<_, Infallible>({
let bytes = body::to_bytes(req.into_body()).await.unwrap();
lox_context::verify_and_send_blockage_migration(bytes, cloned_context)
}),
_ => {
// Return 404 not found response.
Ok(Response::builder()
.status(StatusCode::NOT_FOUND)
.body(Body::from("Not found"))
.unwrap())
}
},
}
}
2023-06-05 18:26:59 -04:00
#[cfg(test)]
mod tests {
use super::*;
use lox::{BridgeAuth, BridgeDb};
use std::sync::{Arc, Mutex};
trait LoxClient {
fn invite(&self) -> Request<Body>;
fn reachability(&self) -> Request<Body>;
fn pubkeys(&self) -> Request<Body>;
}
struct LoxClientMock {}
impl LoxClient for LoxClientMock {
fn invite(&self) -> Request<Body> {
let req = Request::builder()
.method("POST")
.uri("http://localhost/invite")
.body(Body::empty())
.unwrap();
req
}
fn reachability(&self) -> Request<Body> {
let req = Request::builder()
.method("POST")
.uri("http://localhost/reachability")
.body(Body::empty())
.unwrap();
req
}
fn pubkeys(&self) -> Request<Body> {
let req = Request::builder()
.method("POST")
.uri("http://localhost/pubkeys")
.body(Body::empty())
.unwrap();
req
}
}
struct TestHarness {
context: LoxServerContext,
}
impl TestHarness {
fn new() -> Self {
let mut bridgedb = BridgeDb::new();
let mut lox_auth = BridgeAuth::new(bridgedb.pubkey);
// Make 3 x num_buckets open invitation bridges, in sets of 3
for _ in 0..5 {
let bucket = [
lox_context::random(),
lox_context::random(),
lox_context::random(),
];
lox_auth.add_openinv_bridges(bucket, &mut bridgedb);
}
// Add hot_spare more hot spare buckets
for _ in 0..5 {
let bucket = [
lox_context::random(),
lox_context::random(),
lox_context::random(),
];
lox_auth.add_spare_bucket(bucket);
}
// Create the encrypted bridge table
lox_auth.enc_bridge_table();
let context = lox_context::LoxServerContext {
db: Arc::new(Mutex::new(bridgedb)),
ba: Arc::new(Mutex::new(lox_auth)),
extra_bridges: Arc::new(Mutex::new(Vec::new())),
unreplaced_bridges: Arc::new(Mutex::new(Vec::new())),
};
Self { context }
}
}
#[tokio::test]
async fn test_handle() {
let th = TestHarness::new();
let lc = LoxClientMock {};
// Test Invite
let invite_request = lc.invite();
let response = handle(th.context.clone(), invite_request).await.unwrap();
println!("Server response?: {:?}", response);
assert_eq!(response.status(), StatusCode::OK);
// Test Reachability
let reachability_request = lc.reachability();
let reachability_response = handle(th.context.clone(), reachability_request)
.await
.unwrap();
println!("Server response?: {:?}", reachability_response);
assert_eq!(reachability_response.status(), StatusCode::OK);
// Test Pubkeys
let pubkey_request = lc.pubkeys();
let pubkey_response = handle(th.context.clone(), pubkey_request).await.unwrap();
println!("Server response?: {:?}", pubkey_response);
assert_eq!(pubkey_response.status(), StatusCode::OK);
}
}