1use super::store::Resolve;
2use super::*;
3
4use crate::frame::Reason;
5
6use crate::codec::UserError;
7use crate::codec::UserError::*;
8
9use bytes::buf::Take;
10use std::{
11 cmp::{self, Ordering},
12 fmt, io, mem,
13 task::Waker,
14};
15
16#[derive(Debug)]
26pub(super) struct Prioritize {
27 pending_send: store::Queue<stream::NextSend>,
29
30 pending_capacity: store::Queue<stream::NextSendCapacity>,
32
33 pending_open: store::Queue<stream::NextOpen>,
47
48 flow: FlowControl,
50
51 last_opened_id: StreamId,
53
54 in_flight_data_frame: InFlightData,
56
57 max_buffer_size: usize,
59}
60
61#[derive(Debug, Eq, PartialEq)]
62enum InFlightData {
63 Nothing,
65 DataFrame(store::Key),
67 Drop,
69}
70
71pub(crate) struct Prioritized<B> {
72 inner: Take<B>,
74
75 end_of_stream: bool,
76
77 stream: store::Key,
79}
80
81impl Prioritize {
84 pub fn new(config: &Config) -> Prioritize {
85 let mut flow = FlowControl::new();
86
87 flow.inc_window(config.remote_init_window_sz)
88 .expect("invalid initial window size");
89
90 let _res = flow.assign_capacity(config.remote_init_window_sz);
92 debug_assert!(_res.is_ok());
93
94 tracing::trace!("Prioritize::new; flow={:?}", flow);
95
96 Prioritize {
97 pending_send: store::Queue::new(),
98 pending_capacity: store::Queue::new(),
99 pending_open: store::Queue::new(),
100 flow,
101 last_opened_id: StreamId::ZERO,
102 in_flight_data_frame: InFlightData::Nothing,
103 max_buffer_size: config.local_max_buffer_size,
104 }
105 }
106
107 pub(crate) fn max_buffer_size(&self) -> usize {
108 self.max_buffer_size
109 }
110
111 pub fn queue_frame<B>(
113 &mut self,
114 frame: Frame<B>,
115 buffer: &mut Buffer<Frame<B>>,
116 stream: &mut store::Ptr,
117 task: &mut Option<Waker>,
118 ) {
119 let span = tracing::trace_span!("Prioritize::queue_frame", ?stream.id);
120 let _e = span.enter();
121 stream.pending_send.push_back(buffer, frame);
123 self.schedule_send(stream, task);
124 }
125
126 pub fn schedule_send(&mut self, stream: &mut store::Ptr, task: &mut Option<Waker>) {
127 if stream.is_send_ready() {
129 tracing::trace!(?stream.id, "schedule_send");
130 self.pending_send.push(stream);
132
133 if let Some(task) = task.take() {
135 task.wake();
136 }
137 }
138 }
139
140 pub fn queue_open(&mut self, stream: &mut store::Ptr) {
141 self.pending_open.push(stream);
142 }
143
144 pub fn send_data<B>(
146 &mut self,
147 frame: frame::Data<B>,
148 buffer: &mut Buffer<Frame<B>>,
149 stream: &mut store::Ptr,
150 counts: &mut Counts,
151 task: &mut Option<Waker>,
152 ) -> Result<(), UserError>
153 where
154 B: Buf,
155 {
156 let sz = frame.payload().remaining();
157
158 if sz > MAX_WINDOW_SIZE as usize {
159 return Err(UserError::PayloadTooBig);
160 }
161
162 let sz = sz as WindowSize;
163
164 if !stream.state.is_send_streaming() {
165 if stream.state.is_closed() {
166 return Err(InactiveStreamId);
167 } else {
168 return Err(UnexpectedFrameType);
169 }
170 }
171
172 stream.buffered_send_data += sz as usize;
174
175 let span =
176 tracing::trace_span!("send_data", sz, requested = stream.requested_send_capacity);
177 let _e = span.enter();
178 tracing::trace!(buffered = stream.buffered_send_data);
179
180 if (stream.requested_send_capacity as usize) < stream.buffered_send_data {
183 stream.requested_send_capacity =
185 cmp::min(stream.buffered_send_data, WindowSize::MAX as usize) as WindowSize;
186
187 self.try_assign_capacity(stream);
190 }
191
192 if frame.is_end_stream() {
193 stream.state.send_close();
194 self.reserve_capacity(0, stream, counts);
195 }
196
197 tracing::trace!(
198 available = %stream.send_flow.available(),
199 buffered = stream.buffered_send_data,
200 );
201
202 if stream.send_flow.available() > 0 || stream.buffered_send_data == 0 {
211 self.queue_frame(frame.into(), buffer, stream, task);
214 } else {
215 stream.pending_send.push_back(buffer, frame.into());
219 }
220
221 Ok(())
222 }
223
224 pub fn reserve_capacity(
226 &mut self,
227 capacity: WindowSize,
228 stream: &mut store::Ptr,
229 counts: &mut Counts,
230 ) {
231 let span = tracing::trace_span!(
232 "reserve_capacity",
233 ?stream.id,
234 requested = capacity,
235 effective = (capacity as usize) + stream.buffered_send_data,
236 curr = stream.requested_send_capacity
237 );
238 let _e = span.enter();
239
240 let capacity = (capacity as usize) + stream.buffered_send_data;
243
244 match capacity.cmp(&(stream.requested_send_capacity as usize)) {
245 Ordering::Equal => {
246 }
248 Ordering::Less => {
249 stream.requested_send_capacity = capacity as WindowSize;
251
252 let available = stream.send_flow.available().as_size();
254
255 if available as usize > capacity {
258 let diff = available - capacity as WindowSize;
259
260 let _res = stream.send_flow.claim_capacity(diff);
262 debug_assert!(_res.is_ok());
263
264 self.assign_connection_capacity(diff, stream, counts);
265 }
266 }
267 Ordering::Greater => {
268 if stream.state.is_send_closed() {
271 return;
272 }
273
274 stream.requested_send_capacity =
276 cmp::min(capacity, WindowSize::MAX as usize) as WindowSize;
277
278 self.try_assign_capacity(stream);
282 }
283 }
284 }
285
286 pub fn recv_stream_window_update(
287 &mut self,
288 inc: WindowSize,
289 stream: &mut store::Ptr,
290 ) -> Result<(), Reason> {
291 let span = tracing::trace_span!(
292 "recv_stream_window_update",
293 ?stream.id,
294 ?stream.state,
295 inc,
296 flow = ?stream.send_flow
297 );
298 let _e = span.enter();
299
300 if stream.state.is_send_closed() && stream.buffered_send_data == 0 {
301 return Ok(());
303 }
304
305 stream.send_flow.inc_window(inc)?;
307
308 self.try_assign_capacity(stream);
311
312 Ok(())
313 }
314
315 pub fn recv_connection_window_update(
316 &mut self,
317 inc: WindowSize,
318 store: &mut Store,
319 counts: &mut Counts,
320 ) -> Result<(), Reason> {
321 self.flow.inc_window(inc)?;
323
324 self.assign_connection_capacity(inc, store, counts);
325 Ok(())
326 }
327
328 pub fn reclaim_all_capacity(&mut self, stream: &mut store::Ptr, counts: &mut Counts) {
331 let available = stream.send_flow.available().as_size();
332 if available > 0 {
333 let _res = stream.send_flow.claim_capacity(available);
335 debug_assert!(_res.is_ok());
336 self.assign_connection_capacity(available, stream, counts);
338 }
339 }
340
341 pub fn reclaim_reserved_capacity(&mut self, stream: &mut store::Ptr, counts: &mut Counts) {
344 if stream.send_flow.available().as_size() as usize > stream.buffered_send_data {
346 let reserved =
347 stream.send_flow.available().as_size() - stream.buffered_send_data as WindowSize;
348
349 stream
352 .send_flow
353 .claim_capacity(reserved)
354 .expect("window size should be greater than reserved");
355
356 self.assign_connection_capacity(reserved, stream, counts);
357 }
358 }
359
360 pub fn clear_pending_capacity(&mut self, store: &mut Store, counts: &mut Counts) {
361 let span = tracing::trace_span!("clear_pending_capacity");
362 let _e = span.enter();
363 while let Some(stream) = self.pending_capacity.pop(store) {
364 counts.transition(stream, |_, stream| {
365 tracing::trace!(?stream.id, "clear_pending_capacity");
366 })
367 }
368 }
369
370 pub fn assign_connection_capacity<R>(
371 &mut self,
372 inc: WindowSize,
373 store: &mut R,
374 counts: &mut Counts,
375 ) where
376 R: Resolve,
377 {
378 let span = tracing::trace_span!("assign_connection_capacity", inc);
379 let _e = span.enter();
380
381 let _res = self.flow.assign_capacity(inc);
383 debug_assert!(_res.is_ok());
384
385 while self.flow.available() > 0 {
387 let stream = match self.pending_capacity.pop(store) {
388 Some(stream) => stream,
389 None => return,
390 };
391
392 if !(stream.state.is_send_streaming() || stream.buffered_send_data > 0) {
397 continue;
398 }
399
400 counts.transition(stream, |_, stream| {
401 self.try_assign_capacity(stream);
405 })
406 }
407 }
408
409 fn try_assign_capacity(&mut self, stream: &mut store::Ptr) {
411 if stream.is_pending_open {
414 return;
415 }
416
417 let total_requested = stream.requested_send_capacity;
418
419 debug_assert!(stream.send_flow.available() <= total_requested as usize);
422
423 let additional = cmp::min(
426 total_requested - stream.send_flow.available().as_size(),
427 stream.send_flow.window_size() - stream.send_flow.available().as_size(),
429 );
430 let span = tracing::trace_span!("try_assign_capacity", ?stream.id);
431 let _e = span.enter();
432 tracing::trace!(
433 requested = total_requested,
434 additional,
435 buffered = stream.buffered_send_data,
436 window = stream.send_flow.window_size(),
437 conn = %self.flow.available()
438 );
439
440 if additional == 0 {
441 return;
443 }
444
445 if !stream.state.is_send_streaming() && stream.buffered_send_data == 0 {
447 return;
448 }
449
450 let conn_available = self.flow.available().as_size();
452
453 if conn_available > 0 {
455 let assign = cmp::min(conn_available, additional);
458
459 tracing::trace!(capacity = assign, "assigning");
460
461 stream.assign_capacity(assign, self.max_buffer_size);
463
464 let _res = self.flow.claim_capacity(assign);
467 debug_assert!(_res.is_ok());
468 }
469
470 tracing::trace!(
471 available = %stream.send_flow.available(),
472 requested = stream.requested_send_capacity,
473 buffered = stream.buffered_send_data,
474 has_unavailable = %stream.send_flow.has_unavailable()
475 );
476
477 if stream.send_flow.available() < stream.requested_send_capacity as usize
478 && stream.send_flow.has_unavailable()
479 {
480 self.pending_capacity.push(stream);
487 }
488
489 if stream.buffered_send_data > 0 && stream.is_send_ready() {
492 self.pending_send.push(stream);
505 }
506 }
507
508 pub fn buffer_pending<T, B>(
509 &mut self,
510 buffer: &mut Buffer<Frame<B>>,
511 store: &mut Store,
512 counts: &mut Counts,
513 dst: &mut Codec<T, Prioritized<B>>,
514 ) -> io::Result<BufferStatus>
515 where
516 T: AsyncWrite + Unpin,
517 B: Buf,
518 {
519 self.reclaim_frame(buffer, store, dst);
521
522 let max_frame_len = dst.max_send_frame_size();
524
525 tracing::trace!("buffer_pending");
526
527 loop {
528 if !dst.has_send_capacity() {
529 return Ok(BufferStatus::CodecFull);
530 }
531
532 if let Some(mut stream) = self.pop_pending_open(store, counts) {
533 self.pending_send.push_front(&mut stream);
534 self.try_assign_capacity(&mut stream);
535 }
536
537 match self.pop_frame(buffer, store, max_frame_len, counts) {
538 Some(frame) => {
539 tracing::trace!(?frame, "writing");
540
541 debug_assert_eq!(self.in_flight_data_frame, InFlightData::Nothing);
542 if let Frame::Data(ref frame) = frame {
543 self.in_flight_data_frame = InFlightData::DataFrame(frame.payload().stream);
544 }
545 dst.buffer(frame).expect("invalid frame");
546
547 self.reclaim_frame(buffer, store, dst);
552 }
553 None => {
554 return Ok(BufferStatus::Complete);
555 }
556 }
557 }
558 }
559
560 pub fn reclaim_written_frame<T, B>(
561 &mut self,
562 buffer: &mut Buffer<Frame<B>>,
563 store: &mut Store,
564 dst: &mut Codec<T, Prioritized<B>>,
565 ) -> bool
566 where
567 B: Buf,
568 {
569 self.reclaim_frame(buffer, store, dst)
570 }
571
572 fn reclaim_frame<T, B>(
580 &mut self,
581 buffer: &mut Buffer<Frame<B>>,
582 store: &mut Store,
583 dst: &mut Codec<T, Prioritized<B>>,
584 ) -> bool
585 where
586 B: Buf,
587 {
588 let span = tracing::trace_span!("try_reclaim_frame");
589 let _e = span.enter();
590
591 if let Some(frame) = dst.take_last_data_frame() {
593 self.reclaim_frame_inner(buffer, store, frame)
594 } else {
595 false
596 }
597 }
598
599 fn reclaim_frame_inner<B>(
600 &mut self,
601 buffer: &mut Buffer<Frame<B>>,
602 store: &mut Store,
603 frame: frame::Data<Prioritized<B>>,
604 ) -> bool
605 where
606 B: Buf,
607 {
608 tracing::trace!(
609 ?frame,
610 sz = frame.payload().inner.get_ref().remaining(),
611 "reclaimed"
612 );
613
614 let mut eos = false;
615 let key = frame.payload().stream;
616
617 match mem::replace(&mut self.in_flight_data_frame, InFlightData::Nothing) {
618 InFlightData::Nothing => panic!("wasn't expecting a frame to reclaim"),
619 InFlightData::Drop => {
620 tracing::trace!("not reclaiming frame for cancelled stream");
621 return false;
622 }
623 InFlightData::DataFrame(k) => {
624 debug_assert_eq!(k, key);
625 }
626 }
627
628 let mut frame = frame.map(|prioritized| {
629 eos = prioritized.end_of_stream;
631 prioritized.inner.into_inner()
632 });
633
634 if frame.payload().has_remaining() {
635 let mut stream = store.resolve(key);
636
637 if eos {
638 frame.set_end_stream(true);
639 }
640
641 self.push_back_frame(frame.into(), buffer, &mut stream);
642
643 return true;
644 }
645
646 false
647 }
648
649 fn push_back_frame<B>(
652 &mut self,
653 frame: Frame<B>,
654 buffer: &mut Buffer<Frame<B>>,
655 stream: &mut store::Ptr,
656 ) {
657 stream.pending_send.push_front(buffer, frame);
659
660 if stream.send_flow.available() > 0 {
662 debug_assert!(!stream.pending_send.is_empty());
663 self.pending_send.push(stream);
664 }
665 }
666
667 pub fn clear_queue<B>(&mut self, buffer: &mut Buffer<Frame<B>>, stream: &mut store::Ptr) {
668 let span = tracing::trace_span!("clear_queue", ?stream.id);
669 let _e = span.enter();
670
671 while let Some(frame) = stream.pending_send.pop_front(buffer) {
673 tracing::trace!(?frame, "dropping");
674 }
675
676 stream.buffered_send_data = 0;
677 stream.requested_send_capacity = 0;
678 if let InFlightData::DataFrame(key) = self.in_flight_data_frame {
679 if stream.key() == key {
680 self.in_flight_data_frame = InFlightData::Drop;
682 }
683 }
684 }
685
686 pub fn clear_pending_send(&mut self, store: &mut Store, counts: &mut Counts) {
687 while let Some(mut stream) = self.pending_send.pop(store) {
688 let is_pending_reset = stream.is_pending_reset_expiration();
689 if let Some(reason) = stream.state.get_scheduled_reset() {
690 stream.set_reset(reason, Initiator::Library);
691 }
692 counts.transition_after(stream, is_pending_reset);
693 }
694 }
695
696 pub fn clear_pending_open(&mut self, store: &mut Store, counts: &mut Counts) {
697 while let Some(stream) = self.pending_open.pop(store) {
698 let is_pending_reset = stream.is_pending_reset_expiration();
699 counts.transition_after(stream, is_pending_reset);
700 }
701 }
702
703 fn pop_frame<B>(
704 &mut self,
705 buffer: &mut Buffer<Frame<B>>,
706 store: &mut Store,
707 max_len: usize,
708 counts: &mut Counts,
709 ) -> Option<Frame<Prioritized<B>>>
710 where
711 B: Buf,
712 {
713 let span = tracing::trace_span!("pop_frame");
714 let _e = span.enter();
715
716 loop {
717 let mut stream = self.pending_send.pop(store)?;
718 let span = tracing::trace_span!("popped", ?stream.id, ?stream.state);
719 let _e = span.enter();
720
721 let is_pending_reset = stream.is_pending_reset_expiration();
727
728 tracing::trace!(is_pending_reset);
729
730 let frame = match stream.pending_send.pop_front(buffer) {
731 Some(Frame::Data(mut frame)) => {
732 if let Some(reason) = stream.state.get_scheduled_reset() {
733 if reason != Reason::NO_ERROR {
741 stream.pending_send.push_front(buffer, frame.into());
742 self.clear_queue(buffer, &mut stream);
743 self.reclaim_all_capacity(&mut stream, counts);
744 self.pending_send.push(&mut stream);
745 continue;
746 }
747 }
748
749 let stream_capacity = stream.send_flow.available();
752 let sz = frame.payload().remaining();
753
754 tracing::trace!(
755 sz,
756 eos = frame.is_end_stream(),
757 window = %stream_capacity,
758 available = %stream.send_flow.available(),
759 requested = stream.requested_send_capacity,
760 buffered = stream.buffered_send_data,
761 "data frame"
762 );
763
764 if sz > 0 && stream_capacity == 0 {
767 tracing::trace!("stream capacity is 0");
768
769 stream.pending_send.push_front(buffer, frame.into());
780
781 continue;
782 }
783
784 let len = cmp::min(sz, max_len);
786
787 let len = cmp::min(len, stream_capacity.as_size() as usize) as WindowSize;
789
790 debug_assert!(len <= self.flow.window_size());
793
794 if len > 0 && len > stream.send_flow.window_size() {
798 stream.pending_send.push_front(buffer, frame.into());
799 continue;
800 }
801
802 tracing::trace!(len, "sending data frame");
803
804 tracing::trace_span!("updating stream flow").in_scope(|| {
806 stream.send_data(len, self.max_buffer_size);
807
808 let _res = self.flow.assign_capacity(len);
813 debug_assert!(_res.is_ok());
814 });
815
816 let (eos, len) =
817 tracing::trace_span!("updating connection flow").in_scope(|| {
818 let _res = self.flow.send_data(len);
820 debug_assert!(_res.is_ok());
821
822 let eos = frame.is_end_stream();
826 let len = len as usize;
827
828 if frame.payload().remaining() > len {
829 frame.set_end_stream(false);
830 }
831 (eos, len)
832 });
833
834 Frame::Data(frame.map(|buf| Prioritized {
835 inner: buf.take(len),
836 end_of_stream: eos,
837 stream: stream.key(),
838 }))
839 }
840 Some(Frame::PushPromise(pp)) => {
841 let mut pushed = stream.store_mut().find_mut(&pp.promised_id()).unwrap();
842 pushed.is_pending_push = false;
843 if !pushed.pending_send.is_empty() {
846 if counts.can_inc_num_send_streams() {
847 counts.inc_num_send_streams(&mut pushed);
848 self.pending_send.push(&mut pushed);
849 } else {
850 self.queue_open(&mut pushed);
851 }
852 }
853 Frame::PushPromise(pp)
854 }
855 Some(frame) => frame.map(|_| {
856 unreachable!(
857 "Frame::map closure will only be called \
858 on DATA frames."
859 )
860 }),
861 None => {
862 if let Some(reason) = stream.state.get_scheduled_reset() {
863 stream.set_reset(reason, Initiator::Library);
864
865 let frame = frame::Reset::new(stream.id, reason);
866 Frame::Reset(frame)
867 } else {
868 tracing::trace!("removing dangling stream from pending_send");
873 debug_assert!(stream.state.is_closed());
876 counts.transition_after(stream, is_pending_reset);
877 continue;
878 }
879 }
880 };
881
882 tracing::trace!("pop_frame; frame={:?}", frame);
883
884 if cfg!(debug_assertions) && stream.state.is_idle() {
885 debug_assert!(stream.id > self.last_opened_id);
886 self.last_opened_id = stream.id;
887 }
888
889 if !stream.pending_send.is_empty() || stream.state.is_scheduled_reset() {
890 self.pending_send.push(&mut stream);
895 }
896
897 counts.transition_after(stream, is_pending_reset);
898
899 return Some(frame);
900 }
901 }
902
903 fn pop_pending_open<'s>(
904 &mut self,
905 store: &'s mut Store,
906 counts: &mut Counts,
907 ) -> Option<store::Ptr<'s>> {
908 tracing::trace!("schedule_pending_open");
909 if counts.can_inc_num_send_streams() {
911 if let Some(mut stream) = self.pending_open.pop(store) {
912 tracing::trace!("schedule_pending_open; stream={:?}", stream.id);
913
914 counts.inc_num_send_streams(&mut stream);
915 stream.notify_send();
916 return Some(stream);
917 }
918 }
919
920 None
921 }
922}
923
924impl<B> Buf for Prioritized<B>
927where
928 B: Buf,
929{
930 fn remaining(&self) -> usize {
931 self.inner.remaining()
932 }
933
934 fn chunk(&self) -> &[u8] {
935 self.inner.chunk()
936 }
937
938 fn chunks_vectored<'a>(&'a self, dst: &mut [std::io::IoSlice<'a>]) -> usize {
939 self.inner.chunks_vectored(dst)
940 }
941
942 fn advance(&mut self, cnt: usize) {
943 self.inner.advance(cnt)
944 }
945}
946
947impl<B: Buf> fmt::Debug for Prioritized<B> {
948 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
949 fmt.debug_struct("Prioritized")
950 .field("remaining", &self.inner.get_ref().remaining())
951 .field("end_of_stream", &self.end_of_stream)
952 .field("stream", &self.stream)
953 .finish()
954 }
955}