use std::sync::{Arc, LazyLock, RwLock}; use axum::{ Extension, Json, Router, http::StatusCode, response::IntoResponse, routing::{get, post}, }; use axum_macros::debug_handler; use protocol::{Signal, User, UserAndSignal}; use tokio::net::TcpListener; use tower_http::{cors::CorsLayer, trace::TraceLayer}; use crate::middleware::{ UserAndExpectedSignal, verify_then_get_user, verify_then_get_user_and_expected_signal, }; static USERS_AND_SIGNALS: LazyLock>> = LazyLock::new(|| RwLock::new(vec![])); pub async fn start_signalling() { let route = route() .layer(CorsLayer::permissive()) .layer(TraceLayer::new_for_http()); let listener = TcpListener::bind("192.168.1.3:4546").await.unwrap(); println!("http://192.168.1.3:4546"); axum::serve(listener, route).await.unwrap(); } fn route() -> Router { Router::new() .route("/alive", get(alive)) .route( "/", get(read_signal).route_layer(axum::middleware::from_fn( verify_then_get_user_and_expected_signal, )), ) .route( "/", post(create_signal).route_layer(axum::middleware::from_fn(verify_then_get_user)), ) } async fn alive() -> impl IntoResponse { StatusCode::OK } #[debug_handler] async fn create_signal( Extension(user): Extension>, Json(signal): Json, ) -> impl IntoResponse { let user = (*user).clone(); let user_and_signal = UserAndSignal::new(user, signal).await; USERS_AND_SIGNALS.write().unwrap().push(user_and_signal); StatusCode::OK } async fn read_signal( Extension(user_and_expected_signal): Extension>, ) -> impl IntoResponse { let mut target_index = None; let mut json_body = serde_json::json!(""); for (index, user_and_signal) in USERS_AND_SIGNALS.read().unwrap().iter().enumerate() { if user_and_signal.signal.get_signal_type() == user_and_expected_signal.expected_signal { json_body = serde_json::json!(user_and_signal); target_index = Some(index); } } match target_index { Some(target_index) => { USERS_AND_SIGNALS.write().unwrap().remove(target_index); (StatusCode::OK, Json(json_body)).into_response() } None => StatusCode::BAD_REQUEST.into_response(), } }