add connect and disconnect messages

main
_ 2025-02-23 21:36:43 -06:00
parent e3c23a0931
commit c4de3ad00d
4 changed files with 27 additions and 15 deletions

View File

@ -90,9 +90,9 @@ struct Client {
impl Client { impl Client {
fn handle_frame(&self, frame: Bytes) -> Result<()> { fn handle_frame(&self, frame: Bytes) -> Result<()> {
match rmp_serde::from_slice(&frame)? { match rmp_serde::from_slice(&frame)? {
ToClient::ChatLine { id, line } => { ToClient::ChatLine { id, line } => tracing::info!(?id, ?line),
tracing::info!(?id, ?line); ToClient::ClientConnected { id } => tracing::info!(?id, "Connected"),
} ToClient::ClientDisconnected { id } => tracing::info!(?id, "Disconnected"),
} }
Ok(()) Ok(())
} }

View File

@ -1,8 +1,11 @@
use crate::prelude::*;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[derive(Deserialize, Serialize)] #[derive(Deserialize, Serialize)]
pub(crate) enum ToClient { pub(crate) enum ToClient {
ChatLine { id: u64, line: String }, ChatLine { id: Id, line: String },
ClientConnected { id: Id },
ClientDisconnected { id: Id },
} }
#[derive(Deserialize, Serialize)] #[derive(Deserialize, Serialize)]

View File

@ -19,3 +19,5 @@ pub use tokio::{
}; };
// Don't use BytesCodec, it is _nonsense_ // Don't use BytesCodec, it is _nonsense_
pub use tokio_util::codec::{Framed, LengthDelimitedCodec}; pub use tokio_util::codec::{Framed, LengthDelimitedCodec};
pub type Id = u64;

View File

@ -1,7 +1,5 @@
use crate::prelude::*; use crate::prelude::*;
type Id = u64;
pub(crate) struct Args { pub(crate) struct Args {
pub(crate) port: u16, pub(crate) port: u16,
} }
@ -59,7 +57,7 @@ impl App {
} }
} }
// Try to read into the client's inbox // Try to read data in
match stream.as_mut().poll_next(cx) { match stream.as_mut().poll_next(cx) {
Poll::Pending => {} Poll::Pending => {}
Poll::Ready(None) => clients_to_remove.push(*id), Poll::Ready(None) => clients_to_remove.push(*id),
@ -73,16 +71,17 @@ impl App {
// Close out disconnected clients // Close out disconnected clients
for id in clients_to_remove { for id in clients_to_remove {
cx.waker().wake_by_ref();
tracing::info!(?id, "Closing client"); tracing::info!(?id, "Closing client");
self.client_streams.remove(&id); self.client_streams.remove(&id);
self.server.handle_client_disconnected(id); self.server.handle_client_disconnected(id)?;
} }
if let Poll::Ready(result) = self.listener.poll_accept(cx) { if let Poll::Ready(result) = self.listener.poll_accept(cx) {
let (stream, _addr) = result.context("listener.poll_accept")?; let (stream, _addr) = result.context("listener.poll_accept")?;
cx.waker().wake_by_ref(); cx.waker().wake_by_ref();
let stream = Framed::new(stream, LengthDelimitedCodec::new()); let stream = Framed::new(stream, LengthDelimitedCodec::new());
let id = self.server.handle_new_client(); let id = self.server.handle_new_client()?;
self.client_streams.insert(id, stream); self.client_streams.insert(id, stream);
} }
@ -97,8 +96,17 @@ struct Server {
} }
impl Server { impl Server {
fn handle_client_disconnected(&mut self, id: Id) { fn broadcast(&mut self, msg: &ToClient) -> Result<()> {
for client in &mut self.clients.values_mut() {
client.handle_outgoing(msg)?;
}
Ok(())
}
fn handle_client_disconnected(&mut self, id: Id) -> Result<()> {
self.clients.remove(&id); self.clients.remove(&id);
self.broadcast(&ToClient::ClientDisconnected { id })?;
Ok(())
} }
fn handle_client_frame(&mut self, id: Id, frame: Bytes) -> Result<()> { fn handle_client_frame(&mut self, id: Id, frame: Bytes) -> Result<()> {
@ -112,13 +120,11 @@ impl Server {
}; };
msg msg
}; };
for client in &mut self.clients.values_mut() { self.broadcast(&msg)?;
client.handle_outgoing(&msg)?;
}
Ok(()) Ok(())
} }
fn handle_new_client(&mut self) -> Id { fn handle_new_client(&mut self) -> Result<Id> {
let id = self.next_client_id; let id = self.next_client_id;
self.next_client_id += 1; self.next_client_id += 1;
let client = Client { let client = Client {
@ -132,7 +138,8 @@ impl Server {
"Accepted client" "Accepted client"
); );
self.clients.insert(id, client); self.clients.insert(id, client);
id self.broadcast(&ToClient::ClientConnected { id })?;
Ok(id)
} }
fn poll_send(&mut self, id: Id) -> Result<Option<Bytes>> { fn poll_send(&mut self, id: Id) -> Result<Option<Bytes>> {