refactor
parent
2606946240
commit
e3c23a0931
|
@ -1,5 +1,5 @@
|
|||
pub(crate) use crate::messages::{ToClient, ToServer};
|
||||
pub use anyhow::{Context as _, Result, anyhow, bail};
|
||||
pub use anyhow::{Context as _, Result, bail};
|
||||
pub use bytes::Bytes;
|
||||
pub use futures_core::stream::Stream;
|
||||
pub use futures_sink::Sink;
|
||||
|
|
|
@ -48,16 +48,12 @@ impl App {
|
|||
<_ as futures_sink::Sink<Bytes>>::poll_ready(stream.as_mut(), cx)
|
||||
{
|
||||
result.context("Can't check network write half for readiness")?;
|
||||
let client = self
|
||||
.server
|
||||
.clients
|
||||
.get_mut(id)
|
||||
.context("Logic error: Stream has no associated client")?;
|
||||
if let Some(frame) = client.poll_send() {
|
||||
if let Some(frame) = self.server.poll_send(*id)? {
|
||||
stream.as_mut().start_send(frame).context("start_send")?;
|
||||
match <_ as futures_sink::Sink<Bytes>>::poll_flush(stream.as_mut(), cx) {
|
||||
Poll::Pending => {}
|
||||
Poll::Ready(result) => result.context("poll_flush")?,
|
||||
if let Poll::Ready(result) =
|
||||
<_ as futures_sink::Sink<Bytes>>::poll_flush(stream.as_mut(), cx)
|
||||
{
|
||||
result.context("poll_flush")?;
|
||||
}
|
||||
tracing::debug!("Started send");
|
||||
}
|
||||
|
@ -70,14 +66,7 @@ impl App {
|
|||
Poll::Ready(Some(result)) => {
|
||||
let frame = result.context("stream.poll_next")?;
|
||||
cx.waker().wake_by_ref();
|
||||
let client = self
|
||||
.server
|
||||
.clients
|
||||
.get_mut(id)
|
||||
.context("Logic error: Stream has no associated client")?;
|
||||
client
|
||||
.handle_frame(frame.into())
|
||||
.context("client.handle_frame")?
|
||||
self.server.handle_client_frame(*id, frame.into())?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -86,34 +75,16 @@ impl App {
|
|||
for id in clients_to_remove {
|
||||
tracing::info!(?id, "Closing client");
|
||||
self.client_streams.remove(&id);
|
||||
self.server.clients.remove(&id);
|
||||
self.server.handle_client_disconnected(id);
|
||||
}
|
||||
|
||||
// Broadcast chat lines across all clients
|
||||
|
||||
let mut new_messages = vec![];
|
||||
for client in &mut self.server.clients.values_mut() {
|
||||
if let Some(ChatLine { id, line }) = client.poll_inbox() {
|
||||
new_messages.push(ToClient::ChatLine { id, line });
|
||||
}
|
||||
}
|
||||
|
||||
for client in &mut self.server.clients.values_mut() {
|
||||
for msg in &new_messages {
|
||||
client.handle_outgoing(msg)?;
|
||||
}
|
||||
}
|
||||
|
||||
match self.listener.poll_accept(cx) {
|
||||
Poll::Pending => {}
|
||||
Poll::Ready(result) => {
|
||||
if let Poll::Ready(result) = self.listener.poll_accept(cx) {
|
||||
let (stream, _addr) = result.context("listener.poll_accept")?;
|
||||
cx.waker().wake_by_ref();
|
||||
let stream = Framed::new(stream, LengthDelimitedCodec::new());
|
||||
let id = self.server.handle_new_client();
|
||||
self.client_streams.insert(id, stream);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -126,12 +97,32 @@ struct Server {
|
|||
}
|
||||
|
||||
impl Server {
|
||||
fn handle_client_disconnected(&mut self, id: Id) {
|
||||
self.clients.remove(&id);
|
||||
}
|
||||
|
||||
fn handle_client_frame(&mut self, id: Id, frame: Bytes) -> Result<()> {
|
||||
let msg = {
|
||||
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 {
|
||||
return Ok(());
|
||||
};
|
||||
msg
|
||||
};
|
||||
for client in &mut self.clients.values_mut() {
|
||||
client.handle_outgoing(&msg)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_new_client(&mut self) -> Id {
|
||||
let id = self.next_client_id;
|
||||
self.next_client_id += 1;
|
||||
let client = Client {
|
||||
id,
|
||||
inbox: Default::default(),
|
||||
outbox: Default::default(),
|
||||
sequence: 0,
|
||||
};
|
||||
|
@ -143,22 +134,24 @@ impl Server {
|
|||
self.clients.insert(id, client);
|
||||
id
|
||||
}
|
||||
}
|
||||
|
||||
struct ChatLine {
|
||||
id: Id,
|
||||
line: String,
|
||||
fn poll_send(&mut self, id: Id) -> Result<Option<Bytes>> {
|
||||
let client = self
|
||||
.clients
|
||||
.get_mut(&id)
|
||||
.context("Logic error: Stream has no associated client")?;
|
||||
Ok(client.poll_send())
|
||||
}
|
||||
}
|
||||
|
||||
struct Client {
|
||||
id: u64,
|
||||
inbox: VecDeque<ChatLine>,
|
||||
outbox: VecDeque<Bytes>,
|
||||
sequence: u64,
|
||||
}
|
||||
|
||||
impl Client {
|
||||
fn handle_frame(&mut self, frame: Bytes) -> Result<()> {
|
||||
fn handle_frame(&mut self, frame: Bytes) -> Result<Option<ToClient>> {
|
||||
match rmp_serde::from_slice(&frame)? {
|
||||
ToServer::ChatLine { line, sequence } => {
|
||||
if sequence != self.sequence {
|
||||
|
@ -170,10 +163,9 @@ impl Client {
|
|||
bail!("Sequence mismatch");
|
||||
}
|
||||
self.sequence += 1;
|
||||
self.inbox.push_back(ChatLine { id: self.id, line });
|
||||
Ok(Some(ToClient::ChatLine { id: self.id, line }))
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_outgoing(&mut self, msg: &ToClient) -> Result<()> {
|
||||
|
@ -185,10 +177,6 @@ impl Client {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn poll_inbox(&mut self) -> Option<ChatLine> {
|
||||
self.inbox.pop_front()
|
||||
}
|
||||
|
||||
fn poll_send(&mut self) -> Option<Bytes> {
|
||||
self.outbox.pop_front()
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue