91 lines
3.8 KiB
Rust
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();
|
|
}
|
|
_ => (),
|
|
}
|
|
}
|
|
}
|