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