add display names which currently do nothing
parent
c4de3ad00d
commit
54560e118f
|
@ -1,6 +1,7 @@
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
pub(crate) struct Args {
|
pub(crate) struct Args {
|
||||||
|
pub(crate) name: String,
|
||||||
pub(crate) period_ms: u32,
|
pub(crate) period_ms: u32,
|
||||||
pub(crate) port: u16,
|
pub(crate) port: u16,
|
||||||
}
|
}
|
||||||
|
@ -8,6 +9,7 @@ pub(crate) struct Args {
|
||||||
impl Default for Args {
|
impl Default for Args {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
name: "anon".to_string(),
|
||||||
period_ms: 1_000,
|
period_ms: 1_000,
|
||||||
port: 9000,
|
port: 9000,
|
||||||
}
|
}
|
||||||
|
@ -27,7 +29,7 @@ impl App {
|
||||||
let mut timer = tokio::time::interval(Duration::from_millis(args.period_ms.into()));
|
let mut timer = tokio::time::interval(Duration::from_millis(args.period_ms.into()));
|
||||||
timer.set_missed_tick_behavior(MissedTickBehavior::Skip);
|
timer.set_missed_tick_behavior(MissedTickBehavior::Skip);
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
client: Default::default(),
|
client: Client::new(args.name)?,
|
||||||
stream,
|
stream,
|
||||||
timer,
|
timer,
|
||||||
})
|
})
|
||||||
|
@ -88,27 +90,49 @@ struct Client {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl 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<()> {
|
fn handle_frame(&self, frame: Bytes) -> Result<()> {
|
||||||
match rmp_serde::from_slice(&frame)? {
|
let ToClient { id, name, event } = rmp_serde::from_slice(&frame)?;
|
||||||
ToClient::ChatLine { id, line } => tracing::info!(?id, ?line),
|
match event {
|
||||||
ToClient::ClientConnected { id } => tracing::info!(?id, "Connected"),
|
ToClientEvent::ChatLine { line } => tracing::info!(?name, ?line),
|
||||||
ToClient::ClientDisconnected { id } => tracing::info!(?id, "Disconnected"),
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_timeout(&mut self) -> Result<()> {
|
fn handle_set_name(&mut self, name: String) -> Result<()> {
|
||||||
if !self.outbox.is_empty() {
|
self.enqueue(&ToServer::SetName { name })
|
||||||
bail!("Dropped message, outbox is full");
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
fn handle_timeout(&mut self) -> Result<()> {
|
||||||
let msg = ToServer::ChatLine {
|
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(),
|
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,
|
sequence: self.sequence,
|
||||||
};
|
};
|
||||||
let frame = rmp_serde::to_vec(&msg)?;
|
|
||||||
self.outbox.push_back(frame.into());
|
|
||||||
self.sequence += 1;
|
self.sequence += 1;
|
||||||
|
self.enqueue(&msg)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,9 @@ impl Args {
|
||||||
loop {
|
loop {
|
||||||
match args.next().as_deref() {
|
match args.next().as_deref() {
|
||||||
None => break,
|
None => break,
|
||||||
|
Some("--name") => {
|
||||||
|
client_args.name = args.next().context("Missing arg")?.to_string()
|
||||||
|
}
|
||||||
Some("--period-ms") => {
|
Some("--period-ms") => {
|
||||||
client_args.period_ms =
|
client_args.period_ms =
|
||||||
u32::from_str(&args.next().context("Missing arg")?)?
|
u32::from_str(&args.next().context("Missing arg")?)?
|
||||||
|
|
|
@ -2,13 +2,22 @@ use crate::prelude::*;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize)]
|
#[derive(Deserialize, Serialize)]
|
||||||
pub(crate) enum ToClient {
|
pub(crate) struct ToClient {
|
||||||
ChatLine { id: Id, line: String },
|
pub(crate) id: Id,
|
||||||
ClientConnected { id: Id },
|
pub(crate) name: String,
|
||||||
ClientDisconnected { id: Id },
|
pub(crate) event: ToClientEvent,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize)]
|
||||||
|
pub(crate) enum ToClientEvent {
|
||||||
|
ChatLine { line: String },
|
||||||
|
Connected,
|
||||||
|
Disconnected,
|
||||||
|
NameChanged { old_name: String },
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize)]
|
#[derive(Deserialize, Serialize)]
|
||||||
pub(crate) enum ToServer {
|
pub(crate) enum ToServer {
|
||||||
ChatLine { line: String, sequence: u64 },
|
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 anyhow::{Context as _, Result, bail};
|
||||||
pub use bytes::Bytes;
|
pub use bytes::Bytes;
|
||||||
pub use futures_core::stream::Stream;
|
pub use futures_core::stream::Stream;
|
||||||
|
|
|
@ -104,23 +104,30 @@ impl Server {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_client_disconnected(&mut self, id: Id) -> Result<()> {
|
fn handle_client_disconnected(&mut self, id: Id) -> Result<()> {
|
||||||
self.clients.remove(&id);
|
let client = self
|
||||||
self.broadcast(&ToClient::ClientDisconnected { id })?;
|
.clients
|
||||||
|
.remove(&id)
|
||||||
|
.context("Can't remove client who isn't there")?;
|
||||||
|
self.broadcast(&ToClient {
|
||||||
|
id,
|
||||||
|
name: client.name,
|
||||||
|
event: ToClientEvent::Disconnected,
|
||||||
|
})?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_client_frame(&mut self, id: Id, frame: Bytes) -> Result<()> {
|
fn handle_client_frame(&mut self, id: Id, frame: Bytes) -> Result<()> {
|
||||||
let msg = {
|
let (name, event) = {
|
||||||
let client = self
|
let client = self
|
||||||
.clients
|
.clients
|
||||||
.get_mut(&id)
|
.get_mut(&id)
|
||||||
.context("Logic error: Stream has no associated client")?;
|
.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(());
|
return Ok(());
|
||||||
};
|
};
|
||||||
msg
|
(client.name.clone(), event)
|
||||||
};
|
};
|
||||||
self.broadcast(&msg)?;
|
self.broadcast(&ToClient { id, name, event })?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,6 +136,7 @@ impl Server {
|
||||||
self.next_client_id += 1;
|
self.next_client_id += 1;
|
||||||
let client = Client {
|
let client = Client {
|
||||||
id,
|
id,
|
||||||
|
name: "anon".to_string(),
|
||||||
outbox: Default::default(),
|
outbox: Default::default(),
|
||||||
sequence: 0,
|
sequence: 0,
|
||||||
};
|
};
|
||||||
|
@ -137,8 +145,12 @@ impl Server {
|
||||||
total = self.clients.len(),
|
total = self.clients.len(),
|
||||||
"Accepted client"
|
"Accepted client"
|
||||||
);
|
);
|
||||||
|
self.broadcast(&ToClient {
|
||||||
|
id,
|
||||||
|
name: client.name.clone(),
|
||||||
|
event: ToClientEvent::Connected,
|
||||||
|
})?;
|
||||||
self.clients.insert(id, client);
|
self.clients.insert(id, client);
|
||||||
self.broadcast(&ToClient::ClientConnected { id })?;
|
|
||||||
Ok(id)
|
Ok(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,12 +165,13 @@ impl Server {
|
||||||
|
|
||||||
struct Client {
|
struct Client {
|
||||||
id: u64,
|
id: u64,
|
||||||
|
name: String,
|
||||||
outbox: VecDeque<Bytes>,
|
outbox: VecDeque<Bytes>,
|
||||||
sequence: u64,
|
sequence: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Client {
|
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)? {
|
match rmp_serde::from_slice(&frame)? {
|
||||||
ToServer::ChatLine { line, sequence } => {
|
ToServer::ChatLine { line, sequence } => {
|
||||||
if sequence != self.sequence {
|
if sequence != self.sequence {
|
||||||
|
@ -170,7 +183,11 @@ impl Client {
|
||||||
bail!("Sequence mismatch");
|
bail!("Sequence mismatch");
|
||||||
}
|
}
|
||||||
self.sequence += 1;
|
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