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