diff --git a/Cargo.toml b/Cargo.toml index 8b2a424..f999c21 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "async-chat" version = "0.1.0" -edition = "2024" +edition = "2021" authors = ["Christian yemele "] [dependencies] @@ -9,4 +9,5 @@ async-std = { version = "1.7", features = ["unstable"] } tokio = { version = "1.0", features = ["sync"] } serde = { version = "1.0", features = ["derive", "rc"] } serde_json = "1.0" -anyhow = "1.0.97" +anyhow = "1.0" + diff --git a/src/bin/server/connection.rs b/src/bin/server/connection.rs index b3b11ed..3935b22 100644 --- a/src/bin/server/connection.rs +++ b/src/bin/server/connection.rs @@ -4,15 +4,25 @@ use async_chat::{FromClient, FromServer}; use async_std::io::BufReader; use async_std::net::TcpStream; use async_std::prelude::*; + +use async_std::sync::{Arc, Mutex}; +use anyhow::{bail, Result}; + +/// Wraps a TCP connection to a client, allowing safe async writes. +pub struct Outbound(Mutex); + + use async_std::sync::Arc; use async_std::sync::Mutex; pub struct Outbound(Mutex); + impl Outbound { - pub fn new(to_client: TcpStream) -> Outbound { - Outbound(Mutex::new(to_client)) + pub fn new(to_client: TcpStream) -> Self { + Self(Mutex::new(to_client)) } - pub async fn send(&self, packet: FromServer) -> anyhow::Result<()> { + + pub async fn send(&self, packet: FromServer) -> Result<()> { let mut guard = self.0.lock().await; utils::send_as_json(&mut *guard, &packet).await?; guard.flush().await?; @@ -20,37 +30,36 @@ impl Outbound { } } -pub async fn serve(socket: TcpStream, groups: Arc) -> anyhow::Result<()> { - // wrapping our connection in outbound so as to have exclusive access to it in the groups and avoid interference +/// Handles a new client connection, listens for messages, and interacts with group logic. +pub async fn serve(socket: TcpStream, groups: Arc) -> Result<()> { let outbound = Arc::new(Outbound::new(socket.clone())); let buffered = BufReader::new(socket); - // receive data from clients let mut from_client = utils::receive_as_json(buffered); + while let Some(request_result) = from_client.next().await { let request = request_result?; - let result = match request { + + let result: Result<()> = match request { FromClient::Join { group_name } => { let group = groups.get_or_create(group_name); group.join(outbound.clone()); Ok(()) } - FromClient::Post { - group_name, - message, - } => match groups.get(&group_name) { + FromClient::Post { group_name, message } => match groups.get(&group_name) { Some(group) => { group.post(message); Ok(()) } - None => Err(format!("Group '{}' does not exist", group_name)), + None => bail!("Group '{}' does not exist", group_name), }, }; - // not a valid request + if let Err(message) = result { - let report = FromServer::Error(message); - // send error back to client + let report = FromServer::Error(message.to_string()); outbound.send(report).await?; } } + + println!("Client disconnected."); Ok(()) }