]> git.lizzy.rs Git - mt_rudp.git/blob - src/main.rs
241d324f845067e71bc0bbf1795a1a5189abf5df
[mt_rudp.git] / src / main.rs
1 #![feature(yeet_expr)]
2 #![feature(cursor_remaining)]
3 #![feature(hash_drain_filter)]
4 #![feature(async_fn_in_trait)]
5 mod client;
6 pub mod error;
7 mod recv_worker;
8
9 use byteorder::{BigEndian, WriteBytesExt};
10 pub use client::{connect, Sender as Client};
11 use num_enum::TryFromPrimitive;
12 use std::future::Future;
13 use std::{
14     io::{self, Write},
15     ops,
16     sync::Arc,
17 };
18 use tokio::sync::mpsc;
19
20 pub const PROTO_ID: u32 = 0x4f457403;
21 pub const UDP_PKT_SIZE: usize = 512;
22 pub const NUM_CHANS: usize = 3;
23 pub const REL_BUFFER: usize = 0x8000;
24 pub const INIT_SEQNUM: u16 = 65500;
25 pub const TIMEOUT: u64 = 30;
26
27 pub trait UdpSender: Send + Sync + 'static {
28     async fn send(&self, data: Vec<u8>) -> io::Result<()>;
29 }
30
31 pub trait UdpReceiver: Send + Sync + 'static {
32     async fn recv(&self) -> io::Result<Vec<u8>>;
33 }
34
35 #[derive(Debug, Copy, Clone)]
36 pub enum PeerID {
37     Nil = 0,
38     Srv,
39     CltMin,
40 }
41
42 #[derive(Debug, Copy, Clone, PartialEq, TryFromPrimitive)]
43 #[repr(u8)]
44 pub enum PktType {
45     Ctl = 0,
46     Orig,
47     Split,
48     Rel,
49 }
50
51 #[derive(Debug, Copy, Clone, PartialEq, TryFromPrimitive)]
52 #[repr(u8)]
53 pub enum CtlType {
54     Ack = 0,
55     SetPeerID,
56     Ping,
57     Disco,
58 }
59
60 #[derive(Debug)]
61 pub struct Pkt<T> {
62     unrel: bool,
63     chan: u8,
64     data: T,
65 }
66
67 pub type Error = error::Error;
68 pub type InPkt = Result<Pkt<Vec<u8>>, Error>;
69
70 #[derive(Debug)]
71 pub struct AckChan;
72
73 #[derive(Debug)]
74 pub struct RudpShare<S: UdpSender> {
75     pub id: u16,
76     pub remote_id: u16,
77     pub chans: Vec<AckChan>,
78     udp_tx: S,
79 }
80
81 #[derive(Debug)]
82 pub struct RudpReceiver<S: UdpSender> {
83     share: Arc<RudpShare<S>>,
84     pkt_rx: mpsc::UnboundedReceiver<InPkt>,
85 }
86
87 #[derive(Debug)]
88 pub struct RudpSender<S: UdpSender> {
89     share: Arc<RudpShare<S>>,
90 }
91
92 impl<S: UdpSender> RudpShare<S> {
93     pub async fn send(&self, tp: PktType, pkt: Pkt<&[u8]>) -> io::Result<()> {
94         let mut buf = Vec::with_capacity(4 + 2 + 1 + 1 + pkt.data.len());
95         buf.write_u32::<BigEndian>(PROTO_ID)?;
96         buf.write_u16::<BigEndian>(self.remote_id)?;
97         buf.write_u8(pkt.chan as u8)?;
98         buf.write_u8(tp as u8)?;
99         buf.write(pkt.data)?;
100
101         self.udp_tx.send(buf).await?;
102
103         Ok(())
104     }
105 }
106
107 impl<S: UdpSender> RudpSender<S> {
108     pub async fn send(&self, pkt: Pkt<&[u8]>) -> io::Result<()> {
109         self.share.send(PktType::Orig, pkt).await // TODO
110     }
111 }
112
113 impl<S: UdpSender> ops::Deref for RudpReceiver<S> {
114     type Target = mpsc::UnboundedReceiver<InPkt>;
115
116     fn deref(&self) -> &Self::Target {
117         &self.pkt_rx
118     }
119 }
120
121 pub fn new<S: UdpSender, R: UdpReceiver>(
122     id: u16,
123     remote_id: u16,
124     udp_tx: S,
125     udp_rx: R,
126 ) -> (RudpSender<S>, RudpReceiver<S>) {
127     let (pkt_tx, pkt_rx) = mpsc::unbounded_channel();
128
129     let share = Arc::new(RudpShare {
130         id,
131         remote_id,
132         udp_tx,
133         chans: (0..NUM_CHANS).map(|_| AckChan).collect(),
134     });
135     let recv_share = Arc::clone(&share);
136
137     tokio::spawn(async { recv_worker::RecvWorker::new(udp_rx, recv_share, pkt_tx).await });
138
139     (
140         RudpSender {
141             share: Arc::clone(&share),
142         },
143         RudpReceiver { share, pkt_rx },
144     )
145 }
146
147 // connect
148
149 #[tokio::main]
150 async fn main() -> io::Result<()> {
151     //println!("{}", x.deep_size_of());
152     let (tx, rx) = connect("127.0.0.1:30000").await?;
153
154     let mut mtpkt = vec![];
155     mtpkt.write_u16::<BigEndian>(2)?; // high level type
156     mtpkt.write_u8(29)?; // serialize ver
157     mtpkt.write_u16::<BigEndian>(0)?; // compression modes
158     mtpkt.write_u16::<BigEndian>(40)?; // MinProtoVer
159     mtpkt.write_u16::<BigEndian>(40)?; // MaxProtoVer
160     mtpkt.write_u16::<BigEndian>(3)?; // player name length
161     mtpkt.write(b"foo")?; // player name
162
163     tx.send(Pkt {
164         unrel: true,
165         chan: 1,
166         data: &mtpkt,
167     })
168     .await?;
169
170     while let Some(result) = rx.recv().await {
171         match result {
172             Ok(pkt) => {
173                 io::stdout().write(pkt.data.as_slice())?;
174             }
175             Err(err) => eprintln!("Error: {}", err),
176         }
177     }
178     println!("disco");
179
180     Ok(())
181 }