]> git.lizzy.rs Git - mt_rudp.git/blob - src/common.rs
Implement clone for RudpSender
[mt_rudp.git] / src / common.rs
1 use super::*;
2 use async_trait::async_trait;
3 use delegate::delegate;
4 use num_enum::TryFromPrimitive;
5 use std::{borrow::Cow, io, sync::Arc};
6 use tokio::sync::mpsc;
7
8 pub const PROTO_ID: u32 = 0x4f457403;
9 pub const UDP_PKT_SIZE: usize = 512;
10 pub const NUM_CHANS: usize = 3;
11 pub const REL_BUFFER: usize = 0x8000;
12 pub const INIT_SEQNUM: u16 = 65500;
13 pub const TIMEOUT: u64 = 30;
14 pub const PING_TIMEOUT: u64 = 5;
15
16 #[async_trait]
17 pub trait UdpSender: Send + Sync + 'static {
18     async fn send(&self, data: &[u8]) -> io::Result<()>;
19 }
20
21 #[async_trait]
22 pub trait UdpReceiver: Send + Sync + 'static {
23     async fn recv(&self) -> io::Result<Vec<u8>>;
24 }
25
26 #[derive(Debug, Copy, Clone, PartialEq)]
27 #[repr(u16)]
28 pub enum PeerID {
29     Nil = 0,
30     Srv,
31     CltMin,
32 }
33
34 #[derive(Debug, Copy, Clone, PartialEq, TryFromPrimitive)]
35 #[repr(u8)]
36 pub enum PktType {
37     Ctl = 0,
38     Orig,
39     Split,
40     Rel,
41 }
42
43 #[derive(Debug, Copy, Clone, PartialEq, TryFromPrimitive)]
44 #[repr(u8)]
45 pub enum CtlType {
46     Ack = 0,
47     SetPeerID,
48     Ping,
49     Disco,
50 }
51
52 #[derive(Debug)]
53 pub struct Pkt<'a> {
54     pub unrel: bool,
55     pub chan: u8,
56     pub data: Cow<'a, [u8]>,
57 }
58
59 pub type InPkt = Result<Pkt<'static>, Error>;
60
61 #[derive(Debug)]
62 pub struct RudpReceiver<S: UdpSender> {
63     pub(crate) share: Arc<RudpShare<S>>,
64     pub(crate) pkt_rx: mpsc::UnboundedReceiver<InPkt>,
65 }
66
67 #[derive(Debug)]
68 pub struct RudpSender<S: UdpSender> {
69     pub(crate) share: Arc<RudpShare<S>>,
70 }
71
72 // derive(Clone) adds unwanted Clone trait bound to S parameter
73 impl<S: UdpSender> Clone for RudpSender<S> {
74     fn clone(&self) -> Self {
75         Self {
76             share: Arc::clone(&self.share),
77         }
78     }
79 }
80
81 macro_rules! impl_share {
82     ($T:ident) => {
83         impl<S: UdpSender> $T<S> {
84             pub async fn peer_id(&self) -> u16 {
85                 self.share.id
86             }
87
88             pub async fn is_server(&self) -> bool {
89                 self.share.id == PeerID::Srv as u16
90             }
91
92             pub async fn close(self) {
93                 self.share.bomb.lock().await.defuse();
94                 self.share.close_tx.send(true).ok();
95
96                 let mut tasks = self.share.tasks.lock().await;
97                 while let Some(res) = tasks.join_next().await {
98                     res.ok(); // TODO: handle error (?)
99                 }
100             }
101         }
102     };
103 }
104
105 impl_share!(RudpReceiver);
106 impl_share!(RudpSender);
107
108 impl<S: UdpSender> RudpReceiver<S> {
109     delegate! {
110         to self.pkt_rx {
111             pub async fn recv(&mut self) -> Option<InPkt>;
112         }
113     }
114 }