diff --git a/client.js b/client.js new file mode 100644 index 0000000..571abf9 --- /dev/null +++ b/client.js @@ -0,0 +1,18 @@ +setInterval(() => { + const ws = new WebSocket('ws://localhost:7080'); + + function sendMessage(message) { + ws.send(JSON.stringify({ type: 'send_message', params: message })); + } + + ws.onopen = () => { + console.log('WebSocket connection established'); + sendMessage('Hello, Server!'); + }; + + ws.onmessage = (event) => { + const message = JSON.parse(event.data); + console.log('Received:', message); + ws.close(); + }; +}, 100) \ No newline at end of file diff --git a/src/client.rs b/src/client.rs index 73a8aeb..fe8cf3f 100644 --- a/src/client.rs +++ b/src/client.rs @@ -4,7 +4,10 @@ use std::{ sync::{Arc, Mutex}, }; -use tungstenite::{Message, WebSocket, accept}; +use anyhow::Error; +use tungstenite::{Message, Utf8Bytes, WebSocket, accept}; + +use crate::types::{FromClient, ToClient, WsMessage}; #[derive(Clone)] pub struct Client(Arc>>); @@ -34,11 +37,29 @@ impl Hash for Client { } impl Client { - pub fn read(&self) -> crate::Result { - self.0.lock().unwrap().read().map_err(|e| e.into()) + pub fn read(&self) -> crate::Result>> { + match self.0.lock().unwrap().read()? { + Message::Text(t) => { + let v = t.to_string(); + match serde_json::from_str(&v) { + Ok(f) => Ok(Some(WsMessage::FromClient(f))), + Err(_) => Ok(Some(WsMessage::String(v))), + } + } + + Message::Binary(b) => Ok(Some(WsMessage::Binary(b))), + + Message::Close(_) => Ok(None), + + m => Err(Error::msg(format!("Invalid websocket format: {m}"))), + } } - pub fn send(&self, m: Message) -> crate::Result<()> { - self.0.lock().unwrap().send(m).map_err(|e| e.into()) + pub fn send(&self, m: ToClient) -> crate::Result<()> { + self.0 + .lock() + .unwrap() + .send(Message::Text(Utf8Bytes::from(serde_json::to_string(&m)?))) + .map_err(|e| e.into()) } } diff --git a/src/lib.rs b/src/lib.rs index e411d95..a75419c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,12 +11,17 @@ pub mod loader; pub mod logger; pub mod macros; pub mod plugin; +pub mod types; pub mod vfs; pub use anyhow::Result; pub use tungstenite; -use crate::{client::Client, plugin::DynPlugin}; +use crate::{ + client::Client, + plugin::DynPlugin, + types::{ToClient, data}, +}; pub use once_cell; #[derive(serde::Serialize, serde::Deserialize)] @@ -116,20 +121,29 @@ impl Server { // The main req/res loop loop { - let req = client.read()?; + match client.read()? { + Some(req) => { + println!("Request: {:?}", req); + for plugin in self.plugins.lock().unwrap().iter_mut() { + plugin.on_request(&req, self); + } - for plugin in self.plugins.lock().unwrap().iter_mut() { - plugin.on_request(&req, self); - } + for c in self.clients.lock().unwrap().iter() { + if c == &client { + self.wrap_err( + &client, + c.send(ToClient::Message(data::Message { + from: format!("Server"), + contents: format!("Hello"), + })), + )?; + } + } + } - if req.is_close() { - self.clients.lock().unwrap().remove(&client); - break; - } - - for c in self.clients.lock().unwrap().iter() { - if c != &client { - self.wrap_err(&client, c.send(req.clone()))?; + None => { + self.clients.lock().unwrap().remove(&client); + break; } } } diff --git a/src/plugin.rs b/src/plugin.rs index 3766b22..ba72677 100644 --- a/src/plugin.rs +++ b/src/plugin.rs @@ -1,15 +1,16 @@ use std::sync::Arc; -use tungstenite::Message; - -use crate::Server; +use crate::{ + Server, + types::{FromClient, WsMessage}, +}; pub type DynPlugin = Box; pub trait Plugin { fn init(&mut self, server: &Arc); #[allow(unused_variables)] - fn on_request(&mut self, msg: &Message, server: &Arc) -> bool { + fn on_request(&mut self, msg: &WsMessage, server: &Arc) -> bool { false } } diff --git a/src/types.rs b/src/types.rs new file mode 100644 index 0000000..ee0e128 --- /dev/null +++ b/src/types.rs @@ -0,0 +1,40 @@ +use serde::{Deserialize, Serialize}; +use tungstenite::Bytes; + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(tag = "type", content = "params", rename_all = "snake_case")] +pub enum FromClient { + SendMessage(String), +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(tag = "type", content = "params", rename_all = "snake_case")] +pub enum FromServer {} + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(tag = "type", content = "params", rename_all = "snake_case")] +pub enum ToClient { + Message(data::Message), +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(tag = "type", content = "params", rename_all = "snake_case")] +pub enum ToServer {} + +/// WebSocket for client messages +#[derive(Debug, Clone)] +pub enum WsMessage Deserialize<'de>> { + FromClient(T), + Binary(Bytes), + String(String), +} + +pub mod data { + use serde::{Deserialize, Serialize}; + + #[derive(Debug, Clone, Serialize, Deserialize)] + pub struct Message { + pub from: String, + pub contents: String, + } +}