From 58f9e0a0005aab59dfd987bddb09952f3a5c195b Mon Sep 17 00:00:00 2001 From: Lizzy Fleckenstein Date: Wed, 15 Feb 2023 23:44:21 +0100 Subject: [PATCH] Add wrappers around mt_rudp --- Cargo.toml | 6 ++- src/conn.rs | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 10 +++++ src/to_clt.rs | 18 ++++++++- src/to_srv.rs | 27 ++++++++++++- 5 files changed, 162 insertions(+), 3 deletions(-) create mode 100644 src/conn.rs diff --git a/Cargo.toml b/Cargo.toml index afbc3e4..0d82292 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,20 +4,24 @@ version = "0.1.0" edition = "2021" [features] -all = ["client", "server", "random", "serde"] +all = ["client", "server", "random", "serde", "conn"] client = [] +conn = ["dep:mt_rudp", "dep:thiserror"] random = ["dep:generate-random", "dep:rand"] serde = ["dep:serde", "dep:serde_arrays", "enumset/serde"] server = [] test = ["client", "server", "random"] [dependencies] +delegate = "0.9.0" enumset = { git = "https://github.com/Lymia/enumset" } generate-random = { git = "https://github.com/minetest-rust/generate-random", features = ["enumset"], optional = true } +mt_rudp = { git = "https://github.com/minetest-rust/mt_rudp", optional = true } mt_ser = { git = "https://github.com/minetest-rust/mt_ser" } rand = { version = "0.8.5", optional = true } serde = { version = "1.0.152", features = ["derive"], optional = true } serde_arrays = { version = "0.1.0", optional = true } +thiserror = { version = "1.0.38", optional = true } [dev-dependencies] libtest-mimic = "0.6.0" diff --git a/src/conn.rs b/src/conn.rs new file mode 100644 index 0000000..3fc0e55 --- /dev/null +++ b/src/conn.rs @@ -0,0 +1,104 @@ +use super::PktInfo; +use delegate::delegate; +use mt_ser::{DefCfg, MtDeserialize, MtSerialize}; +use std::{borrow::Cow, io}; +use thiserror::Error; + +pub trait Remote { + type UdpSender: mt_rudp::UdpSender; + type PktFrom: MtDeserialize; + type PktTo: MtSerialize + PktInfo; +} + +#[cfg(feature = "client")] +pub struct RemoteSrv; + +#[cfg(feature = "client")] +impl Remote for RemoteSrv { + type UdpSender = mt_rudp::ToSrv; + type PktTo = crate::ToSrvPkt; + type PktFrom = crate::ToCltPkt; +} + +#[cfg(feature = "client")] +pub async fn connect(addr: &str) -> io::Result<(MtSender, MtReceiver)> { + let (tx, rx) = mt_rudp::connect(addr).await?; + Ok((MtSender(tx), MtReceiver(rx))) +} + +/* + +pub struct RemoteClt; +impl Remote for RemoteClt { + type Sender = mt_rudp::ToClt; + type To = crate::ToCltPkt; + type From = crate::ToSrvPkt; +} + +*/ + +pub struct MtSender(pub mt_rudp::RudpSender); +pub struct MtReceiver(pub mt_rudp::RudpReceiver); + +#[derive(Error, Debug)] +pub enum RecvError { + #[error("connection error: {0}")] + ConnError(#[from] mt_rudp::Error), + #[error("deserialize error: {0}")] + DeserializeError(#[from] mt_ser::DeserializeError), +} + +#[derive(Error, Debug)] +pub enum SendError { + #[error("connection error: {0}")] + ConnError(#[from] io::Error), + #[error("serialize error: {0}")] + SerializeError(#[from] mt_ser::SerializeError), +} + +macro_rules! impl_delegate { + ($T:ident) => { + impl $T { + delegate! { + to self.0 { + pub async fn peer_id(&self) -> u16; + pub async fn is_server(&self) -> bool; + pub async fn close(self); + } + } + } + }; +} + +impl_delegate!(MtSender); +impl_delegate!(MtReceiver); + +impl MtReceiver { + pub async fn recv(&mut self) -> Option> { + self.0.recv().await.map(|res| { + res.map_err(RecvError::from).and_then(|pkt| { + // TODO: warn on trailing data + R::PktFrom::mt_deserialize::(&mut io::Cursor::new(pkt.data)) + .map_err(RecvError::from) + }) + }) + } +} + +impl MtSender { + pub async fn send(&self, pkt: &R::PktTo) -> Result<(), SendError> { + let mut writer = Vec::new(); + pkt.mt_serialize::(&mut writer)?; + + let (chan, unrel) = pkt.pkt_info(); + self.0 + .send(mt_rudp::Pkt { + chan, + unrel, + data: Cow::Borrowed(&writer), + }) + .await?; + + Ok(()) + } +} diff --git a/src/lib.rs b/src/lib.rs index 77538cd..8e134c5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -29,8 +29,18 @@ use generate_random::GenerateRandom; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; +#[cfg(feature = "conn")] +mod conn; + +#[cfg(feature = "conn")] +pub use conn::*; + mod to_clt; mod to_srv; pub use to_clt::*; pub use to_srv::*; + +pub trait PktInfo { + fn pkt_info(&self) -> (u8, bool); +} diff --git a/src/to_clt.rs b/src/to_clt.rs index 3792018..5f99be3 100644 --- a/src/to_clt.rs +++ b/src/to_clt.rs @@ -285,7 +285,7 @@ pub enum ToCltPkt { flags: EnumSet, mask: EnumSet, } = 76, - SetHotbarParam(HotbarParam) = 77, + HotbarParam(HotbarParam) = 77, Breath { breath: u16, } = 78, @@ -345,3 +345,19 @@ pub enum ToCltPkt { } = 97, MinimapModes(MinimapModesPkt) = 98, } + +impl PktInfo for ToCltPkt { + fn pkt_info(&self) -> (u8, bool) { + use ToCltPkt::*; + + match self { + BlockData { .. } | Media { .. } => (2, true), + AddHud { .. } + | ChangeHud { .. } + | RemoveHud { .. } + | HudFlags { .. } + | HotbarParam(_) => (1, true), + _ => (0, true), + } + } +} diff --git a/src/to_srv.rs b/src/to_srv.rs index 704acdb..dc9a342 100644 --- a/src/to_srv.rs +++ b/src/to_srv.rs @@ -77,6 +77,10 @@ pub enum ToSrvPkt { #[mt(len = "u8")] blocks: Vec<[i16; 3]>, } = 37, + HaveMedia { + #[mt(len = "u8")] + tokens: Vec, + } = 41, InvAction { #[mt(len = "()")] action: String, @@ -113,7 +117,7 @@ pub enum ToSrvPkt { #[mt(len = "(DefCfg, (DefCfg, u32))")] fields: HashMap, } = 60, - ReqMedia { + RequestMedia { filenames: Vec, } = 64, CltReady { @@ -138,3 +142,24 @@ pub enum ToSrvPkt { } = 82, Disco = 0xffff, } + +impl PktInfo for ToSrvPkt { + fn pkt_info(&self) -> (u8, bool) { + use ToSrvPkt::*; + + match self { + Init { .. } => (1, false), + Init2 { .. } + | RequestMedia { .. } + | CltReady { .. } + | FirstSrp { .. } + | SrpBytesA { .. } + | SrpBytesM { .. } => (1, true), + PlayerPos { .. } => (0, false), + GotBlocks { .. } | HaveMedia { .. } | DeletedBlocks { .. } | RemovedSounds { .. } => { + (2, true) + } + _ => (0, true), + } + } +} -- 2.44.0