From 4daa21e8bf2f04646d244df32e50396f37d9e2fe Mon Sep 17 00:00:00 2001 From: htom Date: Wed, 12 Nov 2025 11:28:14 +0100 Subject: [PATCH] Started to rewrite the project to handle connection storing and message types, added v4 for uuid crate --- server/Cargo.toml | 1 + server/src/handle_connection.rs | 33 +++++++++++++++++++++++ server/src/main.rs | 46 +++++++++++++++------------------ 3 files changed, 55 insertions(+), 25 deletions(-) create mode 100644 server/src/handle_connection.rs diff --git a/server/Cargo.toml b/server/Cargo.toml index d37bf87..2b92661 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -11,3 +11,4 @@ serde = { version = "1", features = ["derive"] } serde_json = "1" futures-util = "0.3.31" url = "2.5.7" +uuid = {version = "1.18.1", features = ["v4"] } diff --git a/server/src/handle_connection.rs b/server/src/handle_connection.rs new file mode 100644 index 0000000..1c2a110 --- /dev/null +++ b/server/src/handle_connection.rs @@ -0,0 +1,33 @@ +use futures_util::{SinkExt, StreamExt}; +use tokio_tungstenite::{accept_async, tungstenite::Message as WsMessage}; +use uuid::Uuid; + +use crate::ConnectionMap; + +async fn handle_connection(stream: tokio::net::TcpStream, connections: ConnectionMap) { + let ws_stream = accept_async(stream).await.unwrap(); + let (write, mut read) = ws_stream.split(); + + let id = Uuid::new_v4(); + + { + let mut map = connections.lock().await; + map.insert(id, write); + } + + println!("New connection: {id}"); + + while let Some(Ok(msg)) = read.next().await { + if msg.is_text() { + println!("Recieved from {id}: {}", msg); + broadcast_message(&connections, &msg).await; + } + } + + { + let mut map = connections.lock().await; + map.remove(&id); + } + + println!("Connection removed: {id}"); +} diff --git a/server/src/main.rs b/server/src/main.rs index 2ce3e48..7f3b6ad 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -1,44 +1,40 @@ use futures_util::{SinkExt, StreamExt}; use serde::{Deserialize, Serialize}; +use std::collections::HashMap; +use std::sync::Arc; use tokio::net::TcpListener; -use tokio_tungstenite::{accept_async, connect_async}; -use url::Url; +use tokio::sync::Mutex; +use tokio_tungstenite::accept_async; +use uuid::Uuid; + +mod handle_connection; #[derive(Serialize, Deserialize, Debug)] -struct Message { +struct MessageData { username: String, + userid: u32, text: String, } +type Tx = futures_util::stream::SplitSink< + tokio_tungstenite::WebSocketStream, + tokio_tungstenite::tungstenite::Message, +>; + +type ConnectionMap = Arc>>; + #[tokio::main] async fn main() { - let address = "0.0.0.0:9001"; //accept connection from anywhere + let address = "0.0.0.0:9001"; //address to connect to let listener = TcpListener::bind(address).await.unwrap(); println!("Server running on ws://{}", address); + let connections: ConnectionMap = Arc::new(Mutex::new(HashMap::new())); + while let Ok((stream, _)) = listener.accept().await { - println!("New connection!"); - + let connections = connections.clone(); tokio::spawn(async move { - let ws_stream = accept_async(stream).await.unwrap(); - let (mut write, mut read) = ws_stream.split(); //seperate the read and write channel - - while let Some(Ok(msg)) = read.next().await { - if msg.is_text() { - let txt = msg.to_text().unwrap(); - if let Ok(json) = serde_json::from_str::(txt) { - println!("Recieved: {:?}", json); - - //for testing the write channel, we send back the - //same data the client sent - let reply = serde_json::to_string(&json).unwrap(); - write - .send(tokio_tungstenite::tungstenite::Message::Text(reply)) - .await - .unwrap(); - } - } - } + handle_connection(stream, connections).await; }); } }