1use super::*;
2use crate::codec::UserError;
3use crate::frame::{PushPromiseHeaderError, Reason, DEFAULT_INITIAL_WINDOW_SIZE};
4use crate::proto;
5
6use http::{HeaderMap, Request, Response};
7
8use std::cmp::Ordering;
9use std::io;
10use std::task::{Context, Poll, Waker};
11use std::time::Instant;
12
13#[derive(Debug)]
14pub(super) struct Recv {
15 init_window_sz: WindowSize,
17
18 flow: FlowControl,
20
21 in_flight_data: WindowSize,
23
24 next_stream_id: Result<StreamId, StreamIdOverflow>,
26
27 last_processed_id: StreamId,
29
30 max_stream_id: StreamId,
38
39 pending_window_updates: store::Queue<stream::NextWindowUpdate>,
41
42 pending_accept: store::Queue<stream::NextAccept>,
44
45 pending_reset_expired: store::Queue<stream::NextResetExpire>,
47
48 reset_duration: Duration,
50
51 buffer: Buffer<Event>,
53
54 is_push_enabled: bool,
56
57 is_extended_connect_protocol_enabled: bool,
59}
60
61#[derive(Debug)]
62pub(super) enum Event {
63 Headers(peer::PollMessage),
64 Data(DataEvent),
65 Trailers(HeaderMap),
66 InformationalHeaders(peer::PollMessage),
67}
68
69#[derive(Debug)]
70pub(super) struct DataEvent {
71 pub(super) payload: Bytes,
72 pub(super) is_budgeted: bool,
73}
74
75#[derive(Debug)]
76pub(super) enum RecvHeaderBlockError {
77 Oversize,
78 State(Error),
79}
80
81#[derive(Debug)]
82pub(crate) enum Open {
83 PushPromise,
84 Headers,
85}
86
87impl Recv {
88 pub fn new(peer: peer::Dyn, config: &Config) -> Self {
89 let next_stream_id = if peer.is_server() { 1 } else { 2 };
90
91 let mut flow = FlowControl::new();
92
93 flow.inc_window(DEFAULT_INITIAL_WINDOW_SIZE)
96 .expect("invalid initial remote window size");
97 flow.assign_capacity(DEFAULT_INITIAL_WINDOW_SIZE).unwrap();
98
99 Recv {
100 init_window_sz: DEFAULT_INITIAL_WINDOW_SIZE,
101 flow,
102 in_flight_data: 0 as WindowSize,
103 next_stream_id: Ok(next_stream_id.into()),
104 pending_window_updates: store::Queue::new(),
105 last_processed_id: StreamId::ZERO,
106 max_stream_id: StreamId::MAX,
107 pending_accept: store::Queue::new(),
108 pending_reset_expired: store::Queue::new(),
109 reset_duration: config.local_reset_duration,
110 buffer: Buffer::new(),
111 is_push_enabled: config.local_push_enabled,
112 is_extended_connect_protocol_enabled: config.extended_connect_protocol_enabled,
113 }
114 }
115
116 pub fn init_window_sz(&self) -> WindowSize {
118 self.init_window_sz
119 }
120
121 pub fn last_processed_id(&self) -> StreamId {
123 self.last_processed_id
124 }
125
126 pub fn open(
130 &mut self,
131 id: StreamId,
132 mode: Open,
133 counts: &mut Counts,
134 ) -> Result<Option<StreamId>, Error> {
135 counts.peer().ensure_can_open(id, mode)?;
136
137 let next_id = self.next_stream_id()?;
138 if id < next_id {
139 proto_err!(conn: "id ({:?}) < next_id ({:?})", id, next_id);
140 return Err(Error::library_go_away(Reason::PROTOCOL_ERROR));
141 }
142
143 self.next_stream_id = id.next_id();
144
145 if !counts.can_inc_num_recv_streams() {
146 return Ok(None);
147 }
148
149 Ok(Some(id))
150 }
151
152 pub fn recv_headers(
156 &mut self,
157 frame: frame::Headers,
158 stream: &mut store::Ptr,
159 counts: &mut Counts,
160 ) -> Result<(), RecvHeaderBlockError> {
161 tracing::trace!("opening stream; init_window={}", self.init_window_sz);
162 let is_initial = stream.state.recv_open(&frame)?;
163
164 if is_initial {
168 if frame.stream_id() > self.last_processed_id {
169 self.last_processed_id = frame.stream_id();
170 }
171
172 if !stream.is_counted {
173 counts.inc_num_recv_streams(stream);
175 }
176 }
177
178 {
179 use super::stream::ContentLength;
180 use http::header;
181
182 let mut first_content_length = None;
183 for content_length in frame.fields().get_all(header::CONTENT_LENGTH) {
184 let content_length = match frame::parse_u64(content_length.as_bytes()) {
185 Ok(v) => v,
186 Err(_) => {
187 proto_err!(stream: "could not parse content-length; stream={:?}", stream.id);
188 return Err(Error::library_reset(stream.id, Reason::PROTOCOL_ERROR).into());
189 }
190 };
191
192 if let Some(first) = first_content_length {
193 if content_length != first {
194 proto_err!(stream: "conflicting content-length headers; stream={:?}", stream.id);
195 return Err(Error::library_reset(stream.id, Reason::PROTOCOL_ERROR).into());
196 }
197 } else {
198 first_content_length = Some(content_length);
199 }
200 }
201
202 if let Some(content_length) =
203 first_content_length.filter(|_| !stream.content_length.is_head())
204 {
205 stream.content_length = ContentLength::Remaining(content_length);
206 if frame.is_end_stream()
209 && content_length > 0
210 && frame
211 .pseudo()
212 .status
213 .map_or(true, |status| status != 204 && status != 304)
214 {
215 proto_err!(stream: "recv_headers with END_STREAM: content-length is not zero; stream={:?};", stream.id);
216 return Err(Error::library_reset(stream.id, Reason::PROTOCOL_ERROR).into());
217 }
218 }
219 }
220
221 if frame.is_over_size() {
222 tracing::debug!(
234 "stream error REQUEST_HEADER_FIELDS_TOO_LARGE -- \
235 recv_headers: frame is over size; stream={:?}",
236 stream.id
237 );
238 return Err(RecvHeaderBlockError::Oversize);
239 }
240
241 let stream_id = frame.stream_id();
242 let (pseudo, fields) = frame.into_parts();
243
244 if pseudo.protocol.is_some()
245 && counts.peer().is_server()
246 && !self.is_extended_connect_protocol_enabled
247 {
248 proto_err!(stream: "cannot use :protocol if extended connect protocol is disabled; stream={:?}", stream.id);
249 return Err(Error::library_reset(stream.id, Reason::PROTOCOL_ERROR).into());
250 }
251
252 if pseudo.status.is_some() && counts.peer().is_server() {
253 proto_err!(stream: "cannot use :status header for requests; stream={:?}", stream.id);
254 return Err(Error::library_reset(stream.id, Reason::PROTOCOL_ERROR).into());
255 }
256
257 if !pseudo.is_informational() {
258 let message = counts
259 .peer()
260 .convert_poll_message(pseudo, fields, stream_id)?;
261
262 stream
264 .pending_recv
265 .push_back(&mut self.buffer, Event::Headers(message));
266 stream.notify_recv();
267
268 if counts.peer().is_server() {
271 self.pending_accept.push(stream);
274 }
275 } else {
276 let message = counts
279 .peer()
280 .convert_poll_message(pseudo, fields, stream_id)?;
281
282 tracing::trace!("Received informational response: stream_id={:?}", stream_id);
283
284 stream
287 .pending_recv
288 .push_back(&mut self.buffer, Event::InformationalHeaders(message));
289 stream.notify_recv();
290 }
291
292 Ok(())
293 }
294
295 pub fn take_request(&mut self, stream: &mut store::Ptr) -> Request<()> {
302 use super::peer::PollMessage::*;
303
304 match stream.pending_recv.pop_front(&mut self.buffer) {
305 Some(Event::Headers(Server(request))) => request,
306 _ => unreachable!("server stream queue must start with Headers"),
307 }
308 }
309
310 pub fn poll_pushed(
312 &mut self,
313 cx: &Context,
314 stream: &mut store::Ptr,
315 ) -> Poll<Option<Result<(Request<()>, store::Key), proto::Error>>> {
316 use super::peer::PollMessage::*;
317
318 let mut ppp = stream.pending_push_promises.take();
319 let pushed = ppp.pop(stream.store_mut()).map(|mut pushed| {
320 match pushed.pending_recv.pop_front(&mut self.buffer) {
321 Some(Event::Headers(Server(headers))) => (headers, pushed.key()),
322 _ => panic!("Headers not set on pushed stream"),
325 }
326 });
327 stream.pending_push_promises = ppp;
328 if let Some(p) = pushed {
329 Poll::Ready(Some(Ok(p)))
330 } else {
331 let is_open = stream.state.ensure_recv_open()?;
332
333 if is_open {
334 stream.push_task = Some(cx.waker().clone());
335 Poll::Pending
336 } else {
337 Poll::Ready(None)
338 }
339 }
340 }
341
342 pub fn poll_response(
344 &mut self,
345 cx: &Context,
346 stream: &mut store::Ptr,
347 ) -> Poll<Result<Response<()>, proto::Error>> {
348 use super::peer::PollMessage::*;
349
350 loop {
352 match stream.pending_recv.pop_front(&mut self.buffer) {
353 Some(Event::Headers(Client(response))) => return Poll::Ready(Ok(response)),
354 Some(Event::InformationalHeaders(_)) => {
355 tracing::trace!("Skipping informational response in poll_response - should be consumed via poll_informational; stream_id={:?}", stream.id);
356 continue;
357 }
358 Some(_) => panic!("poll_response called after response returned"),
359 None => {
360 if !stream.state.ensure_recv_open()? {
361 proto_err!(stream: "poll_response: stream={:?} is not opened;", stream.id);
362 return Poll::Ready(Err(Error::library_reset(
363 stream.id,
364 Reason::PROTOCOL_ERROR,
365 )));
366 }
367
368 stream.recv_task = Some(cx.waker().clone());
369 return Poll::Pending;
370 }
371 }
372 }
373 }
374
375 pub fn poll_informational(
377 &mut self,
378 cx: &Context,
379 stream: &mut store::Ptr,
380 ) -> Poll<Option<Result<Response<()>, proto::Error>>> {
381 use super::peer::PollMessage::*;
382
383 if let Some(event) = stream.pending_recv.pop_front(&mut self.buffer) {
386 match event {
387 Event::Headers(Client(response)) => {
388 stream
390 .pending_recv
391 .push_front(&mut self.buffer, Event::Headers(Client(response)));
392 return Poll::Ready(None);
393 }
394 Event::InformationalHeaders(Client(response)) => {
395 return Poll::Ready(Some(Ok(response)));
397 }
398 other => {
399 stream.pending_recv.push_front(&mut self.buffer, other);
401 }
402 }
403 }
404
405 if stream.state.ensure_recv_open()? {
407 stream.recv_task = Some(cx.waker().clone());
409 Poll::Pending
410 } else {
411 Poll::Ready(None)
413 }
414 }
415
416 pub fn recv_trailers(
418 &mut self,
419 frame: frame::Headers,
420 stream: &mut store::Ptr,
421 ) -> Result<(), Error> {
422 stream.state.recv_close()?;
424
425 if stream.ensure_content_length_zero().is_err() {
426 proto_err!(stream: "recv_trailers: content-length is not zero; stream={:?};", stream.id);
427 return Err(Error::library_reset(stream.id, Reason::PROTOCOL_ERROR));
428 }
429
430 let trailers = frame.into_fields();
431
432 stream
434 .pending_recv
435 .push_back(&mut self.buffer, Event::Trailers(trailers));
436 stream.notify_recv();
437
438 Ok(())
439 }
440
441 pub fn release_connection_capacity(&mut self, capacity: WindowSize, task: &mut Option<Waker>) {
443 tracing::trace!(
444 "release_connection_capacity; size={}, connection in_flight_data={}",
445 capacity,
446 self.in_flight_data,
447 );
448
449 self.in_flight_data -= capacity;
451
452 let _res = self.flow.assign_capacity(capacity);
455 debug_assert!(_res.is_ok());
456
457 if self.flow.unclaimed_capacity().is_some() {
458 if let Some(task) = task.take() {
459 task.wake();
460 }
461 }
462 }
463
464 pub fn release_capacity(
466 &mut self,
467 capacity: WindowSize,
468 stream: &mut store::Ptr,
469 task: &mut Option<Waker>,
470 ) -> Result<(), UserError> {
471 tracing::trace!("release_capacity; size={}", capacity);
472
473 if capacity > stream.in_flight_recv_data {
474 return Err(UserError::ReleaseCapacityTooBig);
475 }
476
477 self.release_connection_capacity(capacity, task);
478
479 stream.in_flight_recv_data -= capacity;
481
482 let _res = stream.recv_flow.assign_capacity(capacity);
485 debug_assert!(_res.is_ok());
486
487 if stream.recv_flow.unclaimed_capacity().is_some() {
488 self.pending_window_updates.push(stream);
490
491 if let Some(task) = task.take() {
492 task.wake();
493 }
494 }
495
496 Ok(())
497 }
498
499 pub fn release_closed_capacity(
501 &mut self,
502 stream: &mut store::Ptr,
503 task: &mut Option<Waker>,
504 counts: &mut Counts,
505 ) {
506 debug_assert_eq!(stream.ref_count, 0);
507
508 if stream.in_flight_recv_data != 0 {
509 tracing::trace!(
510 "auto-release closed stream ({:?}) capacity: {:?}",
511 stream.id,
512 stream.in_flight_recv_data,
513 );
514
515 self.release_connection_capacity(stream.in_flight_recv_data, task);
516 stream.in_flight_recv_data = 0;
517 }
518
519 self.clear_recv_buffer(stream, task, counts);
520 }
521
522 pub fn set_target_connection_window(
535 &mut self,
536 target: WindowSize,
537 task: &mut Option<Waker>,
538 ) -> Result<(), Reason> {
539 tracing::trace!(
540 "set_target_connection_window; target={}; available={}, reserved={}",
541 target,
542 self.flow.available(),
543 self.in_flight_data,
544 );
545
546 let current = self
552 .flow
553 .available()
554 .add(self.in_flight_data)?
555 .checked_size();
556 if target > current {
557 self.flow.assign_capacity(target - current)?;
558 } else {
559 self.flow.claim_capacity(current - target)?;
560 }
561
562 if self.flow.unclaimed_capacity().is_some() {
566 if let Some(task) = task.take() {
567 task.wake();
568 }
569 }
570 Ok(())
571 }
572
573 pub(crate) fn apply_local_settings(
574 &mut self,
575 settings: &frame::Settings,
576 store: &mut Store,
577 ) -> Result<(), proto::Error> {
578 if let Some(val) = settings.is_extended_connect_protocol_enabled() {
579 self.is_extended_connect_protocol_enabled = val;
580 }
581
582 if let Some(target) = settings.initial_window_size() {
583 let old_sz = self.init_window_sz;
584 self.init_window_sz = target;
585
586 tracing::trace!("update_initial_window_size; new={}; old={}", target, old_sz,);
587
588 match target.cmp(&old_sz) {
605 Ordering::Less => {
606 let dec = old_sz - target;
608 tracing::trace!("decrementing all windows; dec={}", dec);
609
610 store.try_for_each(|mut stream| {
611 stream
612 .recv_flow
613 .dec_recv_window(dec)
614 .map_err(proto::Error::library_go_away)?;
615 Ok::<_, proto::Error>(())
616 })?;
617 }
618 Ordering::Greater => {
619 let inc = target - old_sz;
621 tracing::trace!("incrementing all windows; inc={}", inc);
622 store.try_for_each(|mut stream| {
623 stream
626 .recv_flow
627 .inc_window(inc)
628 .map_err(proto::Error::library_go_away)?;
629 stream
630 .recv_flow
631 .assign_capacity(inc)
632 .map_err(proto::Error::library_go_away)?;
633 Ok::<_, proto::Error>(())
634 })?;
635 }
636 Ordering::Equal => (),
637 }
638 }
639
640 Ok(())
641 }
642
643 pub fn is_end_stream(&self, stream: &store::Ptr) -> bool {
644 if !stream.state.is_recv_end_stream() {
645 return false;
646 }
647
648 stream.pending_recv.is_empty()
649 }
650
651 pub fn recv_data(&mut self, frame: frame::Data, stream: &mut store::Ptr) -> Result<(), Error> {
652 let sz = frame.flow_controlled_len();
654
655 assert!(sz <= MAX_WINDOW_SIZE as usize);
658
659 let sz = sz as WindowSize;
660
661 let is_ignoring_frame = stream.state.is_local_error();
662
663 if !is_ignoring_frame && !stream.state.is_recv_streaming() {
664 proto_err!(conn: "unexpected DATA frame; stream={:?}", stream.id);
670 return Err(Error::library_go_away(Reason::PROTOCOL_ERROR));
671 }
672
673 tracing::trace!(
674 "recv_data; size={}; connection={}; stream={}",
675 sz,
676 self.flow.window_size(),
677 stream.recv_flow.window_size()
678 );
679
680 if is_ignoring_frame {
681 tracing::trace!(
682 "recv_data; frame ignored on locally reset {:?} for some time",
683 stream.id,
684 );
685 return self.ignore_data(sz);
686 }
687
688 self.consume_connection_window(sz)?;
691
692 if stream.recv_flow.window_size() < sz {
693 return Err(Error::library_reset(stream.id, Reason::FLOW_CONTROL_ERROR));
702 }
703
704 if stream.dec_content_length(frame.payload().len()).is_err() {
706 proto_err!(stream:
707 "recv_data: content-length overflow; stream={:?}; len={:?}",
708 stream.id,
709 frame.payload().len(),
710 );
711 return Err(Error::library_reset(stream.id, Reason::PROTOCOL_ERROR));
712 }
713
714 if frame.is_end_stream() {
715 if stream.ensure_content_length_zero().is_err() {
716 proto_err!(stream:
717 "recv_data: content-length underflow; stream={:?}; len={:?}",
718 stream.id,
719 frame.payload().len(),
720 );
721 return Err(Error::library_reset(stream.id, Reason::PROTOCOL_ERROR));
722 }
723
724 if stream.state.recv_close().is_err() {
725 proto_err!(conn: "recv_data: failed to transition to closed state; stream={:?}", stream.id);
726 return Err(Error::library_go_away(Reason::PROTOCOL_ERROR));
727 }
728 }
729
730 if !stream.is_recv {
732 tracing::trace!(
733 "recv_data; frame ignored on stream release {:?} for some time",
734 stream.id,
735 );
736 self.release_connection_capacity(sz, &mut None);
737 return Ok(());
738 }
739
740 stream
742 .recv_flow
743 .send_data(sz)
744 .map_err(proto::Error::library_go_away)?;
745
746 stream.in_flight_recv_data += sz;
748
749 let padding = (frame.flow_controlled_len() - frame.payload().len()) as WindowSize;
752 if padding > 0 {
753 tracing::trace!(
754 "recv_data; auto-releasing padding of {:?} for {:?}",
755 padding,
756 stream.id,
757 );
758 let _res = self.release_capacity(padding, stream, &mut None);
759 debug_assert!(_res.is_ok());
761 }
762
763 if frame.payload().is_empty() && !frame.is_end_stream() {
767 return Ok(());
768 }
769
770 let is_budgeted = !frame.is_end_stream();
771 let event = Event::Data(DataEvent {
772 payload: frame.into_payload(),
773 is_budgeted,
774 });
775
776 stream.pending_recv.push_back(&mut self.buffer, event);
778 stream.notify_recv();
779
780 Ok(())
781 }
782
783 pub fn ignore_data(&mut self, sz: WindowSize) -> Result<(), Error> {
784 self.consume_connection_window(sz)?;
786
787 self.release_connection_capacity(sz, &mut None);
796 Ok(())
797 }
798
799 pub fn consume_connection_window(&mut self, sz: WindowSize) -> Result<(), Error> {
800 if self.flow.window_size() < sz {
801 tracing::debug!(
802 "connection error FLOW_CONTROL_ERROR -- window_size ({:?}) < sz ({:?});",
803 self.flow.window_size(),
804 sz,
805 );
806 return Err(Error::library_go_away(Reason::FLOW_CONTROL_ERROR));
807 }
808
809 self.flow.send_data(sz).map_err(Error::library_go_away)?;
811
812 self.in_flight_data += sz;
814 Ok(())
815 }
816
817 pub fn recv_push_promise(
818 &mut self,
819 frame: frame::PushPromise,
820 stream: &mut store::Ptr,
821 ) -> Result<(), Error> {
822 stream.state.reserve_remote()?;
823 if frame.is_over_size() {
824 tracing::debug!(
836 "stream error PROTOCOL_ERROR -- recv_push_promise: \
837 headers frame is over size; promised_id={:?};",
838 frame.promised_id(),
839 );
840 return Err(Error::library_reset(
841 frame.promised_id(),
842 Reason::PROTOCOL_ERROR,
843 ));
844 }
845
846 let promised_id = frame.promised_id();
847 let (pseudo, fields) = frame.into_parts();
848 let req = crate::server::Peer::convert_poll_message(pseudo, fields, promised_id)?;
849
850 if let Err(e) = frame::PushPromise::validate_request(&req) {
851 use PushPromiseHeaderError::*;
852 match e {
853 NotSafeAndCacheable => proto_err!(
854 stream:
855 "recv_push_promise: method {} is not safe and cacheable; promised_id={:?}",
856 req.method(),
857 promised_id,
858 ),
859 InvalidContentLength(e) => proto_err!(
860 stream:
861 "recv_push_promise; promised request has invalid content-length {:?}; promised_id={:?}",
862 e,
863 promised_id,
864 ),
865 }
866 return Err(Error::library_reset(promised_id, Reason::PROTOCOL_ERROR));
867 }
868
869 use super::peer::PollMessage::*;
870 stream
871 .pending_recv
872 .push_back(&mut self.buffer, Event::Headers(Server(req)));
873 stream.notify_recv();
874 stream.notify_push();
875 Ok(())
876 }
877
878 pub fn ensure_not_idle(&self, id: StreamId) -> Result<(), Reason> {
880 if let Ok(next) = self.next_stream_id {
881 if id >= next {
882 tracing::debug!(
883 "stream ID implicitly closed, PROTOCOL_ERROR; stream={:?}",
884 id
885 );
886 return Err(Reason::PROTOCOL_ERROR);
887 }
888 }
889 Ok(())
892 }
893
894 pub fn recv_reset(
896 &mut self,
897 frame: frame::Reset,
898 stream: &mut Stream,
899 counts: &mut Counts,
900 ) -> Result<(), Error> {
901 if stream.is_pending_accept {
910 if counts.can_inc_num_remote_reset_streams() {
911 counts.inc_num_remote_reset_streams();
912 } else {
913 tracing::warn!(
914 "recv_reset; remotely-reset pending-accept streams reached limit ({:?})",
915 counts.max_remote_reset_streams(),
916 );
917 return Err(Error::library_go_away_data(
918 Reason::ENHANCE_YOUR_CALM,
919 "too_many_resets",
920 ));
921 }
922 }
923
924 stream.state.recv_reset(frame, stream.is_pending_send);
926
927 stream.notify_send();
928 stream.notify_recv();
929 stream.notify_push();
930
931 Ok(())
932 }
933
934 pub fn handle_error(&mut self, err: &proto::Error, stream: &mut Stream) {
936 stream.state.handle_error(err);
938
939 stream.notify_send();
941 stream.notify_recv();
942 stream.notify_push();
943 }
944
945 pub fn go_away(&mut self, last_processed_id: StreamId) {
946 assert!(self.max_stream_id >= last_processed_id);
947 self.max_stream_id = last_processed_id;
948 }
949
950 pub fn recv_eof(&mut self, stream: &mut Stream) {
951 stream.state.recv_eof();
952 stream.notify_send();
953 stream.notify_recv();
954 stream.notify_push();
955 }
956
957 pub(super) fn clear_recv_buffer(
958 &mut self,
959 stream: &mut Stream,
960 task: &mut Option<Waker>,
961 counts: &mut Counts,
962 ) {
963 let mut to_release: WindowSize = 0;
964 while let Some(event) = stream.pending_recv.pop_front(&mut self.buffer) {
965 if let Event::Data(data) = &event {
966 if data.is_budgeted {
967 counts.release_data_frame(data.payload.len());
968 }
969 to_release = to_release
970 .saturating_add(data.payload.len() as WindowSize)
971 .min(stream.in_flight_recv_data);
972 }
973 }
974 if to_release > 0 {
979 stream.in_flight_recv_data -= to_release;
980 self.release_connection_capacity(to_release, task);
981 }
982 }
983
984 pub fn max_stream_id(&self) -> StreamId {
988 self.max_stream_id
989 }
990
991 pub fn next_stream_id(&self) -> Result<StreamId, Error> {
992 if let Ok(id) = self.next_stream_id {
993 Ok(id)
994 } else {
995 Err(Error::library_go_away(Reason::PROTOCOL_ERROR))
996 }
997 }
998
999 pub fn may_have_created_stream(&self, id: StreamId) -> bool {
1000 if let Ok(next_id) = self.next_stream_id {
1001 debug_assert_eq!(id.is_server_initiated(), next_id.is_server_initiated(),);
1003 id < next_id
1004 } else {
1005 true
1006 }
1007 }
1008
1009 pub(super) fn maybe_reset_next_stream_id(&mut self, id: StreamId) {
1010 if let Ok(next_id) = self.next_stream_id {
1011 debug_assert_eq!(id.is_server_initiated(), next_id.is_server_initiated());
1013 if id >= next_id {
1014 self.next_stream_id = id.next_id();
1015 }
1016 }
1017 }
1018
1019 pub fn ensure_can_reserve(&self) -> Result<(), Error> {
1021 if !self.is_push_enabled {
1022 proto_err!(conn: "recv_push_promise: push is disabled");
1023 return Err(Error::library_go_away(Reason::PROTOCOL_ERROR));
1024 }
1025
1026 Ok(())
1027 }
1028
1029 pub fn enqueue_reset_expiration(&mut self, stream: &mut store::Ptr, counts: &mut Counts) {
1031 if !stream.state.is_local_error() || stream.is_pending_reset_expiration() {
1032 return;
1033 }
1034
1035 if counts.can_inc_num_reset_streams() {
1036 counts.inc_num_reset_streams();
1037 tracing::trace!("enqueue_reset_expiration; added {:?}", stream.id);
1038 self.pending_reset_expired.push(stream);
1039 } else {
1040 tracing::trace!(
1041 "enqueue_reset_expiration; dropped {:?}, over max_concurrent_reset_streams",
1042 stream.id
1043 );
1044 }
1045 }
1046
1047 pub fn clear_expired_reset_streams(&mut self, store: &mut Store, counts: &mut Counts) {
1048 if !self.pending_reset_expired.is_empty() {
1049 let now = Instant::now();
1050 let reset_duration = self.reset_duration;
1051 while let Some(stream) = self.pending_reset_expired.pop_if(store, |stream| {
1052 let reset_at = stream.reset_at.expect("reset_at must be set if in queue");
1053 now.saturating_duration_since(reset_at) > reset_duration
1057 }) {
1058 counts.transition_after(stream, true);
1059 }
1060 }
1061 }
1062
1063 pub fn clear_queues(
1064 &mut self,
1065 clear_pending_accept: bool,
1066 store: &mut Store,
1067 counts: &mut Counts,
1068 ) {
1069 self.clear_stream_window_update_queue(store, counts);
1070 self.clear_all_reset_streams(store, counts);
1071
1072 if clear_pending_accept {
1073 self.clear_all_pending_accept(store, counts);
1074 }
1075 }
1076
1077 fn clear_stream_window_update_queue(&mut self, store: &mut Store, counts: &mut Counts) {
1078 while let Some(stream) = self.pending_window_updates.pop(store) {
1079 counts.transition(stream, |_, stream| {
1080 tracing::trace!("clear_stream_window_update_queue; stream={:?}", stream.id);
1081 })
1082 }
1083 }
1084
1085 fn clear_all_reset_streams(&mut self, store: &mut Store, counts: &mut Counts) {
1087 while let Some(stream) = self.pending_reset_expired.pop(store) {
1088 counts.transition_after(stream, true);
1089 }
1090 }
1091
1092 fn clear_all_pending_accept(&mut self, store: &mut Store, counts: &mut Counts) {
1093 while let Some(stream) = self.pending_accept.pop(store) {
1094 counts.transition_after(stream, false);
1095 }
1096 }
1097
1098 pub fn buffer_pending<T, B>(
1099 &mut self,
1100 store: &mut Store,
1101 counts: &mut Counts,
1102 dst: &mut Codec<T, Prioritized<B>>,
1103 ) -> io::Result<BufferStatus>
1104 where
1105 T: AsyncWrite + Unpin,
1106 B: Buf,
1107 {
1108 if self.send_connection_window_update(dst)? == BufferStatus::CodecFull {
1110 return Ok(BufferStatus::CodecFull);
1111 }
1112
1113 if self.send_stream_window_updates(store, counts, dst)? == BufferStatus::CodecFull {
1115 return Ok(BufferStatus::CodecFull);
1116 }
1117
1118 Ok(BufferStatus::Complete)
1119 }
1120
1121 fn send_connection_window_update<T, B>(
1123 &mut self,
1124 dst: &mut Codec<T, Prioritized<B>>,
1125 ) -> io::Result<BufferStatus>
1126 where
1127 T: AsyncWrite + Unpin,
1128 B: Buf,
1129 {
1130 if let Some(incr) = self.flow.unclaimed_capacity() {
1131 let frame = frame::WindowUpdate::new(StreamId::zero(), incr);
1132
1133 if !dst.has_send_capacity() {
1135 return Ok(BufferStatus::CodecFull);
1136 }
1137
1138 dst.buffer(frame.into())
1140 .expect("invalid WINDOW_UPDATE frame");
1141
1142 self.flow
1144 .inc_window(incr)
1145 .expect("unexpected flow control state");
1146 }
1147
1148 Ok(BufferStatus::Complete)
1149 }
1150
1151 pub fn send_stream_window_updates<T, B>(
1153 &mut self,
1154 store: &mut Store,
1155 counts: &mut Counts,
1156 dst: &mut Codec<T, Prioritized<B>>,
1157 ) -> io::Result<BufferStatus>
1158 where
1159 T: AsyncWrite + Unpin,
1160 B: Buf,
1161 {
1162 loop {
1163 if !dst.has_send_capacity() {
1165 return Ok(BufferStatus::CodecFull);
1166 }
1167
1168 let stream = match self.pending_window_updates.pop(store) {
1170 Some(stream) => stream,
1171 None => return Ok(BufferStatus::Complete),
1172 };
1173
1174 counts.transition(stream, |_, stream| {
1175 tracing::trace!("pending_window_updates -- pop; stream={:?}", stream.id);
1176 debug_assert!(!stream.is_pending_window_update);
1177
1178 if !stream.state.is_recv_streaming() {
1179 return;
1186 }
1187
1188 if let Some(incr) = stream.recv_flow.unclaimed_capacity() {
1190 let frame = frame::WindowUpdate::new(stream.id, incr);
1192
1193 dst.buffer(frame.into())
1195 .expect("invalid WINDOW_UPDATE frame");
1196
1197 stream
1199 .recv_flow
1200 .inc_window(incr)
1201 .expect("unexpected flow control state");
1202 }
1203 })
1204 }
1205 }
1206
1207 pub fn next_incoming(&mut self, store: &mut Store) -> Option<store::Key> {
1208 self.pending_accept.pop(store).map(|ptr| ptr.key())
1209 }
1210
1211 pub fn poll_data(
1212 &mut self,
1213 cx: &Context,
1214 stream: &mut Stream,
1215 ) -> Poll<Option<Result<DataEvent, proto::Error>>> {
1216 match stream.pending_recv.pop_front(&mut self.buffer) {
1217 Some(Event::Data(data)) => Poll::Ready(Some(Ok(data))),
1218 Some(event) => {
1219 stream.pending_recv.push_front(&mut self.buffer, event);
1221
1222 stream.notify_recv();
1231
1232 Poll::Ready(None)
1234 }
1235 None => self.schedule_recv(cx, stream),
1236 }
1237 }
1238
1239 pub fn poll_trailers(
1240 &mut self,
1241 cx: &Context,
1242 stream: &mut Stream,
1243 ) -> Poll<Option<Result<HeaderMap, proto::Error>>> {
1244 match stream.pending_recv.pop_front(&mut self.buffer) {
1245 Some(Event::Trailers(trailers)) => Poll::Ready(Some(Ok(trailers))),
1246 Some(event) => {
1247 stream.pending_recv.push_front(&mut self.buffer, event);
1249 stream.recv_task = Some(cx.waker().clone());
1250 Poll::Pending
1251 }
1252 None => self.schedule_recv(cx, stream),
1253 }
1254 }
1255
1256 fn schedule_recv<T>(
1257 &mut self,
1258 cx: &Context,
1259 stream: &mut Stream,
1260 ) -> Poll<Option<Result<T, proto::Error>>> {
1261 if stream.state.ensure_recv_open()? {
1262 stream.recv_task = Some(cx.waker().clone());
1264 Poll::Pending
1265 } else {
1266 Poll::Ready(None)
1268 }
1269 }
1270}
1271
1272#[cfg(test)]
1273mod tests {
1274 use super::*;
1275
1276 #[test]
1277 fn clear_recv_buffer_caps_capacity_before_overflow() {
1278 const FRAME_LEN: usize = 1 << 20;
1279 const FRAME_COUNT: usize = (u32::MAX as usize / FRAME_LEN) + 1;
1280
1281 let config = Config {
1282 initial_max_send_streams: 0,
1283 local_max_buffer_size: 0,
1284 local_next_stream_id: 2.into(),
1285 local_push_enabled: false,
1286 extended_connect_protocol_enabled: false,
1287 local_reset_duration: Duration::ZERO,
1288 local_reset_max: 0,
1289 remote_reset_max: 0,
1290 remote_init_window_sz: DEFAULT_INITIAL_WINDOW_SIZE,
1291 remote_max_initiated: None,
1292 local_max_error_reset_streams: None,
1293 data_frame_budget: DataFrameBudget::Configured(DEFAULT_DATA_FRAME_BUDGET),
1294 };
1295 let mut recv = Recv::new(peer::Dyn::Server, &config);
1296 let mut store = Store::new();
1297 let mut stream = store.insert(
1298 StreamId::from(1),
1299 Stream::new(StreamId::from(1), 0, DEFAULT_INITIAL_WINDOW_SIZE),
1300 );
1301 let data = Bytes::from(vec![0; FRAME_LEN]);
1302
1303 for _ in 0..FRAME_COUNT {
1304 stream.pending_recv.push_back(
1305 &mut recv.buffer,
1306 Event::Data(DataEvent {
1307 payload: data.clone(),
1308 is_budgeted: true,
1309 }),
1310 );
1311 }
1312 stream.in_flight_recv_data = DEFAULT_INITIAL_WINDOW_SIZE;
1313 recv.in_flight_data = DEFAULT_INITIAL_WINDOW_SIZE;
1314
1315 let mut counts = Counts::new(peer::Dyn::Server, &config);
1316 recv.clear_recv_buffer(&mut stream, &mut None, &mut counts);
1317
1318 assert!(stream.pending_recv.is_empty());
1319 assert_eq!(stream.in_flight_recv_data, 0);
1320 assert_eq!(recv.in_flight_data, 0);
1321 }
1322}
1323
1324impl Open {
1327 pub fn is_push_promise(&self) -> bool {
1328 matches!(*self, Self::PushPromise)
1329 }
1330}
1331
1332impl From<Error> for RecvHeaderBlockError {
1335 fn from(err: Error) -> Self {
1336 RecvHeaderBlockError::State(err)
1337 }
1338}