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 refused: Option<StreamId>,
56
57 is_push_enabled: bool,
59
60 is_extended_connect_protocol_enabled: bool,
62}
63
64#[derive(Debug)]
65pub(super) enum Event {
66 Headers(peer::PollMessage),
67 Data(DataEvent),
68 Trailers(HeaderMap),
69 InformationalHeaders(peer::PollMessage),
70}
71
72#[derive(Debug)]
73pub(super) struct DataEvent {
74 pub(super) payload: Bytes,
75 pub(super) is_budgeted: bool,
76}
77
78#[derive(Debug)]
79pub(super) enum RecvHeaderBlockError<T> {
80 Oversize(T),
81 State(Error),
82}
83
84#[derive(Debug)]
85pub(crate) enum Open {
86 PushPromise,
87 Headers,
88}
89
90impl Recv {
91 pub fn new(peer: peer::Dyn, config: &Config) -> Self {
92 let next_stream_id = if peer.is_server() { 1 } else { 2 };
93
94 let mut flow = FlowControl::new();
95
96 flow.inc_window(DEFAULT_INITIAL_WINDOW_SIZE)
99 .expect("invalid initial remote window size");
100 flow.assign_capacity(DEFAULT_INITIAL_WINDOW_SIZE).unwrap();
101
102 Recv {
103 init_window_sz: DEFAULT_INITIAL_WINDOW_SIZE,
104 flow,
105 in_flight_data: 0 as WindowSize,
106 next_stream_id: Ok(next_stream_id.into()),
107 pending_window_updates: store::Queue::new(),
108 last_processed_id: StreamId::ZERO,
109 max_stream_id: StreamId::MAX,
110 pending_accept: store::Queue::new(),
111 pending_reset_expired: store::Queue::new(),
112 reset_duration: config.local_reset_duration,
113 buffer: Buffer::new(),
114 refused: None,
115 is_push_enabled: config.local_push_enabled,
116 is_extended_connect_protocol_enabled: config.extended_connect_protocol_enabled,
117 }
118 }
119
120 pub fn init_window_sz(&self) -> WindowSize {
122 self.init_window_sz
123 }
124
125 pub fn last_processed_id(&self) -> StreamId {
127 self.last_processed_id
128 }
129
130 pub fn open(
134 &mut self,
135 id: StreamId,
136 mode: Open,
137 counts: &mut Counts,
138 ) -> Result<Option<StreamId>, Error> {
139 assert!(self.refused.is_none());
140
141 counts.peer().ensure_can_open(id, mode)?;
142
143 let next_id = self.next_stream_id()?;
144 if id < next_id {
145 proto_err!(conn: "id ({:?}) < next_id ({:?})", id, next_id);
146 return Err(Error::library_go_away(Reason::PROTOCOL_ERROR));
147 }
148
149 self.next_stream_id = id.next_id();
150
151 if !counts.can_inc_num_recv_streams() {
152 self.refused = Some(id);
153 return Ok(None);
154 }
155
156 Ok(Some(id))
157 }
158
159 pub fn recv_headers(
163 &mut self,
164 frame: frame::Headers,
165 stream: &mut store::Ptr,
166 counts: &mut Counts,
167 ) -> Result<(), RecvHeaderBlockError<Option<frame::Headers>>> {
168 tracing::trace!("opening stream; init_window={}", self.init_window_sz);
169 let is_initial = stream.state.recv_open(&frame)?;
170
171 if is_initial && !stream.is_counted {
175 if frame.stream_id() > self.last_processed_id {
177 self.last_processed_id = frame.stream_id();
178 }
179
180 counts.inc_num_recv_streams(stream);
182 }
183
184 if !stream.content_length.is_head() {
185 use super::stream::ContentLength;
186 use http::header;
187
188 if let Some(content_length) = frame.fields().get(header::CONTENT_LENGTH) {
189 let content_length = match frame::parse_u64(content_length.as_bytes()) {
190 Ok(v) => v,
191 Err(_) => {
192 proto_err!(stream: "could not parse content-length; stream={:?}", stream.id);
193 return Err(Error::library_reset(stream.id, Reason::PROTOCOL_ERROR).into());
194 }
195 };
196
197 stream.content_length = ContentLength::Remaining(content_length);
198 if frame.is_end_stream()
201 && content_length > 0
202 && frame
203 .pseudo()
204 .status
205 .map_or(true, |status| status != 204 && status != 304)
206 {
207 proto_err!(stream: "recv_headers with END_STREAM: content-length is not zero; stream={:?};", stream.id);
208 return Err(Error::library_reset(stream.id, Reason::PROTOCOL_ERROR).into());
209 }
210 }
211 }
212
213 if frame.is_over_size() {
214 tracing::debug!(
226 "stream error REQUEST_HEADER_FIELDS_TOO_LARGE -- \
227 recv_headers: frame is over size; stream={:?}",
228 stream.id
229 );
230 return if counts.peer().is_server() && is_initial {
231 let mut res = frame::Headers::new(
232 stream.id,
233 frame::Pseudo::response(::http::StatusCode::REQUEST_HEADER_FIELDS_TOO_LARGE),
234 HeaderMap::new(),
235 );
236 res.set_end_stream();
237 Err(RecvHeaderBlockError::Oversize(Some(res)))
238 } else {
239 Err(RecvHeaderBlockError::Oversize(None))
240 };
241 }
242
243 let stream_id = frame.stream_id();
244 let (pseudo, fields) = frame.into_parts();
245
246 if pseudo.protocol.is_some()
247 && counts.peer().is_server()
248 && !self.is_extended_connect_protocol_enabled
249 {
250 proto_err!(stream: "cannot use :protocol if extended connect protocol is disabled; stream={:?}", stream.id);
251 return Err(Error::library_reset(stream.id, Reason::PROTOCOL_ERROR).into());
252 }
253
254 if pseudo.status.is_some() && counts.peer().is_server() {
255 proto_err!(stream: "cannot use :status header for requests; stream={:?}", stream.id);
256 return Err(Error::library_reset(stream.id, Reason::PROTOCOL_ERROR).into());
257 }
258
259 if !pseudo.is_informational() {
260 let message = counts
261 .peer()
262 .convert_poll_message(pseudo, fields, stream_id)?;
263
264 stream
266 .pending_recv
267 .push_back(&mut self.buffer, Event::Headers(message));
268 stream.notify_recv();
269
270 if counts.peer().is_server() {
273 self.pending_accept.push(stream);
276 }
277 } else {
278 let message = counts
281 .peer()
282 .convert_poll_message(pseudo, fields, stream_id)?;
283
284 tracing::trace!("Received informational response: stream_id={:?}", stream_id);
285
286 stream
289 .pending_recv
290 .push_back(&mut self.buffer, Event::InformationalHeaders(message));
291 stream.notify_recv();
292 }
293
294 Ok(())
295 }
296
297 pub fn take_request(&mut self, stream: &mut store::Ptr) -> Request<()> {
304 use super::peer::PollMessage::*;
305
306 match stream.pending_recv.pop_front(&mut self.buffer) {
307 Some(Event::Headers(Server(request))) => request,
308 _ => unreachable!("server stream queue must start with Headers"),
309 }
310 }
311
312 pub fn poll_pushed(
314 &mut self,
315 cx: &Context,
316 stream: &mut store::Ptr,
317 ) -> Poll<Option<Result<(Request<()>, store::Key), proto::Error>>> {
318 use super::peer::PollMessage::*;
319
320 let mut ppp = stream.pending_push_promises.take();
321 let pushed = ppp.pop(stream.store_mut()).map(|mut pushed| {
322 match pushed.pending_recv.pop_front(&mut self.buffer) {
323 Some(Event::Headers(Server(headers))) => (headers, pushed.key()),
324 _ => panic!("Headers not set on pushed stream"),
327 }
328 });
329 stream.pending_push_promises = ppp;
330 if let Some(p) = pushed {
331 Poll::Ready(Some(Ok(p)))
332 } else {
333 let is_open = stream.state.ensure_recv_open()?;
334
335 if is_open {
336 stream.push_task = Some(cx.waker().clone());
337 Poll::Pending
338 } else {
339 Poll::Ready(None)
340 }
341 }
342 }
343
344 pub fn poll_response(
346 &mut self,
347 cx: &Context,
348 stream: &mut store::Ptr,
349 ) -> Poll<Result<Response<()>, proto::Error>> {
350 use super::peer::PollMessage::*;
351
352 loop {
354 match stream.pending_recv.pop_front(&mut self.buffer) {
355 Some(Event::Headers(Client(response))) => return Poll::Ready(Ok(response)),
356 Some(Event::InformationalHeaders(_)) => {
357 tracing::trace!("Skipping informational response in poll_response - should be consumed via poll_informational; stream_id={:?}", stream.id);
358 continue;
359 }
360 Some(_) => panic!("poll_response called after response returned"),
361 None => {
362 if !stream.state.ensure_recv_open()? {
363 proto_err!(stream: "poll_response: stream={:?} is not opened;", stream.id);
364 return Poll::Ready(Err(Error::library_reset(
365 stream.id,
366 Reason::PROTOCOL_ERROR,
367 )));
368 }
369
370 stream.recv_task = Some(cx.waker().clone());
371 return Poll::Pending;
372 }
373 }
374 }
375 }
376
377 pub fn poll_informational(
379 &mut self,
380 cx: &Context,
381 stream: &mut store::Ptr,
382 ) -> Poll<Option<Result<Response<()>, proto::Error>>> {
383 use super::peer::PollMessage::*;
384
385 if let Some(event) = stream.pending_recv.pop_front(&mut self.buffer) {
388 match event {
389 Event::Headers(Client(response)) => {
390 stream
392 .pending_recv
393 .push_front(&mut self.buffer, Event::Headers(Client(response)));
394 return Poll::Ready(None);
395 }
396 Event::InformationalHeaders(Client(response)) => {
397 return Poll::Ready(Some(Ok(response)));
399 }
400 other => {
401 stream.pending_recv.push_front(&mut self.buffer, other);
403 }
404 }
405 }
406
407 if stream.state.ensure_recv_open()? {
409 stream.recv_task = Some(cx.waker().clone());
411 Poll::Pending
412 } else {
413 Poll::Ready(None)
415 }
416 }
417
418 pub fn recv_trailers(
420 &mut self,
421 frame: frame::Headers,
422 stream: &mut store::Ptr,
423 ) -> Result<(), Error> {
424 stream.state.recv_close()?;
426
427 if stream.ensure_content_length_zero().is_err() {
428 proto_err!(stream: "recv_trailers: content-length is not zero; stream={:?};", stream.id);
429 return Err(Error::library_reset(stream.id, Reason::PROTOCOL_ERROR));
430 }
431
432 let trailers = frame.into_fields();
433
434 stream
436 .pending_recv
437 .push_back(&mut self.buffer, Event::Trailers(trailers));
438 stream.notify_recv();
439
440 Ok(())
441 }
442
443 pub fn release_connection_capacity(&mut self, capacity: WindowSize, task: &mut Option<Waker>) {
445 tracing::trace!(
446 "release_connection_capacity; size={}, connection in_flight_data={}",
447 capacity,
448 self.in_flight_data,
449 );
450
451 self.in_flight_data -= capacity;
453
454 let _res = self.flow.assign_capacity(capacity);
457 debug_assert!(_res.is_ok());
458
459 if self.flow.unclaimed_capacity().is_some() {
460 if let Some(task) = task.take() {
461 task.wake();
462 }
463 }
464 }
465
466 pub fn release_capacity(
468 &mut self,
469 capacity: WindowSize,
470 stream: &mut store::Ptr,
471 task: &mut Option<Waker>,
472 ) -> Result<(), UserError> {
473 tracing::trace!("release_capacity; size={}", capacity);
474
475 if capacity > stream.in_flight_recv_data {
476 return Err(UserError::ReleaseCapacityTooBig);
477 }
478
479 self.release_connection_capacity(capacity, task);
480
481 stream.in_flight_recv_data -= capacity;
483
484 let _res = stream.recv_flow.assign_capacity(capacity);
487 debug_assert!(_res.is_ok());
488
489 if stream.recv_flow.unclaimed_capacity().is_some() {
490 self.pending_window_updates.push(stream);
492
493 if let Some(task) = task.take() {
494 task.wake();
495 }
496 }
497
498 Ok(())
499 }
500
501 pub fn release_closed_capacity(
503 &mut self,
504 stream: &mut store::Ptr,
505 task: &mut Option<Waker>,
506 counts: &mut Counts,
507 ) {
508 debug_assert_eq!(stream.ref_count, 0);
509
510 if stream.in_flight_recv_data != 0 {
511 tracing::trace!(
512 "auto-release closed stream ({:?}) capacity: {:?}",
513 stream.id,
514 stream.in_flight_recv_data,
515 );
516
517 self.release_connection_capacity(stream.in_flight_recv_data, task);
518 stream.in_flight_recv_data = 0;
519 }
520
521 self.clear_recv_buffer(stream, task, counts);
522 }
523
524 pub fn set_target_connection_window(
537 &mut self,
538 target: WindowSize,
539 task: &mut Option<Waker>,
540 ) -> Result<(), Reason> {
541 tracing::trace!(
542 "set_target_connection_window; target={}; available={}, reserved={}",
543 target,
544 self.flow.available(),
545 self.in_flight_data,
546 );
547
548 let current = self
554 .flow
555 .available()
556 .add(self.in_flight_data)?
557 .checked_size();
558 if target > current {
559 self.flow.assign_capacity(target - current)?;
560 } else {
561 self.flow.claim_capacity(current - target)?;
562 }
563
564 if self.flow.unclaimed_capacity().is_some() {
568 if let Some(task) = task.take() {
569 task.wake();
570 }
571 }
572 Ok(())
573 }
574
575 pub(crate) fn apply_local_settings(
576 &mut self,
577 settings: &frame::Settings,
578 store: &mut Store,
579 ) -> Result<(), proto::Error> {
580 if let Some(val) = settings.is_extended_connect_protocol_enabled() {
581 self.is_extended_connect_protocol_enabled = val;
582 }
583
584 if let Some(target) = settings.initial_window_size() {
585 let old_sz = self.init_window_sz;
586 self.init_window_sz = target;
587
588 tracing::trace!("update_initial_window_size; new={}; old={}", target, old_sz,);
589
590 match target.cmp(&old_sz) {
607 Ordering::Less => {
608 let dec = old_sz - target;
610 tracing::trace!("decrementing all windows; dec={}", dec);
611
612 store.try_for_each(|mut stream| {
613 stream
614 .recv_flow
615 .dec_recv_window(dec)
616 .map_err(proto::Error::library_go_away)?;
617 Ok::<_, proto::Error>(())
618 })?;
619 }
620 Ordering::Greater => {
621 let inc = target - old_sz;
623 tracing::trace!("incrementing all windows; inc={}", inc);
624 store.try_for_each(|mut stream| {
625 stream
628 .recv_flow
629 .inc_window(inc)
630 .map_err(proto::Error::library_go_away)?;
631 stream
632 .recv_flow
633 .assign_capacity(inc)
634 .map_err(proto::Error::library_go_away)?;
635 Ok::<_, proto::Error>(())
636 })?;
637 }
638 Ordering::Equal => (),
639 }
640 }
641
642 Ok(())
643 }
644
645 pub fn is_end_stream(&self, stream: &store::Ptr) -> bool {
646 if !stream.state.is_recv_end_stream() {
647 return false;
648 }
649
650 stream.pending_recv.is_empty()
651 }
652
653 pub fn recv_data(&mut self, frame: frame::Data, stream: &mut store::Ptr) -> Result<(), Error> {
654 let sz = frame.flow_controlled_len();
656
657 assert!(sz <= MAX_WINDOW_SIZE as usize);
660
661 let sz = sz as WindowSize;
662
663 let is_ignoring_frame = stream.state.is_local_error();
664
665 if !is_ignoring_frame && !stream.state.is_recv_streaming() {
666 proto_err!(conn: "unexpected DATA frame; stream={:?}", stream.id);
672 return Err(Error::library_go_away(Reason::PROTOCOL_ERROR));
673 }
674
675 tracing::trace!(
676 "recv_data; size={}; connection={}; stream={}",
677 sz,
678 self.flow.window_size(),
679 stream.recv_flow.window_size()
680 );
681
682 if is_ignoring_frame {
683 tracing::trace!(
684 "recv_data; frame ignored on locally reset {:?} for some time",
685 stream.id,
686 );
687 return self.ignore_data(sz);
688 }
689
690 self.consume_connection_window(sz)?;
693
694 if stream.recv_flow.window_size() < sz {
695 return Err(Error::library_reset(stream.id, Reason::FLOW_CONTROL_ERROR));
704 }
705
706 if stream.dec_content_length(frame.payload().len()).is_err() {
708 proto_err!(stream:
709 "recv_data: content-length overflow; stream={:?}; len={:?}",
710 stream.id,
711 frame.payload().len(),
712 );
713 return Err(Error::library_reset(stream.id, Reason::PROTOCOL_ERROR));
714 }
715
716 if frame.is_end_stream() {
717 if stream.ensure_content_length_zero().is_err() {
718 proto_err!(stream:
719 "recv_data: content-length underflow; stream={:?}; len={:?}",
720 stream.id,
721 frame.payload().len(),
722 );
723 return Err(Error::library_reset(stream.id, Reason::PROTOCOL_ERROR));
724 }
725
726 if stream.state.recv_close().is_err() {
727 proto_err!(conn: "recv_data: failed to transition to closed state; stream={:?}", stream.id);
728 return Err(Error::library_go_away(Reason::PROTOCOL_ERROR));
729 }
730 }
731
732 if !stream.is_recv {
734 tracing::trace!(
735 "recv_data; frame ignored on stream release {:?} for some time",
736 stream.id,
737 );
738 self.release_connection_capacity(sz, &mut None);
739 return Ok(());
740 }
741
742 stream
744 .recv_flow
745 .send_data(sz)
746 .map_err(proto::Error::library_go_away)?;
747
748 stream.in_flight_recv_data += sz;
750
751 let padding = (frame.flow_controlled_len() - frame.payload().len()) as WindowSize;
754 if padding > 0 {
755 tracing::trace!(
756 "recv_data; auto-releasing padding of {:?} for {:?}",
757 padding,
758 stream.id,
759 );
760 let _res = self.release_capacity(padding, stream, &mut None);
761 debug_assert!(_res.is_ok());
763 }
764
765 if frame.payload().is_empty() && !frame.is_end_stream() {
769 return Ok(());
770 }
771
772 let is_budgeted = !frame.is_end_stream();
773 let event = Event::Data(DataEvent {
774 payload: frame.into_payload(),
775 is_budgeted,
776 });
777
778 stream.pending_recv.push_back(&mut self.buffer, event);
780 stream.notify_recv();
781
782 Ok(())
783 }
784
785 pub fn ignore_data(&mut self, sz: WindowSize) -> Result<(), Error> {
786 self.consume_connection_window(sz)?;
788
789 self.release_connection_capacity(sz, &mut None);
798 Ok(())
799 }
800
801 pub fn consume_connection_window(&mut self, sz: WindowSize) -> Result<(), Error> {
802 if self.flow.window_size() < sz {
803 tracing::debug!(
804 "connection error FLOW_CONTROL_ERROR -- window_size ({:?}) < sz ({:?});",
805 self.flow.window_size(),
806 sz,
807 );
808 return Err(Error::library_go_away(Reason::FLOW_CONTROL_ERROR));
809 }
810
811 self.flow.send_data(sz).map_err(Error::library_go_away)?;
813
814 self.in_flight_data += sz;
816 Ok(())
817 }
818
819 pub fn recv_push_promise(
820 &mut self,
821 frame: frame::PushPromise,
822 stream: &mut store::Ptr,
823 ) -> Result<(), Error> {
824 stream.state.reserve_remote()?;
825 if frame.is_over_size() {
826 tracing::debug!(
838 "stream error PROTOCOL_ERROR -- recv_push_promise: \
839 headers frame is over size; promised_id={:?};",
840 frame.promised_id(),
841 );
842 return Err(Error::library_reset(
843 frame.promised_id(),
844 Reason::PROTOCOL_ERROR,
845 ));
846 }
847
848 let promised_id = frame.promised_id();
849 let (pseudo, fields) = frame.into_parts();
850 let req = crate::server::Peer::convert_poll_message(pseudo, fields, promised_id)?;
851
852 if let Err(e) = frame::PushPromise::validate_request(&req) {
853 use PushPromiseHeaderError::*;
854 match e {
855 NotSafeAndCacheable => proto_err!(
856 stream:
857 "recv_push_promise: method {} is not safe and cacheable; promised_id={:?}",
858 req.method(),
859 promised_id,
860 ),
861 InvalidContentLength(e) => proto_err!(
862 stream:
863 "recv_push_promise; promised request has invalid content-length {:?}; promised_id={:?}",
864 e,
865 promised_id,
866 ),
867 }
868 return Err(Error::library_reset(promised_id, Reason::PROTOCOL_ERROR));
869 }
870
871 use super::peer::PollMessage::*;
872 stream
873 .pending_recv
874 .push_back(&mut self.buffer, Event::Headers(Server(req)));
875 stream.notify_recv();
876 stream.notify_push();
877 Ok(())
878 }
879
880 pub fn ensure_not_idle(&self, id: StreamId) -> Result<(), Reason> {
882 if let Ok(next) = self.next_stream_id {
883 if id >= next {
884 tracing::debug!(
885 "stream ID implicitly closed, PROTOCOL_ERROR; stream={:?}",
886 id
887 );
888 return Err(Reason::PROTOCOL_ERROR);
889 }
890 }
891 Ok(())
894 }
895
896 pub fn recv_reset(
898 &mut self,
899 frame: frame::Reset,
900 stream: &mut Stream,
901 counts: &mut Counts,
902 ) -> Result<(), Error> {
903 if stream.is_pending_accept {
912 if counts.can_inc_num_remote_reset_streams() {
913 counts.inc_num_remote_reset_streams();
914 } else {
915 tracing::warn!(
916 "recv_reset; remotely-reset pending-accept streams reached limit ({:?})",
917 counts.max_remote_reset_streams(),
918 );
919 return Err(Error::library_go_away_data(
920 Reason::ENHANCE_YOUR_CALM,
921 "too_many_resets",
922 ));
923 }
924 }
925
926 stream.state.recv_reset(frame, stream.is_pending_send);
928
929 stream.notify_send();
930 stream.notify_recv();
931 stream.notify_push();
932
933 Ok(())
934 }
935
936 pub fn handle_error(&mut self, err: &proto::Error, stream: &mut Stream) {
938 stream.state.handle_error(err);
940
941 stream.notify_send();
943 stream.notify_recv();
944 stream.notify_push();
945 }
946
947 pub fn go_away(&mut self, last_processed_id: StreamId) {
948 assert!(self.max_stream_id >= last_processed_id);
949 self.max_stream_id = last_processed_id;
950 }
951
952 pub fn recv_eof(&mut self, stream: &mut Stream) {
953 stream.state.recv_eof();
954 stream.notify_send();
955 stream.notify_recv();
956 stream.notify_push();
957 }
958
959 pub(super) fn clear_recv_buffer(
960 &mut self,
961 stream: &mut Stream,
962 task: &mut Option<Waker>,
963 counts: &mut Counts,
964 ) {
965 let mut to_release: WindowSize = 0;
966 while let Some(event) = stream.pending_recv.pop_front(&mut self.buffer) {
967 if let Event::Data(data) = &event {
968 if data.is_budgeted {
969 counts.release_data_frame(data.payload.len());
970 }
971 to_release = to_release
972 .saturating_add(data.payload.len() as WindowSize)
973 .min(stream.in_flight_recv_data);
974 }
975 }
976 if to_release > 0 {
981 stream.in_flight_recv_data -= to_release;
982 self.release_connection_capacity(to_release, task);
983 }
984 }
985
986 pub fn max_stream_id(&self) -> StreamId {
990 self.max_stream_id
991 }
992
993 pub fn next_stream_id(&self) -> Result<StreamId, Error> {
994 if let Ok(id) = self.next_stream_id {
995 Ok(id)
996 } else {
997 Err(Error::library_go_away(Reason::PROTOCOL_ERROR))
998 }
999 }
1000
1001 pub fn may_have_created_stream(&self, id: StreamId) -> bool {
1002 if let Ok(next_id) = self.next_stream_id {
1003 debug_assert_eq!(id.is_server_initiated(), next_id.is_server_initiated(),);
1005 id < next_id
1006 } else {
1007 true
1008 }
1009 }
1010
1011 pub(super) fn maybe_reset_next_stream_id(&mut self, id: StreamId) {
1012 if let Ok(next_id) = self.next_stream_id {
1013 debug_assert_eq!(id.is_server_initiated(), next_id.is_server_initiated());
1015 if id >= next_id {
1016 self.next_stream_id = id.next_id();
1017 }
1018 }
1019 }
1020
1021 pub fn ensure_can_reserve(&self) -> Result<(), Error> {
1023 if !self.is_push_enabled {
1024 proto_err!(conn: "recv_push_promise: push is disabled");
1025 return Err(Error::library_go_away(Reason::PROTOCOL_ERROR));
1026 }
1027
1028 Ok(())
1029 }
1030
1031 pub fn enqueue_reset_expiration(&mut self, stream: &mut store::Ptr, counts: &mut Counts) {
1033 if !stream.state.is_local_error() || stream.is_pending_reset_expiration() {
1034 return;
1035 }
1036
1037 if counts.can_inc_num_reset_streams() {
1038 counts.inc_num_reset_streams();
1039 tracing::trace!("enqueue_reset_expiration; added {:?}", stream.id);
1040 self.pending_reset_expired.push(stream);
1041 } else {
1042 tracing::trace!(
1043 "enqueue_reset_expiration; dropped {:?}, over max_concurrent_reset_streams",
1044 stream.id
1045 );
1046 }
1047 }
1048
1049 pub fn send_pending_refusal<T, B>(
1051 &mut self,
1052 dst: &mut Codec<T, Prioritized<B>>,
1053 ) -> io::Result<BufferStatus>
1054 where
1055 T: AsyncWrite + Unpin,
1056 B: Buf,
1057 {
1058 if let Some(stream_id) = self.refused {
1059 if !dst.has_send_capacity() {
1060 return Ok(BufferStatus::CodecFull);
1061 }
1062
1063 let frame = frame::Reset::new(stream_id, Reason::REFUSED_STREAM);
1065
1066 dst.buffer(frame.into()).expect("invalid RST_STREAM frame");
1068 }
1069
1070 self.refused = None;
1071
1072 Ok(BufferStatus::Complete)
1073 }
1074
1075 pub fn clear_expired_reset_streams(&mut self, store: &mut Store, counts: &mut Counts) {
1076 if !self.pending_reset_expired.is_empty() {
1077 let now = Instant::now();
1078 let reset_duration = self.reset_duration;
1079 while let Some(stream) = self.pending_reset_expired.pop_if(store, |stream| {
1080 let reset_at = stream.reset_at.expect("reset_at must be set if in queue");
1081 now.saturating_duration_since(reset_at) > reset_duration
1085 }) {
1086 counts.transition_after(stream, true);
1087 }
1088 }
1089 }
1090
1091 pub fn clear_queues(
1092 &mut self,
1093 clear_pending_accept: bool,
1094 store: &mut Store,
1095 counts: &mut Counts,
1096 ) {
1097 self.clear_stream_window_update_queue(store, counts);
1098 self.clear_all_reset_streams(store, counts);
1099
1100 if clear_pending_accept {
1101 self.clear_all_pending_accept(store, counts);
1102 }
1103 }
1104
1105 fn clear_stream_window_update_queue(&mut self, store: &mut Store, counts: &mut Counts) {
1106 while let Some(stream) = self.pending_window_updates.pop(store) {
1107 counts.transition(stream, |_, stream| {
1108 tracing::trace!("clear_stream_window_update_queue; stream={:?}", stream.id);
1109 })
1110 }
1111 }
1112
1113 fn clear_all_reset_streams(&mut self, store: &mut Store, counts: &mut Counts) {
1115 while let Some(stream) = self.pending_reset_expired.pop(store) {
1116 counts.transition_after(stream, true);
1117 }
1118 }
1119
1120 fn clear_all_pending_accept(&mut self, store: &mut Store, counts: &mut Counts) {
1121 while let Some(stream) = self.pending_accept.pop(store) {
1122 counts.transition_after(stream, false);
1123 }
1124 }
1125
1126 pub fn buffer_pending<T, B>(
1127 &mut self,
1128 store: &mut Store,
1129 counts: &mut Counts,
1130 dst: &mut Codec<T, Prioritized<B>>,
1131 ) -> io::Result<BufferStatus>
1132 where
1133 T: AsyncWrite + Unpin,
1134 B: Buf,
1135 {
1136 if self.send_connection_window_update(dst)? == BufferStatus::CodecFull {
1138 return Ok(BufferStatus::CodecFull);
1139 }
1140
1141 if self.send_stream_window_updates(store, counts, dst)? == BufferStatus::CodecFull {
1143 return Ok(BufferStatus::CodecFull);
1144 }
1145
1146 Ok(BufferStatus::Complete)
1147 }
1148
1149 fn send_connection_window_update<T, B>(
1151 &mut self,
1152 dst: &mut Codec<T, Prioritized<B>>,
1153 ) -> io::Result<BufferStatus>
1154 where
1155 T: AsyncWrite + Unpin,
1156 B: Buf,
1157 {
1158 if let Some(incr) = self.flow.unclaimed_capacity() {
1159 let frame = frame::WindowUpdate::new(StreamId::zero(), incr);
1160
1161 if !dst.has_send_capacity() {
1163 return Ok(BufferStatus::CodecFull);
1164 }
1165
1166 dst.buffer(frame.into())
1168 .expect("invalid WINDOW_UPDATE frame");
1169
1170 self.flow
1172 .inc_window(incr)
1173 .expect("unexpected flow control state");
1174 }
1175
1176 Ok(BufferStatus::Complete)
1177 }
1178
1179 pub fn send_stream_window_updates<T, B>(
1181 &mut self,
1182 store: &mut Store,
1183 counts: &mut Counts,
1184 dst: &mut Codec<T, Prioritized<B>>,
1185 ) -> io::Result<BufferStatus>
1186 where
1187 T: AsyncWrite + Unpin,
1188 B: Buf,
1189 {
1190 loop {
1191 if !dst.has_send_capacity() {
1193 return Ok(BufferStatus::CodecFull);
1194 }
1195
1196 let stream = match self.pending_window_updates.pop(store) {
1198 Some(stream) => stream,
1199 None => return Ok(BufferStatus::Complete),
1200 };
1201
1202 counts.transition(stream, |_, stream| {
1203 tracing::trace!("pending_window_updates -- pop; stream={:?}", stream.id);
1204 debug_assert!(!stream.is_pending_window_update);
1205
1206 if !stream.state.is_recv_streaming() {
1207 return;
1214 }
1215
1216 if let Some(incr) = stream.recv_flow.unclaimed_capacity() {
1218 let frame = frame::WindowUpdate::new(stream.id, incr);
1220
1221 dst.buffer(frame.into())
1223 .expect("invalid WINDOW_UPDATE frame");
1224
1225 stream
1227 .recv_flow
1228 .inc_window(incr)
1229 .expect("unexpected flow control state");
1230 }
1231 })
1232 }
1233 }
1234
1235 pub fn next_incoming(&mut self, store: &mut Store) -> Option<store::Key> {
1236 self.pending_accept.pop(store).map(|ptr| ptr.key())
1237 }
1238
1239 pub fn poll_data(
1240 &mut self,
1241 cx: &Context,
1242 stream: &mut Stream,
1243 ) -> Poll<Option<Result<DataEvent, proto::Error>>> {
1244 match stream.pending_recv.pop_front(&mut self.buffer) {
1245 Some(Event::Data(data)) => Poll::Ready(Some(Ok(data))),
1246 Some(event) => {
1247 stream.pending_recv.push_front(&mut self.buffer, event);
1249
1250 stream.notify_recv();
1259
1260 Poll::Ready(None)
1262 }
1263 None => self.schedule_recv(cx, stream),
1264 }
1265 }
1266
1267 pub fn poll_trailers(
1268 &mut self,
1269 cx: &Context,
1270 stream: &mut Stream,
1271 ) -> Poll<Option<Result<HeaderMap, proto::Error>>> {
1272 match stream.pending_recv.pop_front(&mut self.buffer) {
1273 Some(Event::Trailers(trailers)) => Poll::Ready(Some(Ok(trailers))),
1274 Some(event) => {
1275 stream.pending_recv.push_front(&mut self.buffer, event);
1277 stream.recv_task = Some(cx.waker().clone());
1278 Poll::Pending
1279 }
1280 None => self.schedule_recv(cx, stream),
1281 }
1282 }
1283
1284 fn schedule_recv<T>(
1285 &mut self,
1286 cx: &Context,
1287 stream: &mut Stream,
1288 ) -> Poll<Option<Result<T, proto::Error>>> {
1289 if stream.state.ensure_recv_open()? {
1290 stream.recv_task = Some(cx.waker().clone());
1292 Poll::Pending
1293 } else {
1294 Poll::Ready(None)
1296 }
1297 }
1298}
1299
1300#[cfg(test)]
1301mod tests {
1302 use super::*;
1303
1304 #[test]
1305 fn clear_recv_buffer_caps_capacity_before_overflow() {
1306 const FRAME_LEN: usize = 1 << 20;
1307 const FRAME_COUNT: usize = (u32::MAX as usize / FRAME_LEN) + 1;
1308
1309 let config = Config {
1310 initial_max_send_streams: 0,
1311 local_max_buffer_size: 0,
1312 local_next_stream_id: 2.into(),
1313 local_push_enabled: false,
1314 extended_connect_protocol_enabled: false,
1315 local_reset_duration: Duration::ZERO,
1316 local_reset_max: 0,
1317 remote_reset_max: 0,
1318 remote_init_window_sz: DEFAULT_INITIAL_WINDOW_SIZE,
1319 remote_max_initiated: None,
1320 local_max_error_reset_streams: None,
1321 data_frame_budget: DEFAULT_DATA_FRAME_BUDGET,
1322 };
1323 let mut recv = Recv::new(peer::Dyn::Server, &config);
1324 let mut store = Store::new();
1325 let mut stream = store.insert(
1326 StreamId::from(1),
1327 Stream::new(StreamId::from(1), 0, DEFAULT_INITIAL_WINDOW_SIZE),
1328 );
1329 let data = Bytes::from(vec![0; FRAME_LEN]);
1330
1331 for _ in 0..FRAME_COUNT {
1332 stream.pending_recv.push_back(
1333 &mut recv.buffer,
1334 Event::Data(DataEvent {
1335 payload: data.clone(),
1336 is_budgeted: true,
1337 }),
1338 );
1339 }
1340 stream.in_flight_recv_data = DEFAULT_INITIAL_WINDOW_SIZE;
1341 recv.in_flight_data = DEFAULT_INITIAL_WINDOW_SIZE;
1342
1343 let mut counts = Counts::new(peer::Dyn::Server, &config);
1344 recv.clear_recv_buffer(&mut stream, &mut None, &mut counts);
1345
1346 assert!(stream.pending_recv.is_empty());
1347 assert_eq!(stream.in_flight_recv_data, 0);
1348 assert_eq!(recv.in_flight_data, 0);
1349 }
1350}
1351
1352impl Open {
1355 pub fn is_push_promise(&self) -> bool {
1356 matches!(*self, Self::PushPromise)
1357 }
1358}
1359
1360impl<T> From<Error> for RecvHeaderBlockError<T> {
1363 fn from(err: Error) -> Self {
1364 RecvHeaderBlockError::State(err)
1365 }
1366}