use futures_util::stream::StreamExt; mod connection; use crate::command::service::CommandManagementService; use crate::http::backend::connection::BackendConnection; use crate::telemetry::management_service::TelemetryManagementService; use actix_web::{rt, web, HttpRequest, HttpResponse}; use log::{error, trace}; use std::sync::Arc; use tokio::select; use tokio_util::sync::CancellationToken; async fn backend_connect( req: HttpRequest, stream: web::Payload, cancel_token: web::Data, telemetry_management_service: web::Data>, command_management_service: web::Data>, ) -> Result { trace!("backend_connect"); let (res, session, stream) = actix_ws::handle(&req, stream)?; let mut stream = stream .aggregate_continuations() // up to 1 MiB .max_continuation_size(2_usize.pow(20)); let cancel_token = cancel_token.get_ref().clone(); let tlm_management = telemetry_management_service.get_ref().clone(); let cmd_management = command_management_service.get_ref().clone(); rt::spawn(async move { let mut connection = BackendConnection::new(session, tlm_management, cmd_management); while !connection.should_close { let result = select! { _ = cancel_token.cancelled() => { connection.should_close = true; Ok(()) }, Some(msg) = connection.rx.recv() => connection.handle_response(msg).await, Some(msg) = stream.next() => connection.handle_request_message(msg).await, else => { connection.should_close = true; Ok(()) }, }; if let Err(e) = result { error!("backend socket error: {e}"); connection.should_close = true; } } connection.cleanup().await; }); Ok(res) } pub fn setup_backend(cfg: &mut web::ServiceConfig) { cfg.route("", web::get().to(backend_connect)); }