1use futures::TryFutureExt;
2
3use crate::{
4 p2::bindings::sockets::network::ErrorCode,
5 sockets::{MaybeReady, UdpSocket as P3Socket, noop_cx},
6};
7use std::{
8 net::SocketAddr,
9 sync::{Arc, Mutex},
10};
11
12pub struct UdpSocket {
14 pub(crate) inner: Arc<Mutex<P3Socket>>,
15 pub(crate) in_progress_operation: Option<AsyncOperation>,
16}
17impl UdpSocket {
18 pub(crate) fn new(inner: P3Socket) -> Self {
19 Self {
20 inner: Arc::new(Mutex::new(inner)),
21 in_progress_operation: None,
22 }
23 }
24 pub(crate) fn get_mut(&mut self) -> Option<&mut P3Socket> {
25 Arc::get_mut(&mut self.inner)?.get_mut().ok()
26 }
27 pub(crate) fn lock(&self) -> std::sync::MutexGuard<'_, P3Socket> {
28 self.inner.lock().expect("other thread panicked")
29 }
30}
31
32#[derive(Clone, Copy, Debug, PartialEq, Eq)]
33pub(crate) enum AsyncOperation {
34 Bind,
35}
36
37pub struct IncomingDatagramStream {
38 pub(crate) inner: Arc<Mutex<P3Socket>>,
39 pub(crate) connected_addr: Option<SocketAddr>,
40 pub(crate) current_recv: Option<MaybeReady<Result<(Vec<u8>, SocketAddr), ErrorCode>>>,
41}
42impl IncomingDatagramStream {
43 pub(crate) fn new(inner: Arc<Mutex<P3Socket>>) -> Self {
44 let connected_addr = inner.lock().unwrap().remote_address().ok();
45 Self {
46 inner,
47 connected_addr,
48 current_recv: None,
49 }
50 }
51 pub(crate) fn poll_recv_ready(
52 &mut self,
53 cx: &mut std::task::Context<'_>,
54 ) -> std::task::Poll<()> {
55 if self.current_recv.is_none() {
56 let connected_addr = self.connected_addr;
57 let inner = self.inner.clone();
58 let recv = MaybeReady::poll_or_spawn(async move {
59 loop {
60 let fut = inner.lock().unwrap().recv();
61 let (data, addr) = fut.await?;
62
63 if let Some(connected_addr) = connected_addr
73 && connected_addr != addr
74 {
75 continue;
76 }
77
78 return Ok((data, addr));
79 }
80 });
81 self.current_recv = Some(recv);
82 }
83
84 self.current_recv
85 .as_mut()
86 .unwrap()
87 .poll_ready(cx)
88 .map(|_| ())
89 }
90
91 pub(crate) fn try_recv(&mut self) -> Result<(Vec<u8>, SocketAddr), ErrorCode> {
92 let noop_cx = &mut noop_cx();
93 if self.poll_recv_ready(noop_cx).is_pending() {
94 return Err(ErrorCode::WouldBlock);
95 }
96
97 self.current_recv.take().unwrap().unwrap_ready()
98 }
99}
100
101pub struct OutgoingDatagramStream {
102 pub(crate) inner: Arc<Mutex<P3Socket>>,
103 pub(crate) check_send_permit_count: usize,
105 pub(crate) prev_send: Option<MaybeReady<Result<(), ErrorCode>>>,
106}
107impl OutgoingDatagramStream {
108 pub(crate) fn new(inner: Arc<Mutex<P3Socket>>) -> Self {
109 Self {
110 inner,
111 check_send_permit_count: 0,
112 prev_send: None,
113 }
114 }
115 pub(crate) fn poll_send_ready(
116 &mut self,
117 cx: &mut std::task::Context<'_>,
118 ) -> std::task::Poll<()> {
119 match &mut self.prev_send {
120 Some(send) => send.poll_ready(cx).map(|_| ()),
121 None => std::task::Poll::Ready(()),
122 }
123 }
124
125 pub(crate) fn try_send(
126 &mut self,
127 data: Vec<u8>,
128 addr: Option<std::net::SocketAddr>,
129 ) -> Result<(), ErrorCode> {
130 if let Some(send) = &mut self.prev_send {
131 if !send.poll_ready(&mut noop_cx()).is_ready() {
132 return Err(ErrorCode::WouldBlock);
133 }
134
135 let result = self.prev_send.take().unwrap().unwrap_ready();
136 if let Err(e) = result {
137 return Err(e);
138 }
139 }
140
141 debug_assert!(self.prev_send.is_none());
142
143 let mut send = MaybeReady::poll_or_spawn(
144 self.inner
145 .lock()
146 .unwrap()
147 .send(data, addr)
148 .map_err(|e| e.into()),
149 );
150 if send.poll_ready(&mut noop_cx()).is_ready() {
151 send.unwrap_ready()
152 } else {
153 self.prev_send = Some(send);
154 Ok(())
155 }
156 }
157}