2 #![feature(cursor_remaining)]
3 use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
4 use num_enum::{TryFromPrimitive, TryFromPrimitiveError};
14 pub const PROTO_ID: u32 = 0x4f457403;
15 pub const UDP_PKT_SIZE: usize = 512;
16 pub const NUM_CHANNELS: usize = 3;
17 pub const REL_BUFFER: usize = 0x8000;
18 pub const INIT_SEQNUM: u16 = 65500;
20 #[derive(Debug, Copy, Clone, PartialEq)]
27 #[derive(Debug, Copy, Clone, PartialEq, TryFromPrimitive)]
53 impl From<io::Error> for Error {
54 fn from(err: io::Error) -> Self {
59 impl From<TryFromPrimitiveError<PktType>> for Error {
60 fn from(err: TryFromPrimitiveError<PktType>) -> Self {
61 Self::InvalidType(err.number)
65 impl From<mpsc::SendError<PktResult>> for Error {
66 fn from(err: mpsc::SendError<PktResult>) -> Self {
71 impl fmt::Display for Error {
72 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
74 write!(f, "RUDP Error: ")?;
77 IoError(err) => write!(f, "IO Error: {}", err),
78 InvalidProtoId(id) => write!(f, "Invalid Protocol ID: {id}"),
79 InvalidPeerID => write!(f, "Invalid Peer ID"),
80 InvalidChannel(ch) => write!(f, "Invalid Channel: {ch}"),
81 InvalidType(tp) => write!(f, "Invalid Type: {tp}"),
82 LocalHangup => write!(f, "Local packet receiver hung up"),
91 struct RecvChannel<'a> {
92 packets: Vec<Option<Vec<u8>>>, // used to be called char **
97 pub type PktResult = Result<Pkt<Vec<u8>>, Error>;
98 type PktSender = mpsc::Sender<PktResult>;
102 sock: net::UdpSocket,
109 pub fn send(&self, pkt: Pkt<&[u8]>) -> io::Result<()> {
110 let mut buf = Vec::with_capacity(4 + 2 + 1 + 1 + pkt.data.len());
111 buf.write_u32::<BigEndian>(PROTO_ID)?;
112 buf.write_u16::<BigEndian>(self.remote_id)?;
113 buf.write_u8(pkt.chan as u8)?;
114 buf.write_u8(PktType::Orig as u8)?;
115 buf.write(pkt.data)?;
117 self.sock.send(&buf)?;
122 fn recv_loop(&self, tx: PktSender) {
123 let mut inbox = [0; UDP_PKT_SIZE];
125 let mut recv_chans = self.channels.map(|chan| RecvChannel {
127 packets: (0..REL_BUFFER).map(|_| Cell::new(None)),
132 if let Err(err) = self.recv_pkt(&mut inbox, &mut recv_chans, &tx) {
133 if !tx.send(Err(err)).is_ok() {
143 chans: &mut Vec<RecvChannel>,
145 ) -> Result<(), Error> {
149 // todo: reset timeout
150 let len = self.sock.recv(buffer)?;
151 let mut cursor = io::Cursor::new(&buffer[..len]);
153 let proto_id = cursor.read_u32::<BigEndian>()?;
154 if proto_id != PROTO_ID {
155 do yeet InvalidProtoId(proto_id);
158 let peer_id = cursor.read_u16::<BigEndian>()?;
160 let n_channel = cursor.read_u8()?;
161 let mut channel = self
163 .get_mut(n_channel as usize)
164 .ok_or(InvalidChannel(n_channel))?;
166 self.process_pkt(cursor, channel);
171 mut cursor: io::Cursor<&[u8]>,
172 chan: &mut RecvChannel,
173 ) -> Result<(), Error> {
174 match cursor.read_u8()?.try_into()? {
176 dbg!(cursor.remaining_slice());
182 data: cursor.remaining_slice().into(),
186 dbg!(cursor.remaining_slice());
189 let seqnum = cursor.read_u16::<BigEndian>()?;
190 chan.packets[seqnum].set(cursor.remaining_slice().into());
192 while Some(pkt) = chan.packets[chan.seqnum].take() {
193 self.process_pkt(io::Cursor::new(&pkt), chan)?;
194 chan.seqnum.overflowing_add(1);
205 inner: Arc<ConnInner>,
206 rx: mpsc::Receiver<PktResult>,
210 pub fn connect(addr: &str) -> io::Result<Self> {
211 let (tx, rx) = mpsc::channel();
213 let inner = Arc::new(ConnInner {
214 sock: net::UdpSocket::bind("0.0.0.0:0")?,
215 id: PeerID::Srv as u16,
216 remote_id: PeerID::Nil as u16,
217 chans: (0..NUM_CHANNELS).map(|_| Channel {}).collect(),
220 inner.sock.connect(addr)?;
222 let recv_inner = Arc::clone(&inner);
223 thread::spawn(move || {
224 recv_inner.recv_loop(tx);
227 Ok(Conn { inner, rx })
230 pub fn send(&self, pkt: Pkt<&[u8]>) -> io::Result<()> {
234 pub fn recv(&self) -> Result<PktResult, mpsc::RecvError> {
240 //println!("{}", x.deep_size_of());
241 let conn = Conn::connect("127.0.0.1:30000").expect("the spanish inquisition");
243 let mut mtpkt = vec![];
244 mtpkt.write_u16::<BigEndian>(2).unwrap(); // high level type
245 mtpkt.write_u8(29).unwrap(); // serialize ver
246 mtpkt.write_u16::<BigEndian>(0).unwrap(); // compression modes
247 mtpkt.write_u16::<BigEndian>(40).unwrap(); // MinProtoVer
248 mtpkt.write_u16::<BigEndian>(40).unwrap(); // MaxProtoVer
249 mtpkt.write_u16::<BigEndian>(3).unwrap(); // player name length
250 mtpkt.write(b"foo").unwrap(); // player name
259 while let Ok(result) = conn.recv() {
262 io::stdout().write(pkt.data.as_slice()).unwrap();
264 Err(err) => eprintln!("Error: {}", err),