main
_ 2025-02-23 19:43:08 -06:00
parent 425503d66d
commit a2b286b01d
2 changed files with 18 additions and 21 deletions

View File

@ -11,7 +11,7 @@ pub use std::{
rc::Rc, rc::Rc,
str::FromStr, str::FromStr,
task::{Context, Poll}, task::{Context, Poll},
time::{Duration, Instant}, time::Duration,
}; };
pub use tokio::{ pub use tokio::{
net::{TcpListener, TcpStream}, net::{TcpListener, TcpStream},

View File

@ -1,5 +1,7 @@
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,
} }
@ -11,9 +13,9 @@ impl Default for Args {
} }
pub(crate) struct App { pub(crate) struct App {
clients: Vec<Client>, clients: BTreeMap<Id, Client>,
listener: TcpListener, listener: TcpListener,
next_client_id: u64, next_client_id: Id,
} }
impl App { impl App {
@ -31,7 +33,9 @@ impl App {
let previous_client_count = self.clients.len(); let previous_client_count = self.clients.len();
let mut new_messages = vec![]; let mut new_messages = vec![];
for client in &mut self.clients { let mut clients_to_delete = vec![];
for (id, client) in &mut self.clients {
let id = *id;
{ {
let mut stream = pin!(&mut client.stream); let mut stream = pin!(&mut client.stream);
match <_ as futures_sink::Sink<Bytes>>::poll_flush(stream.as_mut(), cx) { match <_ as futures_sink::Sink<Bytes>>::poll_flush(stream.as_mut(), cx) {
@ -71,9 +75,9 @@ impl App {
Poll::Ready(Err(err)) => { Poll::Ready(Err(err)) => {
tracing::error!(?err, "client.poll_next error"); tracing::error!(?err, "client.poll_next error");
} }
Poll::Ready(Ok(None)) => client.closed = true, Poll::Ready(Ok(None)) => clients_to_delete.push(id),
Poll::Ready(Ok(Some(ToServer::ChatLine { line, sequence }))) => { Poll::Ready(Ok(Some(ToServer::ChatLine { line, sequence }))) => {
tracing::debug!(id = client.id, ?line); tracing::debug!(id = id, ?line);
if sequence != client.sequence { if sequence != client.sequence {
tracing::error!( tracing::error!(
expected = client.sequence, expected = client.sequence,
@ -82,24 +86,19 @@ impl App {
); );
return Poll::Ready(Err(anyhow!("Sequence mismatch"))); return Poll::Ready(Err(anyhow!("Sequence mismatch")));
} }
tracing::info!(?sequence, id = client.id); tracing::info!(?sequence, id = id);
client.sequence += 1; client.sequence += 1;
new_messages.push(Rc::new(ToClient::ChatLine { new_messages.push(Rc::new(ToClient::ChatLine { id, line }));
id: client.id,
line,
}));
} }
} }
} }
self.clients.retain(|client| { for id in clients_to_delete {
if client.closed { tracing::info!(?id, "Closing client");
tracing::info!(id = client.id, "Closing client"); self.clients.remove(&id);
} }
!client.closed
});
for client in &mut self.clients { for client in &mut self.clients.values_mut() {
for msg in &new_messages { for msg in &new_messages {
client.outbox.push_back(Rc::clone(msg)); client.outbox.push_back(Rc::clone(msg));
} }
@ -112,7 +111,6 @@ impl App {
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 client = Client { let client = Client {
closed: false,
id: self.next_client_id, id: self.next_client_id,
outbox: Default::default(), outbox: Default::default(),
sequence: 0, sequence: 0,
@ -120,7 +118,7 @@ impl App {
}; };
self.next_client_id += 1; self.next_client_id += 1;
tracing::info!(id = client.id, "Accepted client"); tracing::info!(id = client.id, "Accepted client");
self.clients.push(client); self.clients.insert(client.id, client);
} }
} }
@ -133,7 +131,6 @@ impl App {
} }
struct Client { struct Client {
closed: bool,
id: u64, id: u64,
outbox: VecDeque<Rc<ToClient>>, outbox: VecDeque<Rc<ToClient>>,
sequence: u64, sequence: u64,