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 time::Instant,
37};
38
39use bytes::Bytes;
40use futures_util::stream::FuturesUnordered;
41use futures_util::{ready, Future, FutureExt, StreamExt};
42use http::{Request, Response, StatusCode};
43use http_body::{Body, Frame as BodyFrame};
44use http_body_util::BodyExt;
45use tokio_util::sync::CancellationToken;
46
47use crate::{
48 h3::{
49 control::{ControlEvent, ControlStreams},
50 date::DateCache,
51 stream::{RequestStream, SharedCodecs, StreamError},
52 },
53 EarlyHints, HttpProtocol, Incoming, Upgrade, Upgraded,
54};
55
56const H3_NO_ERROR: u64 = 0x0100;
58const H3_REQUEST_REJECTED: u64 = 0x010b;
59
60#[derive(Debug, Clone, Copy)]
64pub(super) struct ResetLimits {
65 pub(super) max_local_error_resets: Option<usize>,
66 pub(super) max_pending_accept_resets: Option<usize>,
67}
68
69#[derive(Debug)]
72struct ConnResetState {
73 limits: ResetLimits,
74 local_error_resets: usize,
77 pending_accept_resets: usize,
81 close_code: Option<u64>,
84}
85
86impl ConnResetState {
87 #[inline]
90 fn note_local_error_reset(&mut self) -> Option<u64> {
91 match self.limits.max_local_error_resets {
92 Some(max) if self.local_error_resets >= max => Some(H3Error::ExcessiveLoad.code()),
93 _ => {
94 self.local_error_resets += 1;
95 None
96 }
97 }
98 }
99
100 #[inline]
103 fn note_pending_accept_reset(&mut self) -> Option<u64> {
104 match self.limits.max_pending_accept_resets {
105 Some(max) if self.pending_accept_resets >= max => Some(H3Error::ExcessiveLoad.code()),
106 _ => {
107 self.pending_accept_resets += 1;
108 None
109 }
110 }
111 }
112}
113
114type SharedRequest = Arc<tokio::sync::Mutex<RequestStream>>;
117
118static HTTP3_INVALID_HEADERS: [http::header::HeaderName; 5] = [
119 http::header::HeaderName::from_static("keep-alive"),
120 http::header::HeaderName::from_static("proxy-connection"),
121 http::header::CONNECTION,
122 http::header::TRANSFER_ENCODING,
123 http::header::UPGRADE,
124];
125
126pub(crate) struct H3Body {
128 stream: SharedRequest,
129 data_done: bool,
130 send_continue_body: Option<Arc<AtomicBool>>,
131}
132
133impl H3Body {
134 #[inline]
135 fn new(stream: SharedRequest, send_continue_body: Option<Arc<AtomicBool>>) -> Self {
136 Self {
137 stream,
138 data_done: false,
139 send_continue_body,
140 }
141 }
142}
143
144impl Body for H3Body {
145 type Data = Bytes;
146 type Error = std::io::Error;
147
148 #[inline]
149 fn poll_frame(
150 self: Pin<&mut Self>,
151 cx: &mut Context<'_>,
152 ) -> Poll<Option<Result<BodyFrame<Self::Data>, Self::Error>>> {
153 let this = unsafe { self.get_unchecked_mut() };
155
156 if !this.data_done {
157 loop {
158 let mut stream = match std::pin::pin!(this.stream.lock()).poll_unpin(cx) {
159 Poll::Ready(stream) => stream,
160 Poll::Pending => return Poll::Pending,
161 };
162 match stream.poll_recv_data(cx) {
163 Poll::Ready(Ok(Some(data))) => {
164 if data.is_empty() {
165 continue;
166 }
167 return Poll::Ready(Some(Ok(BodyFrame::data(data))));
168 }
169 Poll::Ready(Ok(None)) => {
170 drop(stream);
171 this.data_done = true;
172 break;
173 }
174 Poll::Ready(Err(err)) => {
175 return Poll::Ready(Some(Err(h3_stream_error_to_io(err))));
176 }
177 Poll::Pending => {
178 if let Some(scb) = this.send_continue_body.as_ref() {
179 scb.store(true, std::sync::atomic::Ordering::Relaxed);
180 }
181 return Poll::Pending;
182 }
183 };
184 }
185 }
186
187 let mut stream = match std::pin::pin!(this.stream.lock()).poll_unpin(cx) {
188 Poll::Ready(stream) => stream,
189 Poll::Pending => {
190 if let Some(scb) = this.send_continue_body.as_ref() {
191 scb.store(true, std::sync::atomic::Ordering::Relaxed);
192 }
193 return Poll::Pending;
194 }
195 };
196 match stream.poll_recv_trailers(cx) {
197 Poll::Ready(Ok(Some(trailers))) => Poll::Ready(Some(Ok(BodyFrame::trailers(trailers)))),
198 Poll::Ready(Ok(None)) => Poll::Ready(None),
199 Poll::Ready(Err(err)) => Poll::Ready(Some(Err(h3_stream_error_to_io(err)))),
200 Poll::Pending => {
201 if let Some(scb) = this.send_continue_body.as_ref() {
202 scb.store(true, std::sync::atomic::Ordering::Relaxed);
203 }
204 Poll::Pending
205 }
206 }
207 }
208}
209
210#[inline]
211fn h3_control_error_to_io(error: control::ControlError) -> std::io::Error {
212 std::io::Error::other(error)
213}
214
215#[inline]
216fn h3_transport_error_to_io(error: TransportError) -> std::io::Error {
217 std::io::Error::other(error)
218}
219
220#[inline]
221fn h3_stream_error_to_io(error: stream::StreamError) -> std::io::Error {
222 std::io::Error::other(error)
223}
224
225#[inline]
226fn remove_invalid_http3_headers(headers: &mut http::HeaderMap) {
227 for header in &HTTP3_INVALID_HEADERS {
228 headers.remove(header);
229 }
230 if headers
231 .get(http::header::TE)
232 .is_some_and(|v| v != "trailers")
233 {
234 headers.remove(http::header::TE);
235 }
236}
237
238#[inline]
244async fn wait_for_encoder(shared: &Arc<SharedCodecs>, _stream_id: u64) {
245 loop {
246 if shared.encoder.lock().is_some() {
247 return;
248 }
249 shared.encoder_notify.notified().await;
250 }
251}
252
253#[inline]
255async fn send_interim_response(
256 stream: &SharedRequest,
257 status: StatusCode,
258) -> Result<(), std::io::Error> {
259 let mut guard = stream.lock().await;
260 std::future::poll_fn(|cx| guard.poll_send_response(cx, status, &http::HeaderMap::new()))
261 .await
262 .map_err(h3_stream_error_to_io)
263}
264
265#[inline]
268async fn send_response(
269 stream: &SharedRequest,
270 shared: &Arc<SharedCodecs>,
271 stream_id: u64,
272 status: StatusCode,
273 headers: &http::HeaderMap,
274) -> Result<(), std::io::Error> {
275 wait_for_encoder(shared, stream_id).await;
276 let mut guard = stream.lock().await;
277 let res = std::future::poll_fn(|cx| guard.poll_send_response(cx, status, headers))
278 .await
279 .map_err(h3_stream_error_to_io);
280 res
281}
282
283#[inline]
285async fn send_data(stream: &SharedRequest, data: Bytes) -> Result<(), std::io::Error> {
286 let mut guard = stream.lock().await;
287 std::future::poll_fn(|cx| guard.poll_send_data(cx, data.clone()))
288 .await
289 .map_err(h3_stream_error_to_io)
290}
291
292#[inline]
294async fn send_trailers(
295 stream: &SharedRequest,
296 trailers: &http::HeaderMap,
297) -> Result<(), std::io::Error> {
298 let mut guard = stream.lock().await;
299 std::future::poll_fn(|cx| guard.poll_send_trailers(cx, trailers))
300 .await
301 .map_err(h3_stream_error_to_io)
302}
303
304#[inline]
306async fn send_finish(stream: &SharedRequest) -> Result<(), std::io::Error> {
307 let mut guard = stream.lock().await;
308 let result = std::future::poll_fn(|cx| guard.poll_finish(cx))
309 .await
310 .map_err(h3_stream_error_to_io);
311 let result2 = std::future::poll_fn(|cx| guard.poll_stopped(cx))
312 .await
313 .map_err(h3_stream_error_to_io);
314 result.or(result2)
315}
316
317#[allow(clippy::type_complexity)]
323#[allow(clippy::too_many_arguments)]
324async fn handle_request<F, Fut, ResB, ResBE, ResE>(
325 stream: SharedRequest,
326 shared: Arc<SharedCodecs>,
327 stream_id: u64,
328 request_fn: Rc<F>,
329 date_cache: DateCache,
330 send_continue_response: bool,
331 send_date_header: bool,
332 conn_state: Arc<parking_lot::Mutex<ConnResetState>>,
333) where
334 F: Fn(Request<Incoming>) -> Fut,
335 Fut: std::future::Future<Output = Result<Response<ResB>, ResE>>,
336 ResB: Body<Data = Bytes, Error = ResBE> + Unpin,
337 ResE: std::error::Error,
338 ResBE: std::error::Error,
339{
340 let request_headers = {
342 let mut guard = stream.lock().await;
343 std::future::poll_fn(|cx| guard.poll_headers(cx)).await
344 };
345 let request = match request_headers {
346 Ok(Some(request)) => request,
347 Ok(None) => return,
349 Err(err) => {
350 if err.is_stream_scoped() {
355 let mut state = conn_state.lock();
356 if let Some(code) = state.note_pending_accept_reset() {
357 state.close_code = Some(code);
358 }
359 return;
360 }
361 if matches!(err, StreamError::Message) {
365 let mut guard = stream.lock().await;
366 let code = err.h3_code();
367 let _ = std::future::poll_fn(|cx| guard.poll_reset(cx, code)).await;
368 let _ = std::future::poll_fn(|cx| guard.poll_stop_sending(cx, code)).await;
369 drop(guard);
370 let mut state = conn_state.lock();
371 if let Some(code) = state.note_local_error_reset() {
372 state.close_code = Some(code);
373 }
374 return;
375 }
376 conn_state.lock().close_code = Some(err.h3_code());
380 return;
381 }
382 };
383
384 let is_100_continue = send_continue_response
386 && request
387 .headers()
388 .get(http::header::EXPECT)
389 .and_then(|v| v.to_str().ok())
390 .is_some_and(|v| v.eq_ignore_ascii_case("100-continue"));
391
392 let send_continue_body = is_100_continue.then(|| Arc::new(AtomicBool::new(false)));
393 let (request_parts, _) = request.into_parts();
394 let (request_body, upgrade) = if request_parts.method == http::Method::CONNECT {
395 (Incoming::Empty, Some(stream.clone()))
396 } else {
397 (
398 Incoming::Boxed(Box::pin(H3Body::new(
399 stream.clone(),
400 send_continue_body.clone(),
401 ))),
402 None,
403 )
404 };
405 let mut request = Request::from_parts(request_parts, request_body);
406
407 let (early_hints, mut early_hints_rx) = EarlyHints::new_lazy();
409 request.extensions_mut().insert(early_hints);
410
411 let upgrade = if let Some(recv_stream) = upgrade {
413 let (upgrade_tx, upgrade_rx) = oneshot::async_channel();
414 let upgrade = Upgrade::new(upgrade_rx);
415 let upgraded = upgrade.upgraded.clone();
416 request.extensions_mut().insert(upgrade);
417 Some((upgrade_tx, upgraded, recv_stream))
418 } else {
419 None
420 };
421
422 let mut response_fut = std::pin::pin!(request_fn(request));
423 let mut early_hints_open = true;
424 let mut continue_sent = false;
425 let response_result = loop {
426 if !early_hints_open {
427 break response_fut.as_mut().await;
428 }
429
430 let next = std::future::poll_fn(|cx| {
431 if let Poll::Ready(res) = response_fut.as_mut().poll(cx) {
432 return Poll::Ready(Some(futures_util::future::Either::Left(res)));
433 }
434
435 match early_hints_rx.poll_recv(cx) {
436 Poll::Ready(Some(msg)) => {
437 return Poll::Ready(Some(futures_util::future::Either::Right(Ok(msg))))
438 }
439 Poll::Ready(None) => {
440 return Poll::Ready(Some(futures_util::future::Either::Right(Err(()))))
441 }
442 Poll::Pending => {}
443 }
444
445 if !continue_sent
446 && is_100_continue
447 && send_continue_body
448 .as_ref()
449 .is_some_and(|b| b.load(Ordering::Relaxed))
450 {
451 continue_sent = true;
452 return Poll::Ready(None);
453 }
454
455 Poll::Pending
456 })
457 .await;
458
459 match next {
460 Some(futures_util::future::Either::Left(response_result)) => {
462 break response_result;
463 }
464 Some(futures_util::future::Either::Right(Ok((headers, sender)))) => {
466 sender
467 .into_inner()
468 .send(
469 send_response(
470 &stream,
471 &shared,
472 stream_id,
473 StatusCode::EARLY_HINTS,
474 &headers,
475 )
476 .await,
477 )
478 .ok();
479 }
480 Some(futures_util::future::Either::Right(Err(()))) => {
481 early_hints_open = false;
482 }
483 None => {
485 if send_interim_response(&stream, StatusCode::CONTINUE)
486 .await
487 .is_err()
488 {
489 return;
490 }
491 }
492 }
493 };
494
495 let Ok(mut response) = response_result else {
496 return;
498 };
499
500 {
501 let response_headers = response.headers_mut();
502 if send_date_header {
503 if let Some(http_date) = date_cache.get_date_header_value() {
504 response_headers
505 .entry(http::header::DATE)
506 .or_insert(http_date);
507 }
508 }
509 remove_invalid_http3_headers(response_headers);
510 }
511
512 let response_is_end_stream = response.body().is_end_stream();
513 if !response_is_end_stream {
514 if let Some(content_length) = response.body().size_hint().exact() {
515 if !response
516 .headers()
517 .contains_key(http::header::CONTENT_LENGTH)
518 {
519 response
520 .headers_mut()
521 .insert(http::header::CONTENT_LENGTH, content_length.into());
522 }
523 }
524 }
525
526 if is_100_continue
527 && !continue_sent
528 && !response.status().is_client_error()
529 && !response.status().is_server_error()
530 && send_interim_response(&stream, StatusCode::CONTINUE)
531 .await
532 .is_err()
533 {
534 return;
535 }
536
537 let (response_parts, mut response_body) = response.into_parts();
538 if send_response(
539 &stream,
540 &shared,
541 stream_id,
542 response_parts.status,
543 &response_parts.headers,
544 )
545 .await
546 .is_err()
547 {
548 return;
549 }
550
551 if let Some((upgrade_tx, upgraded, recv_stream)) = upgrade {
552 if upgraded.load(Ordering::Relaxed) {
553 let (upgraded, task) = self::upgrade::pair(recv_stream);
554 let _ = upgrade_tx.send(Upgraded::new(upgraded, None));
555 task.await;
556 return;
557 }
558 }
559
560 if !response_is_end_stream {
561 while let Some(chunk) = response_body.frame().await {
562 match chunk {
563 Ok(frame) => {
564 if frame.is_data() {
565 match frame.into_data() {
566 Ok(data) => {
567 if data.is_empty() {
568 continue;
570 }
571 if send_data(&stream, data).await.is_err() {
572 return;
573 }
574 }
575 Err(_) => {
576 return;
577 }
578 }
579 } else if frame.is_trailers() {
580 match frame.into_trailers() {
581 Ok(mut trailers) => {
582 remove_invalid_http3_headers(&mut trailers);
583 if send_trailers(&stream, &trailers).await.is_err() {
584 return;
585 }
586 break;
587 }
588 Err(_) => {
589 return;
590 }
591 }
592 }
593 }
594 Err(_) => {
595 return;
596 }
597 }
598 }
599 }
600
601 let _ = send_finish(&stream).await;
602}
603
604pub struct Http3<Io> {
627 io_to_handshake: Option<Io>,
628 date_header_value_cached: DateCache,
629 options: Http3Options,
630 cancel_token: Option<CancellationToken>,
631}
632
633impl<Io> Http3<Io>
634where
635 Io: transport::Connection + Unpin + 'static,
636{
637 #[inline]
650 pub fn new(io: Io, options: Http3Options) -> Self {
651 Self {
652 io_to_handshake: Some(io),
653 date_header_value_cached: DateCache::default(),
654 options,
655 cancel_token: None,
656 }
657 }
658
659 #[inline]
665 pub fn graceful_shutdown_token(mut self, token: CancellationToken) -> Self {
666 self.cancel_token = Some(token);
667 self
668 }
669}
670
671impl<Io> HttpProtocol for Http3<Io>
672where
673 Io: transport::Connection + Unpin + 'static,
674{
675 #[allow(clippy::manual_async_fn)]
676 #[inline]
677 fn handle<F, Fut, ResB, ResBE, ResE>(
678 self,
679 request_fn: F,
680 ) -> impl std::future::Future<Output = Result<(), std::io::Error>>
681 where
682 F: Fn(Request<super::Incoming>) -> Fut + 'static,
683 Fut: std::future::Future<Output = Result<Response<ResB>, ResE>> + 'static,
684 ResB: http_body::Body<Data = bytes::Bytes, Error = ResBE> + Unpin + 'static,
685 ResE: std::error::Error + 'static,
686 ResBE: std::error::Error + 'static,
687 {
688 async move {
689 let request_fn = Rc::new(request_fn);
690 let Http3 {
691 mut io_to_handshake,
692 date_header_value_cached,
693 options,
694 cancel_token,
695 } = self;
696 let mut conn = io_to_handshake
697 .take()
698 .ok_or_else(|| std::io::Error::other("no io to handshake"))?;
699 let date_cache = date_header_value_cached;
700 let send_continue_response = options.send_continue_response;
701 let send_date_header = options.send_date_header;
702
703 if let Some(timeout) = options.handshake_timeout {
707 zincio::time::timeout(timeout, async {
708 while !conn.is_handshake_complete() {
709 zincio::time::sleep(std::time::Duration::from_millis(1)).await;
710 }
711 })
712 .await
713 .map_err(|_| {
714 std::io::Error::new(std::io::ErrorKind::TimedOut, "handshake timeout")
715 })?;
716 } else {
717 while !conn.is_handshake_complete() {
718 zincio::time::sleep(std::time::Duration::from_millis(1)).await;
719 }
720 }
721
722 let mut controls = ControlStreams::new(options.local_settings.clone());
723 let shared = controls.shared().clone();
724 let conn_state: Arc<parking_lot::Mutex<ConnResetState>> =
729 Arc::new(parking_lot::Mutex::new(ConnResetState {
730 limits: ResetLimits {
731 max_local_error_resets: options.max_local_error_reset_streams,
732 max_pending_accept_resets: options.max_pending_accept_reset_streams,
733 },
734 local_error_resets: 0,
735 pending_accept_resets: 0,
736 close_code: None,
737 }));
738 let mut ongoing: FuturesUnordered<oneshot::AsyncReceiver<()>> = FuturesUnordered::new();
739 let mut cancel_fut: Option<Pin<Box<dyn std::future::Future<Output = ()> + Send>>> =
740 None;
741 if let Some(token) = cancel_token.as_ref() {
742 cancel_fut = Some(Box::pin(token.cancelled()));
743 }
744 let mut accept_sleep: Option<zincio::time::Sleep> = None;
745 let mut shutdown_sleep: Option<zincio::time::Sleep> = None;
746 let mut drain_grace: Option<zincio::time::Sleep> = None;
754 let mut shutdown = false;
755 let mut control_dead = false;
756 let mut closing_with: Option<u64> = None;
760 let mut outcome: Option<Result<(), std::io::Error>> = None;
761 let mut last_request_id = 0u64;
762
763 std::future::poll_fn(|cx| -> Poll<Result<(), std::io::Error>> {
766 ready!(controls
767 .poll_init(&mut conn, cx)
768 .map_err(h3_control_error_to_io))?;
769 ready!(controls.poll_flush(cx).map_err(h3_control_error_to_io))?;
770 Poll::Ready(Ok(()))
771 })
772 .await?;
773
774 std::future::poll_fn(|cx| loop {
775 if let Some(code) = conn_state.lock().close_code.take() {
778 if closing_with.is_none() {
779 closing_with = Some(code);
780 shutdown = true;
781 control_dead = true;
782 }
783 }
784
785 let mut timeout_fired = false;
788 if let Some(sleep) = accept_sleep.as_mut() {
789 if let Poll::Ready(()) = Pin::new(&mut *sleep).poll(cx) {
790 accept_sleep = None;
791 timeout_fired = true;
792 }
793 } else if let Some(accept_timeout) = options.accept_timeout {
794 accept_sleep = Some(zincio::time::sleep(accept_timeout));
795 continue;
796 }
797
798 if let Some(sleep) = shutdown_sleep.as_mut() {
802 if let Poll::Ready(()) = Pin::new(&mut *sleep).poll(cx) {
803 sleep.reset(Instant::now() + std::time::Duration::from_millis(10));
804 }
805 }
806
807 let mut cancel_fired = false;
809 if let Some(fut) = cancel_fut.as_mut() {
810 if let Poll::Ready(()) = fut.as_mut().poll(cx) {
811 cancel_fired = true;
812 }
813 }
814 if !shutdown {
815 if cancel_fired {
816 shutdown = true;
817 outcome = Some(Ok(()));
818 } else if timeout_fired {
819 shutdown = true;
820 outcome = Some(Err(std::io::Error::new(
821 std::io::ErrorKind::TimedOut,
822 "accept timeout",
823 )));
824 }
825 }
826
827 controls.queue_encoder_streams_from_shared(&shared);
830
831 if !control_dead {
840 match controls.poll_flush(cx) {
841 Poll::Ready(Ok(())) => {}
842 Poll::Ready(Err(err)) => {
843 if shutdown {
844 control_dead = true;
845 } else {
846 closing_with = Some(err.h3_code());
847 shutdown = true;
848 control_dead = true;
849 }
850 }
851 Poll::Pending => {}
852 }
853 }
854
855 if !control_dead {
857 loop {
858 match controls.poll_read(&mut conn, cx) {
859 Poll::Ready(Ok(Some(ControlEvent::Goaway { .. }))) => {
860 if !shutdown {
864 shutdown = true;
865 outcome = Some(Ok(()));
866 }
867 }
868 Poll::Ready(Ok(Some(_))) => {}
869 Poll::Ready(Ok(None)) => {}
870 Poll::Ready(Err(err)) => {
871 if shutdown {
872 control_dead = true;
873 break;
874 }
875 closing_with = Some(err.h3_code());
876 shutdown = true;
877 control_dead = true;
878 break;
879 }
880 Poll::Pending => break,
881 }
882 }
883 }
884
885 if shutdown {
889 if let Some(code) = closing_with {
890 ready!(conn
891 .poll_shutdown(cx, code)
892 .map_err(h3_transport_error_to_io))?;
893 return Poll::Ready(outcome.take().unwrap_or(Ok(())));
894 }
895 if controls.goaway_sent().is_none() {
896 controls.send_goaway(last_request_id);
897 }
898 if ongoing.is_empty() {
899 if let Some(grace) = drain_grace.as_mut() {
903 if Pin::new(&mut *grace).poll(cx).is_ready() {
904 ready!(conn
905 .poll_shutdown(cx, H3_NO_ERROR)
906 .map_err(h3_transport_error_to_io))?;
907 return Poll::Ready(outcome.take().unwrap_or(Ok(())));
908 }
909 } else {
910 drain_grace =
911 Some(zincio::time::sleep(std::time::Duration::from_millis(50)));
912 }
913 } else if shutdown_sleep.is_none() {
914 shutdown_sleep =
915 Some(zincio::time::sleep(std::time::Duration::from_millis(10)));
916 }
917 }
918
919 loop {
921 match conn.poll_accept(cx) {
922 Poll::Ready(Ok(Some(stream))) => {
923 let id = stream.id();
924 last_request_id = last_request_id.max(id);
925 if let Some(sleep) = accept_sleep.as_mut() {
926 if let Some(timeout) = options.accept_timeout {
927 sleep.reset(Instant::now() + timeout);
928 } else {
929 accept_sleep = None;
930 }
931 } else {
932 accept_sleep = None;
933 }
934 if shutdown
935 && (controls.goaway_sent().is_none()
936 || id > controls.goaway_sent().unwrap_or(u64::MAX))
937 {
938 let mut rejected = RequestStream::new(stream, shared.clone());
941 let _ = rejected.poll_reset(cx, H3_REQUEST_REJECTED);
942 } else {
943 let (end_tx, end_rx) = oneshot::async_channel();
944 ongoing.push(end_rx);
945 let request_stream = Arc::new(tokio::sync::Mutex::new(
946 RequestStream::new(stream, shared.clone()),
947 ));
948 let request_fn = request_fn.clone();
949 let date_cache = date_cache.clone();
950 let shared = shared.clone();
951 let conn_state_for_task = conn_state.clone();
952 zincio::spawn(async move {
953 let _end = end_tx;
954 handle_request(
955 request_stream,
956 shared.clone(),
957 id,
958 request_fn,
959 date_cache,
960 send_continue_response,
961 send_date_header,
962 conn_state_for_task,
963 )
964 .await;
965 });
966 }
967 }
968 Poll::Ready(Ok(None)) => {
970 return Poll::Ready(Ok(()));
971 }
972 Poll::Ready(Err(err)) => {
973 return Poll::Ready(Err(h3_transport_error_to_io(err)));
974 }
975 Poll::Pending => {
976 break;
977 }
978 }
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}