syndicate-rs/src/peer.rs

141 lines
5.4 KiB
Rust
Raw Normal View History

use super::V;
2019-10-20 15:01:27 +00:00
use super::ConnId;
use super::dataspace;
2019-10-16 15:54:58 +00:00
use super::packets;
2019-10-20 15:01:27 +00:00
use super::spaces;
2019-10-16 15:54:58 +00:00
use core::time::Duration;
use futures::{Sink, SinkExt, Stream};
2020-05-06 15:14:05 +00:00
use futures::FutureExt;
2019-10-16 15:54:58 +00:00
use futures::select;
2020-05-11 20:02:43 +00:00
use preserves::value;
use std::pin::Pin;
2019-10-16 15:54:58 +00:00
use std::sync::{Mutex, Arc};
2020-05-06 15:14:05 +00:00
use tokio::stream::StreamExt;
2019-10-16 15:54:58 +00:00
use tokio::sync::mpsc::{unbounded_channel, UnboundedSender, UnboundedReceiver};
2020-05-06 15:14:05 +00:00
use tokio::time::interval;
2019-10-16 15:54:58 +00:00
pub type ResultC2S = Result<packets::C2S, packets::DecodeError>;
pub struct Peer<I, O>
where I: Stream<Item = ResultC2S> + Send,
O: Sink<packets::S2C, Error = packets::EncodeError>,
{
2019-10-16 15:54:58 +00:00
id: ConnId,
2020-05-11 20:08:27 +00:00
tx: UnboundedSender<packets::S2C>,
rx: UnboundedReceiver<packets::S2C>,
i: Pin<Box<I>>,
o: Pin<Box<O>>,
2019-10-20 15:01:27 +00:00
space: Option<dataspace::DataspaceRef>,
2019-10-16 15:54:58 +00:00
}
2020-05-11 20:08:27 +00:00
fn err(s: &str, ctx: V) -> packets::S2C {
packets::S2C::Err(s.into(), ctx)
2019-10-16 15:54:58 +00:00
}
impl<I, O> Peer<I, O>
where I: Stream<Item = ResultC2S> + Send,
O: Sink<packets::S2C, Error = packets::EncodeError>,
{
pub fn new(id: ConnId, i: I, o: O) -> Self {
2019-10-16 15:54:58 +00:00
let (tx, rx) = unbounded_channel();
Peer{ id, tx, rx, i: Box::pin(i), o: Box::pin(o), space: None }
2019-10-16 15:54:58 +00:00
}
2019-10-20 15:01:27 +00:00
pub async fn run(&mut self, spaces: Arc<Mutex<spaces::Spaces>>) -> Result<(), std::io::Error> {
let firstpacket = self.i.next().await;
2020-05-11 20:08:27 +00:00
let dsname = if let Some(Ok(packets::C2S::Connect(dsname))) = firstpacket {
2019-10-16 15:54:58 +00:00
dsname
} else {
let e = format!("Expected initial Connect, got {:?}", firstpacket);
self.o.send(err(&e, value::Value::from(false).wrap())).await?;
return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, e))
2019-10-16 15:54:58 +00:00
};
2019-10-20 15:01:27 +00:00
self.space = Some(spaces.lock().unwrap().lookup(&dsname));
self.space.as_ref().unwrap().write().unwrap().register(self.id, self.tx.clone());
2019-10-16 15:54:58 +00:00
2020-05-06 15:14:05 +00:00
let mut ping_timer = interval(Duration::from_secs(60));
2019-10-16 15:54:58 +00:00
let mut running = true;
while running {
let mut to_send = Vec::new();
select! {
2020-05-11 20:08:27 +00:00
_instant = ping_timer.next().boxed().fuse() => to_send.push(packets::S2C::Ping()),
frame = self.i.next().fuse() => match frame {
2019-10-16 15:54:58 +00:00
Some(res) => match res {
Ok(p) => {
2020-05-11 21:31:00 +00:00
// println!("{:?}: input {:?}", self.id, &p);
2019-10-16 15:54:58 +00:00
match p {
2020-05-11 20:08:27 +00:00
packets::C2S::Turn(actions) => {
match self.space.as_ref().unwrap().write().unwrap()
.turn(self.id, actions)
{
Ok(()) => (),
Err((msg, ctx)) => {
to_send.push(err(&msg, ctx));
running = false;
}
}
}
2020-05-11 20:08:27 +00:00
packets::C2S::Ping() =>
to_send.push(packets::S2C::Pong()),
packets::C2S::Pong() =>
2019-10-20 15:01:27 +00:00
(),
2020-05-11 20:08:27 +00:00
packets::C2S::Connect(_) => {
to_send.push(err("Unexpected Connect", value::to_value(p).unwrap()));
2019-10-16 15:54:58 +00:00
running = false;
}
}
}
Err(packets::DecodeError::Read(value::decoder::Error::Eof)) => running = false,
Err(packets::DecodeError::Read(value::decoder::Error::Io(e))) => return Err(e),
Err(packets::DecodeError::Read(value::decoder::Error::Syntax(s))) => {
to_send.push(err(s, value::Value::from(false).wrap()));
2019-10-16 15:54:58 +00:00
running = false;
}
2019-10-17 14:41:42 +00:00
Err(packets::DecodeError::Parse(e, v)) => {
to_send.push(err(&format!("Packet deserialization error: {}", e), v));
2019-10-16 15:54:58 +00:00
running = false;
}
}
None => running = false,
},
msgopt = self.rx.recv().boxed().fuse() => {
match msgopt {
Some(msg) => to_send.push(msg),
None => {
/* weird. */
to_send.push(err("Outbound channel closed unexpectedly",
value::Value::from(false).wrap()));
2019-10-16 15:54:58 +00:00
running = false;
}
}
},
}
for v in to_send {
2020-05-11 20:08:27 +00:00
if let packets::S2C::Err(ref msg, ref ctx) = v {
println!("{:?}: connection crashed: {}; context {:?}", self.id, msg, ctx);
2019-10-16 15:54:58 +00:00
} else {
2020-05-11 21:31:00 +00:00
// println!("{:?}: output {:?}", self.id, &v);
()
2019-10-16 15:54:58 +00:00
}
self.o.send(v).await?;
2019-10-16 15:54:58 +00:00
}
2020-05-11 21:31:00 +00:00
tokio::task::yield_now().await;
2019-10-16 15:54:58 +00:00
}
Ok(())
}
}
impl<I, O> Drop for Peer<I, O>
where I: Stream<Item = ResultC2S> + Send,
O: Sink<packets::S2C, Error = packets::EncodeError>,
{
2019-10-16 15:54:58 +00:00
fn drop(&mut self) {
2019-10-20 15:01:27 +00:00
if let Some(ref s) = self.space {
s.write().unwrap().deregister(self.id);
}
2019-10-16 15:54:58 +00:00
}
}