From 54560e118f2bc5a57c3c7104294ba71f746c8fc7 Mon Sep 17 00:00:00 2001 From: _ <_@_> Date: Mon, 24 Feb 2025 04:45:39 +0000 Subject: [PATCH] add display names which currently do nothing --- src/client.rs | 46 +++++++++++++++++++++++++++++++++++----------- src/main.rs | 3 +++ src/messages.rs | 17 +++++++++++++---- src/prelude.rs | 2 +- src/server.rs | 35 ++++++++++++++++++++++++++--------- 5 files changed, 78 insertions(+), 25 deletions(-) diff --git a/src/client.rs b/src/client.rs index 6bebbcc..9d3aef9 100644 --- a/src/client.rs +++ b/src/client.rs @@ -1,6 +1,7 @@ use crate::prelude::*; pub(crate) struct Args { + pub(crate) name: String, pub(crate) period_ms: u32, pub(crate) port: u16, } @@ -8,6 +9,7 @@ pub(crate) struct Args { impl Default for Args { fn default() -> Self { Self { + name: "anon".to_string(), period_ms: 1_000, port: 9000, } @@ -27,7 +29,7 @@ impl App { let mut timer = tokio::time::interval(Duration::from_millis(args.period_ms.into())); timer.set_missed_tick_behavior(MissedTickBehavior::Skip); Ok(Self { - client: Default::default(), + client: Client::new(args.name)?, stream, timer, }) @@ -88,27 +90,49 @@ struct Client { } impl Client { + fn new(name: String) -> Result { + let mut this = Self { + outbox: Default::default(), + sequence: 0, + }; + + this.handle_set_name(name)?; + Ok(this) + } + + fn enqueue(&mut self, msg: &ToServer) -> Result<()> { + if !self.outbox.is_empty() { + bail!("Dropped message, outbox is full"); + } + let frame = rmp_serde::to_vec(&msg)?; + self.outbox.push_back(frame.into()); + Ok(()) + } + fn handle_frame(&self, frame: Bytes) -> Result<()> { - match rmp_serde::from_slice(&frame)? { - ToClient::ChatLine { id, line } => tracing::info!(?id, ?line), - ToClient::ClientConnected { id } => tracing::info!(?id, "Connected"), - ToClient::ClientDisconnected { id } => tracing::info!(?id, "Disconnected"), + let ToClient { id, name, event } = rmp_serde::from_slice(&frame)?; + match event { + ToClientEvent::ChatLine { line } => tracing::info!(?name, ?line), + ToClientEvent::Connected => tracing::info!(?id, "Connected"), + ToClientEvent::Disconnected => tracing::info!(?id, ?name, "Disconnected"), + ToClientEvent::NameChanged { old_name } => { + tracing::info!(?id, ?old_name, new_name = name, "Name changed") + } } Ok(()) } - fn handle_timeout(&mut self) -> Result<()> { - if !self.outbox.is_empty() { - bail!("Dropped message, outbox is full"); - } + fn handle_set_name(&mut self, name: String) -> Result<()> { + self.enqueue(&ToServer::SetName { name }) + } + fn handle_timeout(&mut self) -> Result<()> { let msg = ToServer::ChatLine { line: "There was a time, in the era of great chaos, when the Earth and the Moon were at war with each other. A daredevil from the Moon piloted a bizarre aircraft. It was feared, and because of its shape, called EINHANDER.".to_string(), sequence: self.sequence, }; - let frame = rmp_serde::to_vec(&msg)?; - self.outbox.push_back(frame.into()); self.sequence += 1; + self.enqueue(&msg)?; Ok(()) } diff --git a/src/main.rs b/src/main.rs index 528cbbe..2f257c6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -24,6 +24,9 @@ impl Args { loop { match args.next().as_deref() { None => break, + Some("--name") => { + client_args.name = args.next().context("Missing arg")?.to_string() + } Some("--period-ms") => { client_args.period_ms = u32::from_str(&args.next().context("Missing arg")?)? diff --git a/src/messages.rs b/src/messages.rs index 15846a3..d27e769 100644 --- a/src/messages.rs +++ b/src/messages.rs @@ -2,13 +2,22 @@ use crate::prelude::*; use serde::{Deserialize, Serialize}; #[derive(Deserialize, Serialize)] -pub(crate) enum ToClient { - ChatLine { id: Id, line: String }, - ClientConnected { id: Id }, - ClientDisconnected { id: Id }, +pub(crate) struct ToClient { + pub(crate) id: Id, + pub(crate) name: String, + pub(crate) event: ToClientEvent, +} + +#[derive(Deserialize, Serialize)] +pub(crate) enum ToClientEvent { + ChatLine { line: String }, + Connected, + Disconnected, + NameChanged { old_name: String }, } #[derive(Deserialize, Serialize)] pub(crate) enum ToServer { ChatLine { line: String, sequence: u64 }, + SetName { name: String }, } diff --git a/src/prelude.rs b/src/prelude.rs index 183fb0d..7d3653a 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -1,4 +1,4 @@ -pub(crate) use crate::messages::{ToClient, ToServer}; +pub(crate) use crate::messages::{ToClient, ToClientEvent, ToServer}; pub use anyhow::{Context as _, Result, bail}; pub use bytes::Bytes; pub use futures_core::stream::Stream; diff --git a/src/server.rs b/src/server.rs index 5a7110f..22eb14b 100644 --- a/src/server.rs +++ b/src/server.rs @@ -104,23 +104,30 @@ impl Server { } fn handle_client_disconnected(&mut self, id: Id) -> Result<()> { - self.clients.remove(&id); - self.broadcast(&ToClient::ClientDisconnected { id })?; + let client = self + .clients + .remove(&id) + .context("Can't remove client who isn't there")?; + self.broadcast(&ToClient { + id, + name: client.name, + event: ToClientEvent::Disconnected, + })?; Ok(()) } fn handle_client_frame(&mut self, id: Id, frame: Bytes) -> Result<()> { - let msg = { + let (name, event) = { let client = self .clients .get_mut(&id) .context("Logic error: Stream has no associated client")?; - let Some(msg) = client.handle_frame(frame).context("client.handle_frame")? else { + let Some(event) = client.handle_frame(frame).context("client.handle_frame")? else { return Ok(()); }; - msg + (client.name.clone(), event) }; - self.broadcast(&msg)?; + self.broadcast(&ToClient { id, name, event })?; Ok(()) } @@ -129,6 +136,7 @@ impl Server { self.next_client_id += 1; let client = Client { id, + name: "anon".to_string(), outbox: Default::default(), sequence: 0, }; @@ -137,8 +145,12 @@ impl Server { total = self.clients.len(), "Accepted client" ); + self.broadcast(&ToClient { + id, + name: client.name.clone(), + event: ToClientEvent::Connected, + })?; self.clients.insert(id, client); - self.broadcast(&ToClient::ClientConnected { id })?; Ok(id) } @@ -153,12 +165,13 @@ impl Server { struct Client { id: u64, + name: String, outbox: VecDeque, sequence: u64, } impl Client { - fn handle_frame(&mut self, frame: Bytes) -> Result> { + fn handle_frame(&mut self, frame: Bytes) -> Result> { match rmp_serde::from_slice(&frame)? { ToServer::ChatLine { line, sequence } => { if sequence != self.sequence { @@ -170,7 +183,11 @@ impl Client { bail!("Sequence mismatch"); } self.sequence += 1; - Ok(Some(ToClient::ChatLine { id: self.id, line })) + Ok(Some(ToClientEvent::ChatLine { line })) + } + ToServer::SetName { name } => { + let old_name = std::mem::replace(&mut self.name, name); + Ok(Some(ToClientEvent::NameChanged { old_name })) } } }