diff --git a/Cargo.toml b/Cargo.toml
index 80909de..03a8543 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -6,6 +6,7 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
+anyhow = "1.0.75"
axum = { version = "0.6.20", features = ["ws", "headers"] }
futures = "0.3.28"
geo = "0.26.0"
diff --git a/pub/index.html b/pub/index.html
index 41ae32d..90180b6 100644
--- a/pub/index.html
+++ b/pub/index.html
@@ -14,6 +14,8 @@
class="button2x" value="#ffffff">
+
diff --git a/pub/main.js b/pub/main.js
index 511594d..bcca9f5 100644
--- a/pub/main.js
+++ b/pub/main.js
@@ -55,7 +55,7 @@ const updateCanvas = (canvas, ctx, lines) => {
}
};
-const initDrawing = (canvas, clearButton, selectedColor, ws) => {
+const initDrawing = (canvas, clearButton, errButton, selectedColor, ws) => {
const ctx = canvas.getContext("2d");
ctx.lineWidth = 2;
let lines = [];
@@ -68,10 +68,14 @@ const initDrawing = (canvas, clearButton, selectedColor, ws) => {
resetCanvas();
clearButton.onclick = evt => {
- lines = [];
- resetCanvas();
ws.send(JSON.stringify({ t: "clear" }));
};
+
+ if (errButton) {
+ errButton.onclick = evt => {
+ ws.send(JSON.stringify({ t: "error", msg: "this is an error" }));
+ };
+ }
canvas.addEventListener("mousedown", evt => {
const pt = getMousePoint(canvas, evt, selectedColor.value);
@@ -89,7 +93,7 @@ const initDrawing = (canvas, clearButton, selectedColor, ws) => {
});
canvas.addEventListener("mouseup", evt => {
- console.log(currentLine);
+ // console.log(currentLine);
currentLine = null;
ws.send(JSON.stringify({ t: "stroke"}));
});
@@ -109,7 +113,7 @@ const initDrawing = (canvas, clearButton, selectedColor, ws) => {
};
const initWs = errorBox => {
- const socket = new WebSocket('ws://localhost:3000/ws');
+ const socket = new WebSocket('ws://'+ location.host + '/ws');
socket.addEventListener('open', function (event) {
console.log("Open", event);
@@ -131,9 +135,10 @@ window.onload = () => {
const colorsDiv = document.querySelector("#colors");
const selectedColor = document.querySelector("#selectedColor");
const clearButton = document.querySelector("#clearButton");
+ const errButton = document.querySelector("#errButton");
const errorBox = document.querySelector("#errorBox");
const canvas = document.querySelector("#canvas");
initUI(colorsDiv, selectedColor);
let ws = initWs(errorBox);
- initDrawing(canvas, clearButton, selectedColor, ws);
+ initDrawing(canvas, clearButton, errButton, selectedColor, ws);
};
diff --git a/src/gen_server.rs b/src/gen_server.rs
index 758321b..3a75e54 100644
--- a/src/gen_server.rs
+++ b/src/gen_server.rs
@@ -25,7 +25,10 @@ async fn gen_server(mut rx: Receiver) {
match msg {
GSMsg::NewClient((addr, c_tx)) => {
for line in &lines {
- c_tx.send(GSMsg::NewLine(line.clone())).await.unwrap();
+ let ret = c_tx.send(GSMsg::NewLine(line.clone())).await;
+ if let Err(err) = ret {
+ tracing::warn!("Client {addr} send error: {err}");
+ }
}
clients.insert(addr, c_tx);
tracing::info!("NewClient {addr}");
@@ -53,11 +56,9 @@ async fn send_all(
let mut to_remove : Vec = vec![];
for (addr, ref mut tx) in clients.iter() {
- let ret = tx
- .send(msg.clone())
- .await;
- if ret.is_err() {
- tracing::warn!("Client {addr} abruptly disconnected");
+ let ret = tx.send(msg.clone()).await;
+ if let Err(err) = ret {
+ tracing::warn!("Client {addr} abruptly disconnected: {err}");
to_remove.push(*addr);
}
}
diff --git a/src/main.rs b/src/main.rs
index cb957cc..0d88da2 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -25,9 +25,10 @@ use gen_server::GSMsg;
const LISTEN_ON : &str = "0.0.0.0:3000";
#[tokio::main]
-async fn main() {
+async fn main() -> anyhow::Result<()> {
tracing_subscriber::registry()
- .with(tracing_subscriber::EnvFilter::try_from_default_env()
+ //.with(tracing_subscriber::EnvFilter::try_from_default_env()
+ .with(tracing_subscriber::EnvFilter::try_from_env("LJ_SKETCH")
.unwrap_or_else(|_| "lj_sketch=info,tower_http=info".into()))
.with(tracing_subscriber::fmt::layer())
.init();
@@ -45,13 +46,12 @@ async fn main() {
.make_span_with(DefaultMakeSpan::default()
.include_headers(false)));
- let addr : SocketAddr = LISTEN_ON.parse().unwrap();
-
- tracing::info!("listening on {}", addr);
+ let addr : SocketAddr = LISTEN_ON.parse()?;
+ tracing::info!("listening on {}", addr);
axum::Server::bind(&addr)
.serve(app.into_make_service_with_connect_info::())
- .await
- .unwrap();
+ .await?;
+ Ok(())
}
async fn ws_handler(
diff --git a/src/ws_client.rs b/src/ws_client.rs
index adc32a2..49c45d7 100644
--- a/src/ws_client.rs
+++ b/src/ws_client.rs
@@ -1,8 +1,10 @@
-use axum::extract::ws::{Message, Message::Text, Message::Close, WebSocket};
+use axum::extract::ws::{Message, WebSocket};
use std::net::SocketAddr;
use tokio::sync::mpsc::{self, Sender};
use serde::{Serialize, Deserialize};
use core::ops::ControlFlow;
+use anyhow::{Result,anyhow};
+
use crate::gen_server::GSMsg;
use crate::line::{Line, simplify_line};
@@ -22,12 +24,23 @@ enum JMsg {
}
pub async fn handle_socket(
- mut socket: WebSocket,
+ socket: WebSocket,
who: SocketAddr,
gs_tx: Sender
) {
+ match handle_socket_(socket, who, gs_tx).await {
+ Ok(()) => {},
+ Err(err) => tracing::warn!("{who}: WS Handler error: {err}")
+ }
+}
+
+pub async fn handle_socket_(
+ mut socket: WebSocket,
+ who: SocketAddr,
+ gs_tx: Sender
+) -> Result<()> {
let (chan_tx, mut chan_rx) = mpsc::channel(32);
- gs_tx.send(GSMsg::NewClient((who, chan_tx))).await.unwrap();
+ gs_tx.send(GSMsg::NewClient((who, chan_tx))).await?;
let mut line : Line = vec![];
loop {
@@ -37,18 +50,15 @@ pub async fn handle_socket(
tracing::warn!("{who}: Error receiving packet: {msg:?}");
continue;
};
- match process_ws_msg(&gs_tx, &who, &mut line, msg).await {
- ControlFlow::Break(()) => break,
+ match process_ws_msg(&gs_tx, &who, &mut line, msg).await? {
+ ControlFlow::Break(()) => break Ok(()),
ControlFlow::Continue(()) => {}
}
},
Some(msg) = chan_rx.recv() => {
- process_gs_msg(&mut socket, &who, msg).await
+ process_gs_msg(&mut socket, &who, msg).await?
},
- else => {
- tracing::warn!("{who}: Connection lost unexpectedly.");
- break;
- }
+ else => break Err(anyhow!("{who}: Connection lost unexpectedly."))
}
}
}
@@ -57,19 +67,20 @@ async fn process_gs_msg(
socket: &mut WebSocket,
who: &SocketAddr,
msg: GSMsg
-) {
+) -> Result<()> {
match msg {
GSMsg::NewLine(line) => {
- socket.send(Message::Text(line_to_json(&line))).await.unwrap();
+ socket.send(Message::Text(line_to_json(&line)?)).await?;
},
GSMsg::Clear => {
- let msg = serde_json::to_string(&JMsg::Clear).unwrap();
- socket.send(Message::Text(msg)).await.unwrap();
+ let msg = serde_json::to_string(&JMsg::Clear)?;
+ socket.send(Message::Text(msg)).await?;
},
msg => {
tracing::info!("{who} should not get this: {:?}", msg);
}
- }
+ }
+ Ok(())
}
async fn process_ws_msg(
@@ -77,75 +88,75 @@ async fn process_ws_msg(
who: &SocketAddr,
line: &mut Line,
msg: Message
-) -> ControlFlow<(),()> {
+) -> Result> {
match msg {
- Text(text) => match serde_json::from_str(&text) {
- Ok(json) => {
- tracing::debug!("{who}: '{json:?}'");
- match handle_ws_msg(line, json) {
- Ok(Some(req)) => gs_tx.send(req).await.unwrap(),
- Ok(None) => {},
- Err(err) => {
- tracing::warn!("{who}: message error: {err}");
+ Message::Text(text) => {
+ tracing::debug!("{who}: sent: {text}");
+ match serde_json::from_str(&text) {
+ Ok(json) => {
+ tracing::debug!("{who}: got json: {json:?}");
+ match handle_ws_msg(line, json) {
+ Ok(Some(req)) => gs_tx.send(req).await?,
+ Ok(None) => {},
+ Err(err) => {
+ tracing::warn!("{who}: message error: {err}");
+ }
}
- }
- },
- Err(err) => {
- tracing::warn!("{who}: can't parse JSON: {err}");
+ },
+ Err(err) => tracing::warn!("{who}: can't parse JSON: {err} in: {text}")
+
}
},
- Close(close) => {
+ Message::Close(close) => {
tracing::info!("{who}: closing: {close:?}");
- gs_tx.send(GSMsg::DeleteClient(*who)).await.unwrap();
- return ControlFlow::Break(());
+ gs_tx.send(GSMsg::DeleteClient(*who)).await?;
+ return Ok(ControlFlow::Break(()));
},
_ => {
tracing::warn!("{who}: can't handle message: {msg:?}");
}
};
- ControlFlow::Continue(())
+ Ok(ControlFlow::Continue(()))
}
fn handle_ws_msg(
line: &mut Line,
msg: JMsg
-) -> Result