1use std::{
2 collections::VecDeque,
3 sync::{Arc, Mutex},
4 task::{Context, Poll, Waker},
5};
6
7use super::{Dir, Role, StreamId};
8use crate::{
9 frame::{
10 MaxStreamsFrame, StreamsBlockedFrame,
11 io::{ReceiveFrame, SendFrame},
12 },
13 net::tx::{ArcSendWakers, Signals},
14 sid::MAX_STREAMS_LIMIT,
15 varint::VarInt,
16};
17
18#[derive(Debug)]
20struct LocalStreamIds<BLOCKED> {
21 role: Role,
23 max: [u64; 2],
24 unallocated: [u64; 2],
25 wakers: [VecDeque<Waker>; 2],
27 blocked: BLOCKED,
29 tx_wakers: ArcSendWakers,
30}
31
32impl<BLOCKED> LocalStreamIds<BLOCKED>
33where
34 BLOCKED: SendFrame<StreamsBlockedFrame> + Clone + Send + 'static,
35{
36 fn new(
39 role: Role,
40 init_max_bi_streams: u64,
41 init_max_uni_streams: u64,
42 blocked: BLOCKED,
43 tx_wakers: ArcSendWakers,
44 ) -> Self {
45 debug_assert!(
46 role == Role::Client || (init_max_bi_streams == 0 && init_max_uni_streams == 0),
47 "Server cannot remember the parameters"
48 );
49 Self {
50 role,
51 max: [init_max_bi_streams, init_max_uni_streams],
52 unallocated: [0, 0],
53 wakers: [VecDeque::with_capacity(2), VecDeque::with_capacity(2)],
54 blocked,
55 tx_wakers,
56 }
57 }
58
59 fn role(&self) -> Role {
61 self.role
62 }
63
64 fn opened_streams(&self, dir: Dir) -> u64 {
66 self.unallocated[dir as usize]
67 }
68
69 fn recv_max_streams_frame(&mut self, frame: MaxStreamsFrame) {
72 let (dir, val) = match frame {
73 MaxStreamsFrame::Bi(max) => (Dir::Bi, max.into_u64()),
74 MaxStreamsFrame::Uni(max) => (Dir::Uni, max.into_u64()),
75 };
76 self.increase_limit(dir, val);
77 }
78
79 fn increase_limit(&mut self, dir: Dir, val: u64) {
80 assert!(val <= MAX_STREAMS_LIMIT);
81 let max_streams = &mut self.max[dir as usize];
82 if *max_streams < val {
84 if *max_streams < self.unallocated[dir as usize] {
86 self.tx_wakers.wake_all_by(Signals::WRITTEN);
87 }
88 for waker in self.wakers[dir as usize].drain(..) {
89 waker.wake();
90 }
91 *max_streams = val;
92 }
93 }
94
95 fn poll_alloc_sid(&mut self, cx: &mut Context<'_>, dir: Dir) -> Poll<Option<StreamId>> {
96 let idx = dir as usize;
97 let max = self.max[idx];
98 let unallocated = self.unallocated[idx];
99 if unallocated > MAX_STREAMS_LIMIT {
100 Poll::Ready(None)
101 } else if unallocated < max {
102 self.unallocated[idx] += 1;
103 Poll::Ready(Some(StreamId::new(self.role, dir, unallocated)))
104 } else {
105 self.wakers[idx].push_back(cx.waker().clone());
107 self.blocked.send_frame([StreamsBlockedFrame::with(
109 dir,
110 VarInt::from_u64(max).expect("max_streams limit must be less than VARINT_MAX"),
111 )]);
112 Poll::Pending
113 }
114 }
115
116 pub fn revise_max_streams(
117 &mut self,
118 zero_rtt_rejected: bool,
119 max_stream_bidi: u64,
120 max_stream_uni: u64,
121 ) {
122 if zero_rtt_rejected {
123 self.max = [0, 0];
124 }
125 self.increase_limit(Dir::Bi, max_stream_bidi);
126 self.increase_limit(Dir::Uni, max_stream_uni);
127 }
128}
129
130#[derive(Debug, Clone)]
141pub struct ArcLocalStreamIds<BLOCKED>(Arc<Mutex<LocalStreamIds<BLOCKED>>>);
142
143impl<BLOCKED> ArcLocalStreamIds<BLOCKED>
144where
145 BLOCKED: SendFrame<StreamsBlockedFrame> + Clone + Send + 'static,
146{
147 pub fn new(
151 role: Role,
152 max_bidi: u64,
153 max_uni: u64,
154 blocked: BLOCKED,
155 tx_wakers: ArcSendWakers,
156 ) -> Self {
157 Self(Arc::new(Mutex::new(LocalStreamIds::new(
158 role, max_bidi, max_uni, blocked, tx_wakers,
159 ))))
160 }
161
162 pub fn role(&self) -> Role {
164 self.0.lock().unwrap().role()
165 }
166
167 pub fn opened_streams(&self, dir: Dir) -> u64 {
175 self.0.lock().unwrap().opened_streams(dir)
176 }
177
178 pub fn recv_max_streams_frame(&self, frame: MaxStreamsFrame) {
186 self.0.lock().unwrap().recv_max_streams_frame(frame);
187 }
188
189 pub fn poll_alloc_sid(&self, cx: &mut Context<'_>, dir: Dir) -> Poll<Option<StreamId>> {
209 self.0.lock().unwrap().poll_alloc_sid(cx, dir)
210 }
211
212 pub fn revise_max_streams(
213 &self,
214 zero_rtt_rejected: bool,
215 max_stream_bidi: u64,
216 max_stream_uni: u64,
217 ) {
218 self.0.lock().unwrap().revise_max_streams(
219 zero_rtt_rejected,
220 max_stream_bidi,
221 max_stream_uni,
222 );
223 }
224}
225
226impl<BLOCKED> ReceiveFrame<MaxStreamsFrame> for ArcLocalStreamIds<BLOCKED>
227where
228 BLOCKED: SendFrame<StreamsBlockedFrame> + Clone + Send + 'static,
229{
230 type Output = ();
231
232 fn recv_frame(&self, frame: MaxStreamsFrame) -> Result<Self::Output, crate::error::Error> {
233 self.recv_max_streams_frame(frame);
234 Ok(())
235 }
236}
237
238#[cfg(test)]
239mod tests {
240 use derive_more::Deref;
241
242 use super::*;
243 use crate::util::ArcAsyncDeque;
244
245 #[derive(Clone, Deref, Default)]
246 struct StreamsBlockedFrameTx(ArcAsyncDeque<StreamsBlockedFrame>);
247
248 impl SendFrame<StreamsBlockedFrame> for StreamsBlockedFrameTx {
249 fn send_frame<I: IntoIterator<Item = StreamsBlockedFrame>>(&self, iter: I) {
250 (&self.0).extend(iter);
251 }
252 }
253
254 #[test]
255 fn test_stream_id_new() {
256 let sid = StreamId::new(Role::Client, Dir::Bi, 0);
257 assert_eq!(sid, StreamId(0));
258 assert_eq!(sid.role(), Role::Client);
259 assert_eq!(sid.dir(), Dir::Bi);
260 }
261
262 #[test]
263 fn test_recv_max_stream_frames() {
264 let local = ArcLocalStreamIds::new(
265 Role::Client,
266 0,
267 0,
268 StreamsBlockedFrameTx::default(),
269 ArcSendWakers::default(),
270 );
271 local.recv_max_streams_frame(MaxStreamsFrame::Bi(VarInt::from_u32(0)));
272 let waker = futures::task::noop_waker();
273 let mut cx = Context::from_waker(&waker);
274 assert_eq!(local.poll_alloc_sid(&mut cx, Dir::Bi), Poll::Pending,);
275 assert!(!local.0.lock().unwrap().wakers[0].is_empty());
276
277 local.recv_max_streams_frame(MaxStreamsFrame::Bi(VarInt::from_u32(1)));
278 let _ = local.0.lock().unwrap().wakers[0].pop_front();
279 assert_eq!(
280 local.poll_alloc_sid(&mut cx, Dir::Bi),
281 Poll::Ready(Some(StreamId(0)))
282 );
283 assert_eq!(local.poll_alloc_sid(&mut cx, Dir::Bi), Poll::Pending);
284 assert!(!local.0.lock().unwrap().wakers[0].is_empty());
285
286 local.recv_max_streams_frame(MaxStreamsFrame::Uni(VarInt::from_u32(2)));
287 assert_eq!(
288 local.poll_alloc_sid(&mut cx, Dir::Uni),
289 Poll::Ready(Some(StreamId(2)))
290 );
291 assert_eq!(
292 local.poll_alloc_sid(&mut cx, Dir::Uni),
293 Poll::Ready(Some(StreamId(6)))
294 );
295 assert_eq!(local.poll_alloc_sid(&mut cx, Dir::Uni), Poll::Pending);
296 assert!(!local.0.lock().unwrap().wakers[1].is_empty());
297 }
298}