1mod control;
12mod date;
13mod error;
14mod frame;
15mod options;
16pub mod qpack;
17#[cfg(feature = "h3-quinn")]
18pub mod quinn;
19mod settings;
20mod stream;
21pub mod transport;
22mod upgrade;
23
24pub use error::{H3Error, TransportError};
25pub use frame::{Frame, FrameDecoder, FrameError, Settings};
26pub use options::*;
27
28use std::{
29 pin::Pin,
30 rc::Rc,
31 sync::{
32 atomic::{AtomicBool, Ordering},
33 Arc,
34 },
35 task::{Context, Poll},
36};
37
38use bytes::Bytes;
39use futures_util::stream::FuturesUnordered;
40use futures_util::{ready, Future, FutureExt, StreamExt};
41use http::{Request, Response, StatusCode};
42use http_body::{Body, Frame as BodyFrame};
43use http_body_util::BodyExt;
44use tokio_util::sync::CancellationToken;
45
46use crate::{
47 h3::{
48 control::{ControlEvent, ControlStreams},
49 date::DateCache,
50 stream::{RequestStream, SharedCodecs, StreamError},
51 },
52 EarlyHints, HttpProtocol, Incoming, Upgrade, Upgraded,
53};
54
55const H3_NO_ERROR: u64 = 0x0100;
57const H3_REQUEST_REJECTED: u64 = 0x010b;
58
59#[derive(Debug, Clone, Copy)]
63pub(super) struct ResetLimits {
64 pub(super) max_local_error_resets: Option<usize>,
65 pub(super) max_pending_accept_resets: Option<usize>,
66}
67
68#[derive(Debug)]
71struct ConnResetState {
72 limits: ResetLimits,
73 local_error_resets: usize,
76 pending_accept_resets: usize,
80 close_code: Option<u64>,
83}
84
85impl ConnResetState {
86 #[inline]
89 fn note_local_error_reset(&mut self) -> Option<u64> {
90 match self.limits.max_local_error_resets {
91 Some(max) if self.local_error_resets >= max => Some(H3Error::ExcessiveLoad.code()),
92 _ => {
93 self.local_error_resets += 1;
94 None
95 }
96 }
97 }
98
99 #[inline]
102 fn note_pending_accept_reset(&mut self) -> Option<u64> {
103 match self.limits.max_pending_accept_resets {
104 Some(max) if self.pending_accept_resets >= max => Some(H3Error::ExcessiveLoad.code()),
105 _ => {
106 self.pending_accept_resets += 1;
107 None
108 }
109 }
110 }
111}
112
113type SharedRequest = Arc<tokio::sync::Mutex<RequestStream>>;
116
117static HTTP3_INVALID_HEADERS: [http::header::HeaderName; 5] = [
118 http::header::HeaderName::from_static("keep-alive"),
119 http::header::HeaderName::from_static("proxy-connection"),
120 http::header::CONNECTION,
121 http::header::TRANSFER_ENCODING,
122 http::header::UPGRADE,
123];
124
125struct H3BodyState {
127 stream: SharedRequest,
128 data_done: bool,
129 send_continue_body: Option<Arc<AtomicBool>>,
130}
131
132pub(crate) struct H3Body {
133 inner: tokio::sync::Mutex<H3BodyState>,
134}
135
136impl H3Body {
137 #[inline]
138 fn new(stream: SharedRequest, send_continue_body: Option<Arc<AtomicBool>>) -> Self {
139 Self {
140 inner: tokio::sync::Mutex::new(H3BodyState {
141 stream,
142 data_done: false,
143 send_continue_body,
144 }),
145 }
146 }
147}
148
149impl Body for H3Body {
150 type Data = Bytes;
151 type Error = std::io::Error;
152
153 #[inline]
154 fn poll_frame(
155 self: Pin<&mut Self>,
156 cx: &mut Context<'_>,
157 ) -> Poll<Option<Result<BodyFrame<Self::Data>, Self::Error>>> {
158 let mut inner = match std::pin::pin!(self.inner.lock()).poll_unpin(cx) {
159 Poll::Ready(inner) => inner,
160 Poll::Pending => return Poll::Pending,
161 };
162
163 if !inner.data_done {
164 loop {
165 let mut stream = match std::pin::pin!(inner.stream.lock()).poll_unpin(cx) {
166 Poll::Ready(stream) => stream,
167 Poll::Pending => return Poll::Pending,
168 };
169 match stream.poll_recv_data(cx) {
170 Poll::Ready(Ok(Some(data))) => {
171 if data.is_empty() {
172 continue;
173 }
174 return Poll::Ready(Some(Ok(BodyFrame::data(data))));
175 }
176 Poll::Ready(Ok(None)) => {
177 drop(stream);
178 inner.data_done = true;
179 break;
180 }
181 Poll::Ready(Err(err)) => {
182 return Poll::Ready(Some(Err(h3_stream_error_to_io(err))));
183 }
184 Poll::Pending => {
185 if let Some(scb) = inner.send_continue_body.as_ref() {
186 scb.store(true, std::sync::atomic::Ordering::Relaxed);
187 }
188 return Poll::Pending;
189 }
190 };
191 }
192 }
193
194 let mut stream = match std::pin::pin!(inner.stream.lock()).poll_unpin(cx) {
195 Poll::Ready(stream) => stream,
196 Poll::Pending => {
197 if let Some(scb) = inner.send_continue_body.as_ref() {
198 scb.store(true, std::sync::atomic::Ordering::Relaxed);
199 }
200 return Poll::Pending;
201 }
202 };
203 match stream.poll_recv_trailers(cx) {
204 Poll::Ready(Ok(Some(trailers))) => Poll::Ready(Some(Ok(BodyFrame::trailers(trailers)))),
205 Poll::Ready(Ok(None)) => Poll::Ready(None),
206 Poll::Ready(Err(err)) => Poll::Ready(Some(Err(h3_stream_error_to_io(err)))),
207 Poll::Pending => {
208 if let Some(scb) = inner.send_continue_body.as_ref() {
209 scb.store(true, std::sync::atomic::Ordering::Relaxed);
210 }
211 Poll::Pending
212 }
213 }
214 }
215}
216
217#[inline]
218fn h3_control_error_to_io(error: control::ControlError) -> std::io::Error {
219 std::io::Error::other(error)
220}
221
222#[inline]
223fn h3_transport_error_to_io(error: TransportError) -> std::io::Error {
224 std::io::Error::other(error)
225}
226
227#[inline]
228fn h3_stream_error_to_io(error: stream::StreamError) -> std::io::Error {
229 std::io::Error::other(error)
230}
231
232#[inline]
233fn remove_invalid_http3_headers(headers: &mut http::HeaderMap) {
234 for header in &HTTP3_INVALID_HEADERS {
235 headers.remove(header);
236 }
237 if headers
238 .get(http::header::TE)
239 .is_some_and(|v| v != "trailers")
240 {
241 headers.remove(http::header::TE);
242 }
243}
244
245#[inline]
251async fn wait_for_encoder(shared: &Arc<parking_lot::Mutex<SharedCodecs>>, stream_id: u64) {
252 std::future::poll_fn(|cx| {
253 let mut shared = shared.lock();
254 if shared.encoder.is_some() {
255 shared.waiters.remove(&stream_id);
256 return Poll::Ready(());
257 }
258 shared.waiters.insert(stream_id, cx.waker().clone());
259 Poll::Pending
260 })
261 .await
262}
263
264#[inline]
266async fn send_interim_response(
267 stream: &SharedRequest,
268 status: StatusCode,
269) -> Result<(), std::io::Error> {
270 let mut guard = stream.lock().await;
271 std::future::poll_fn(|cx| guard.poll_send_response(cx, status, &http::HeaderMap::new()))
272 .await
273 .map_err(h3_stream_error_to_io)
274}
275
276#[inline]
279async fn send_response(
280 stream: &SharedRequest,
281 shared: &Arc<parking_lot::Mutex<SharedCodecs>>,
282 stream_id: u64,
283 status: StatusCode,
284 headers: &http::HeaderMap,
285) -> Result<(), std::io::Error> {
286 wait_for_encoder(shared, stream_id).await;
287 let mut guard = stream.lock().await;
288 let res = std::future::poll_fn(|cx| guard.poll_send_response(cx, status, headers))
289 .await
290 .map_err(h3_stream_error_to_io);
291 res
292}
293
294#[inline]
296async fn send_data(stream: &SharedRequest, data: Bytes) -> Result<(), std::io::Error> {
297 let mut guard = stream.lock().await;
298 std::future::poll_fn(|cx| guard.poll_send_data(cx, data.clone()))
299 .await
300 .map_err(h3_stream_error_to_io)
301}
302
303#[inline]
305async fn send_trailers(
306 stream: &SharedRequest,
307 trailers: &http::HeaderMap,
308) -> Result<(), std::io::Error> {
309 let mut guard = stream.lock().await;
310 std::future::poll_fn(|cx| guard.poll_send_trailers(cx, trailers))
311 .await
312 .map_err(h3_stream_error_to_io)
313}
314
315#[inline]
317async fn send_finish(stream: &SharedRequest) -> Result<(), std::io::Error> {
318 let mut guard = stream.lock().await;
319 std::future::poll_fn(|cx| guard.poll_finish(cx))
320 .await
321 .map_err(h3_stream_error_to_io)
322}
323
324#[allow(clippy::type_complexity)]
330#[allow(clippy::too_many_arguments)]
331async fn handle_request<F, Fut, ResB, ResBE, ResE>(
332 stream: SharedRequest,
333 shared: Arc<parking_lot::Mutex<SharedCodecs>>,
334 stream_id: u64,
335 request_fn: Rc<F>,
336 date_cache: DateCache,
337 send_continue_response: bool,
338 send_date_header: bool,
339 conn_state: Arc<parking_lot::Mutex<ConnResetState>>,
340) where
341 F: Fn(Request<Incoming>) -> Fut,
342 Fut: std::future::Future<Output = Result<Response<ResB>, ResE>>,
343 ResB: Body<Data = Bytes, Error = ResBE> + Unpin,
344 ResE: std::error::Error,
345 ResBE: std::error::Error,
346{
347 let request_headers = {
349 let mut guard = stream.lock().await;
350 std::future::poll_fn(|cx| guard.poll_headers(cx)).await
351 };
352 let request = match request_headers {
353 Ok(Some(request)) => request,
354 Ok(None) => return,
356 Err(err) => {
357 if err.is_stream_scoped() {
362 let mut state = conn_state.lock();
363 if let Some(code) = state.note_pending_accept_reset() {
364 state.close_code = Some(code);
365 }
366 return;
367 }
368 if matches!(err, StreamError::Message) {
372 let mut guard = stream.lock().await;
373 let code = err.h3_code();
374 let _ = std::future::poll_fn(|cx| guard.poll_reset(cx, code)).await;
375 let _ = std::future::poll_fn(|cx| guard.poll_stop_sending(cx, code)).await;
376 drop(guard);
377 let mut state = conn_state.lock();
378 if let Some(code) = state.note_local_error_reset() {
379 state.close_code = Some(code);
380 }
381 return;
382 }
383 conn_state.lock().close_code = Some(err.h3_code());
387 return;
388 }
389 };
390
391 let is_100_continue = send_continue_response
393 && request
394 .headers()
395 .get(http::header::EXPECT)
396 .and_then(|v| v.to_str().ok())
397 .is_some_and(|v| v.eq_ignore_ascii_case("100-continue"));
398
399 let send_continue_body = is_100_continue.then(|| Arc::new(AtomicBool::new(false)));
400 let (request_parts, _) = request.into_parts();
401 let (request_body, upgrade) = if request_parts.method == http::Method::CONNECT {
402 (Incoming::Empty, Some(stream.clone()))
403 } else {
404 (
405 Incoming::Boxed(Box::pin(H3Body::new(
406 stream.clone(),
407 send_continue_body.clone(),
408 ))),
409 None,
410 )
411 };
412 let mut request = Request::from_parts(request_parts, request_body);
413
414 let (early_hints, mut early_hints_rx) = EarlyHints::new_lazy();
416 request.extensions_mut().insert(early_hints);
417
418 let upgrade = if let Some(recv_stream) = upgrade {
420 let (upgrade_tx, upgrade_rx) = oneshot::async_channel();
421 let upgrade = Upgrade::new(upgrade_rx);
422 let upgraded = upgrade.upgraded.clone();
423 request.extensions_mut().insert(upgrade);
424 Some((upgrade_tx, upgraded, recv_stream))
425 } else {
426 None
427 };
428
429 let mut response_fut = std::pin::pin!(request_fn(request));
430 let mut early_hints_open = true;
431 let mut continue_sent = false;
432 let response_result = loop {
433 if !early_hints_open {
434 break response_fut.as_mut().await;
435 }
436
437 let next = std::future::poll_fn(|cx| {
438 if let Poll::Ready(res) = response_fut.as_mut().poll(cx) {
439 return Poll::Ready(Some(futures_util::future::Either::Left(res)));
440 }
441
442 match early_hints_rx.poll_recv(cx) {
443 Poll::Ready(Some(msg)) => {
444 return Poll::Ready(Some(futures_util::future::Either::Right(Ok(msg))))
445 }
446 Poll::Ready(None) => {
447 return Poll::Ready(Some(futures_util::future::Either::Right(Err(()))))
448 }
449 Poll::Pending => {}
450 }
451
452 if !continue_sent
453 && is_100_continue
454 && send_continue_body
455 .as_ref()
456 .is_some_and(|b| b.load(Ordering::Relaxed))
457 {
458 continue_sent = true;
459 return Poll::Ready(None);
460 }
461
462 Poll::Pending
463 })
464 .await;
465
466 match next {
467 Some(futures_util::future::Either::Left(response_result)) => {
469 break response_result;
470 }
471 Some(futures_util::future::Either::Right(Ok((headers, sender)))) => {
473 sender
474 .into_inner()
475 .send(
476 send_response(
477 &stream,
478 &shared,
479 stream_id,
480 StatusCode::EARLY_HINTS,
481 &headers,
482 )
483 .await,
484 )
485 .ok();
486 }
487 Some(futures_util::future::Either::Right(Err(()))) => {
488 early_hints_open = false;
489 }
490 None => {
492 if send_interim_response(&stream, StatusCode::CONTINUE)
493 .await
494 .is_err()
495 {
496 return;
497 }
498 }
499 }
500 };
501
502 let Ok(mut response) = response_result else {
503 return;
505 };
506
507 {
508 let response_headers = response.headers_mut();
509 if send_date_header {
510 if let Some(http_date) = date_cache.get_date_header_value() {
511 response_headers
512 .entry(http::header::DATE)
513 .or_insert(http_date);
514 }
515 }
516 remove_invalid_http3_headers(response_headers);
517 }
518
519 let response_is_end_stream = response.body().is_end_stream();
520 if !response_is_end_stream {
521 if let Some(content_length) = response.body().size_hint().exact() {
522 if !response
523 .headers()
524 .contains_key(http::header::CONTENT_LENGTH)
525 {
526 response
527 .headers_mut()
528 .insert(http::header::CONTENT_LENGTH, content_length.into());
529 }
530 }
531 }
532
533 if is_100_continue
534 && !continue_sent
535 && !response.status().is_client_error()
536 && !response.status().is_server_error()
537 && send_interim_response(&stream, StatusCode::CONTINUE)
538 .await
539 .is_err()
540 {
541 return;
542 }
543
544 let (response_parts, mut response_body) = response.into_parts();
545 if send_response(
546 &stream,
547 &shared,
548 stream_id,
549 response_parts.status,
550 &response_parts.headers,
551 )
552 .await
553 .is_err()
554 {
555 return;
556 }
557
558 if let Some((upgrade_tx, upgraded, recv_stream)) = upgrade {
559 if upgraded.load(Ordering::Relaxed) {
560 let (upgraded, task) = self::upgrade::pair(recv_stream);
561 let _ = upgrade_tx.send(Upgraded::new(upgraded, None));
562 task.await;
563 return;
564 }
565 }
566
567 if !response_is_end_stream {
568 while let Some(chunk) = response_body.frame().await {
569 match chunk {
570 Ok(frame) => {
571 if frame.is_data() {
572 match frame.into_data() {
573 Ok(data) => {
574 if data.is_empty() {
575 continue;
577 }
578 if send_data(&stream, data).await.is_err() {
579 return;
580 }
581 }
582 Err(_) => {
583 return;
584 }
585 }
586 } else if frame.is_trailers() {
587 match frame.into_trailers() {
588 Ok(mut trailers) => {
589 remove_invalid_http3_headers(&mut trailers);
590 if send_trailers(&stream, &trailers).await.is_err() {
591 return;
592 }
593 break;
594 }
595 Err(_) => {
596 return;
597 }
598 }
599 }
600 }
601 Err(_) => {
602 return;
603 }
604 }
605 }
606 }
607
608 let _ = send_finish(&stream).await;
609}
610
611pub struct Http3<Io> {
634 io_to_handshake: Option<Io>,
635 date_header_value_cached: DateCache,
636 options: Http3Options,
637 cancel_token: Option<CancellationToken>,
638}
639
640impl<Io> Http3<Io>
641where
642 Io: transport::Connection + Unpin + 'static,
643{
644 #[inline]
657 pub fn new(io: Io, options: Http3Options) -> Self {
658 Self {
659 io_to_handshake: Some(io),
660 date_header_value_cached: DateCache::default(),
661 options,
662 cancel_token: None,
663 }
664 }
665
666 #[inline]
672 pub fn graceful_shutdown_token(mut self, token: CancellationToken) -> Self {
673 self.cancel_token = Some(token);
674 self
675 }
676}
677
678impl<Io> HttpProtocol for Http3<Io>
679where
680 Io: transport::Connection + Unpin + 'static,
681{
682 #[allow(clippy::manual_async_fn)]
683 #[inline]
684 fn handle<F, Fut, ResB, ResBE, ResE>(
685 self,
686 request_fn: F,
687 ) -> impl std::future::Future<Output = Result<(), std::io::Error>>
688 where
689 F: Fn(Request<super::Incoming>) -> Fut + 'static,
690 Fut: std::future::Future<Output = Result<Response<ResB>, ResE>> + 'static,
691 ResB: http_body::Body<Data = bytes::Bytes, Error = ResBE> + Unpin + 'static,
692 ResE: std::error::Error + 'static,
693 ResBE: std::error::Error + 'static,
694 {
695 async move {
696 let request_fn = Rc::new(request_fn);
697 let Http3 {
698 mut io_to_handshake,
699 date_header_value_cached,
700 options,
701 cancel_token,
702 } = self;
703 let mut conn = io_to_handshake
704 .take()
705 .ok_or_else(|| std::io::Error::other("no io to handshake"))?;
706 let date_cache = date_header_value_cached;
707 let send_continue_response = options.send_continue_response;
708 let send_date_header = options.send_date_header;
709
710 if let Some(timeout) = options.handshake_timeout {
714 vibeio::time::timeout(timeout, async {
715 while !conn.is_handshake_complete() {
716 vibeio::time::sleep(std::time::Duration::from_millis(1)).await;
717 }
718 })
719 .await
720 .map_err(|_| {
721 std::io::Error::new(std::io::ErrorKind::TimedOut, "handshake timeout")
722 })?;
723 } else {
724 while !conn.is_handshake_complete() {
725 vibeio::time::sleep(std::time::Duration::from_millis(1)).await;
726 }
727 }
728
729 let mut controls = ControlStreams::new(options.local_settings.clone());
730 let shared = controls.shared().clone();
731 let conn_state: Arc<parking_lot::Mutex<ConnResetState>> =
736 Arc::new(parking_lot::Mutex::new(ConnResetState {
737 limits: ResetLimits {
738 max_local_error_resets: options.max_local_error_reset_streams,
739 max_pending_accept_resets: options.max_pending_accept_reset_streams,
740 },
741 local_error_resets: 0,
742 pending_accept_resets: 0,
743 close_code: None,
744 }));
745 let mut ongoing: FuturesUnordered<oneshot::AsyncReceiver<()>> = FuturesUnordered::new();
746 let mut cancel_fut: Option<Pin<Box<dyn std::future::Future<Output = ()> + Send>>> =
747 None;
748 if let Some(token) = cancel_token.as_ref() {
749 cancel_fut = Some(Box::pin(token.cancelled()));
750 }
751 let mut accept_sleep: Option<Pin<Box<vibeio::time::Sleep>>> = None;
752 let mut shutdown_sleep: Option<Pin<Box<vibeio::time::Sleep>>> = None;
753 let mut drain_grace: Option<Pin<Box<vibeio::time::Sleep>>> = None;
761 let mut shutdown = false;
762 let mut control_dead = false;
763 let mut closing_with: Option<u64> = None;
767 let mut outcome: Option<Result<(), std::io::Error>> = None;
768 let mut last_request_id = 0u64;
769
770 std::future::poll_fn(|cx| -> Poll<Result<(), std::io::Error>> {
773 ready!(controls
774 .poll_init(&mut conn, cx)
775 .map_err(h3_control_error_to_io))?;
776 ready!(controls.poll_flush(cx).map_err(h3_control_error_to_io))?;
777 Poll::Ready(Ok(()))
778 })
779 .await?;
780
781 std::future::poll_fn(|cx| loop {
782 if let Some(code) = conn_state.lock().close_code.take() {
785 if closing_with.is_none() {
786 closing_with = Some(code);
787 shutdown = true;
788 control_dead = true;
789 }
790 }
791
792 let mut timeout_fired = false;
795 if let Some(sleep) = accept_sleep.as_mut() {
796 if let Poll::Ready(()) = sleep.as_mut().poll(cx) {
797 accept_sleep = None;
798 timeout_fired = true;
799 }
800 } else if let Some(accept_timeout) = options.accept_timeout {
801 accept_sleep = Some(Box::pin(vibeio::time::sleep(accept_timeout)));
802 continue;
803 }
804
805 if let Some(sleep) = shutdown_sleep.as_mut() {
809 if let Poll::Ready(()) = sleep.as_mut().poll(cx) {
810 shutdown_sleep = None;
811 }
812 }
813
814 let mut cancel_fired = false;
816 if let Some(fut) = cancel_fut.as_mut() {
817 if let Poll::Ready(()) = fut.as_mut().poll(cx) {
818 cancel_fired = true;
819 }
820 }
821 if !shutdown {
822 if cancel_fired {
823 shutdown = true;
824 outcome = Some(Ok(()));
825 } else if timeout_fired {
826 shutdown = true;
827 outcome = Some(Err(std::io::Error::new(
828 std::io::ErrorKind::TimedOut,
829 "accept timeout",
830 )));
831 }
832 }
833
834 {
837 let mut shared = shared.lock();
838 controls.queue_encoder_streams(&mut shared.encoder_stream);
839 }
840
841 if !control_dead {
850 match controls.poll_flush(cx) {
851 Poll::Ready(Ok(())) => {}
852 Poll::Ready(Err(err)) => {
853 if shutdown {
854 control_dead = true;
855 } else {
856 closing_with = Some(err.h3_code());
857 shutdown = true;
858 control_dead = true;
859 }
860 }
861 Poll::Pending => {}
862 }
863 }
864
865 if !control_dead {
867 loop {
868 match controls.poll_read(&mut conn, cx) {
869 Poll::Ready(Ok(Some(ControlEvent::Goaway { .. }))) => {
870 if !shutdown {
874 shutdown = true;
875 outcome = Some(Ok(()));
876 }
877 }
878 Poll::Ready(Ok(Some(_))) => {}
879 Poll::Ready(Ok(None)) => {}
880 Poll::Ready(Err(err)) => {
881 if shutdown {
882 control_dead = true;
883 break;
884 }
885 closing_with = Some(err.h3_code());
886 shutdown = true;
887 control_dead = true;
888 break;
889 }
890 Poll::Pending => break,
891 }
892 }
893 }
894
895 if shutdown {
899 if let Some(code) = closing_with {
900 ready!(conn
901 .poll_shutdown(cx, code)
902 .map_err(h3_transport_error_to_io))?;
903 return Poll::Ready(outcome.take().unwrap_or(Ok(())));
904 }
905 if controls.goaway_sent().is_none() {
906 controls.send_goaway(last_request_id);
907 }
908 if ongoing.is_empty() {
909 if let Some(grace) = drain_grace.as_mut() {
913 if grace.as_mut().poll(cx).is_ready() {
914 ready!(conn
915 .poll_shutdown(cx, H3_NO_ERROR)
916 .map_err(h3_transport_error_to_io))?;
917 return Poll::Ready(outcome.take().unwrap_or(Ok(())));
918 }
919 } else {
920 drain_grace = Some(Box::pin(vibeio::time::sleep(
921 std::time::Duration::from_millis(50),
922 )));
923 }
924 } else if shutdown_sleep.is_none() {
925 shutdown_sleep = Some(Box::pin(vibeio::time::sleep(
926 std::time::Duration::from_millis(10),
927 )));
928 }
929 }
930
931 match conn.poll_accept(cx) {
933 Poll::Ready(Ok(Some(stream))) => {
934 let id = stream.id();
935 last_request_id = last_request_id.max(id);
936 accept_sleep = None;
937 if shutdown
938 && (controls.goaway_sent().is_none()
939 || id > controls.goaway_sent().unwrap_or(u64::MAX))
940 {
941 let mut rejected = RequestStream::new(stream, shared.clone());
944 let _ = rejected.poll_reset(cx, H3_REQUEST_REJECTED);
945 } else {
946 let (end_tx, end_rx) = oneshot::async_channel();
947 ongoing.push(end_rx);
948 let request_stream = Arc::new(tokio::sync::Mutex::new(
949 RequestStream::new(stream, shared.clone()),
950 ));
951 let request_fn = request_fn.clone();
952 let date_cache = date_cache.clone();
953 let shared = shared.clone();
954 let conn_state_for_task = conn_state.clone();
955 vibeio::spawn(async move {
956 let _end = end_tx;
957 handle_request(
958 request_stream,
959 shared.clone(),
960 id,
961 request_fn,
962 date_cache,
963 send_continue_response,
964 send_date_header,
965 conn_state_for_task,
966 )
967 .await;
968 });
969 }
970 }
971 Poll::Ready(Ok(None)) => {
973 return Poll::Ready(Ok(()));
974 }
975 Poll::Ready(Err(err)) => {
976 return Poll::Ready(Err(h3_transport_error_to_io(err)));
977 }
978 Poll::Pending => {}
979 }
980
981 match ongoing.poll_next_unpin(cx) {
988 Poll::Ready(Some(Ok(()))) => continue,
989 Poll::Ready(Some(Err(_))) => continue,
990 Poll::Ready(None) => {}
991 Poll::Pending => {}
992 }
993 if ongoing.is_empty() && shutdown {
994 continue;
995 }
996
997 return Poll::Pending;
998 })
999 .await
1000 }
1001 }
1002}