add display names which currently do nothing
parent
c4de3ad00d
commit
54560e118f
|
@ -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<Self> {
|
||||
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(())
|
||||
}
|
||||
|
||||
|
|
|
@ -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")?)?
|
||||
|
|
|
@ -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 },
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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<Bytes>,
|
||||
sequence: u64,
|
||||
}
|
||||
|
||||
impl Client {
|
||||
fn handle_frame(&mut self, frame: Bytes) -> Result<Option<ToClient>> {
|
||||
fn handle_frame(&mut self, frame: Bytes) -> Result<Option<ToClientEvent>> {
|
||||
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 }))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue