baobab/interfaces/websocket/server/src/handler.rs
2025-07-29 01:15:23 +02:00

91 lines
3.8 KiB
Rust

use actix::prelude::*;
use actix_web_actors::ws;
use log::debug;
use serde_json::Value;
use crate::{Server, JsonRpcRequest, JsonRpcResponse, JsonRpcError};
impl actix::StreamHandler<Result<ws::Message, ws::ProtocolError>> for Server {
fn handle(&mut self, msg: Result<ws::Message, ws::ProtocolError>, ctx: &mut Self::Context) {
match msg {
Ok(ws::Message::Text(text)) => {
debug!("WS Text for {}: {}", self.circle_name, text);
// Handle plaintext ping messages for keep-alive
if text.trim() == "ping" {
debug!("Received keep-alive ping from {}, responding with pong", self.circle_name);
ctx.text("pong");
return;
}
match serde_json::from_str::<JsonRpcRequest>(&text) {
Ok(req) => {
let client_rpc_id = req.id.clone().unwrap_or(Value::Null);
match req.method.as_str() {
"fetch_nonce" => {
self.handle_fetch_nonce(req.params, client_rpc_id, ctx)
}
"authenticate" => {
self.handle_authenticate(req.params, client_rpc_id, ctx)
}
"whoami" => {
self.handle_whoami(req.params, client_rpc_id, ctx)
}
"play" => self.handle_play(req.params, client_rpc_id, ctx),
_ => {
let err_resp = JsonRpcResponse {
jsonrpc: "2.0".to_string(),
result: None,
error: Some(JsonRpcError {
code: -32601,
message: format!("Method not found: {}", req.method),
data: None,
}),
id: client_rpc_id,
};
ctx.text(serde_json::to_string(&err_resp).unwrap());
}
}
}
Err(e) => {
log::error!(
"WS Error: Failed to parse JSON: {}, original text: '{}'",
e,
text
);
let err_resp = JsonRpcResponse {
jsonrpc: "2.0".to_string(),
result: None,
error: Some(JsonRpcError {
code: -32700,
message: "Failed to parse JSON request".to_string(),
data: Some(Value::String(text.to_string())),
}),
id: Value::Null,
};
ctx.text(serde_json::to_string(&err_resp).unwrap());
}
}
}
Ok(ws::Message::Ping(msg)) => ctx.pong(&msg),
Ok(ws::Message::Close(reason)) => {
log::info!(
"WebSocket connection closing for server {}: {:?}",
self.circle_name,
reason
);
ctx.close(reason);
ctx.stop();
}
Err(e) => {
log::error!(
"WebSocket error for server {}: {}",
self.circle_name,
e
);
ctx.stop();
}
_ => (),
}
}
}