use super::*; use std::{borrow::Cow, collections::HashMap, io, sync::Arc}; use tokio::sync::{watch, Mutex, RwLock}; #[derive(Debug)] pub(crate) struct Ack { pub(crate) tx: watch::Sender, pub(crate) rx: watch::Receiver, pub(crate) data: Vec, } #[derive(Debug)] pub(crate) struct Chan { pub(crate) acks: HashMap, pub(crate) seqnum: u16, } #[derive(Debug)] pub(crate) struct RudpShare { pub(crate) id: u16, pub(crate) remote_id: RwLock, pub(crate) chans: [Mutex; NUM_CHANS], pub(crate) udp_tx: P::Sender, pub(crate) close: watch::Sender, } pub async fn new( id: u16, remote_id: u16, udp_tx: P::Sender, udp_rx: P::Receiver, ) -> io::Result<(RudpSender

, RudpReceiver

)> { let (close_tx, close_rx) = watch::channel(false); let share = Arc::new(RudpShare { id, remote_id: RwLock::new(remote_id), udp_tx, close: close_tx, chans: std::array::from_fn(|_| { Mutex::new(Chan { acks: HashMap::new(), seqnum: INIT_SEQNUM, }) }), }); Ok(( RudpSender { share: Arc::clone(&share), }, RudpReceiver::new(udp_rx, share, close_rx), )) } macro_rules! impl_share { ($T:ident) => { impl $T

{ pub async fn peer_id(&self) -> u16 { self.share.id } pub async fn is_server(&self) -> bool { self.share.id == PeerID::Srv as u16 } pub async fn close(self) { self.share.close.send(true).ok(); // FIXME: handle err? self.share .send( PktType::Ctl, Pkt { unrel: true, chan: 0, data: Cow::Borrowed(&[CtlType::Disco as u8]), }, ) .await .ok(); } } }; } impl_share!(RudpReceiver); impl_share!(RudpSender);