Skip to main content

actix_http/h1/
dispatcher.rs

1use std::{
2    collections::VecDeque,
3    fmt,
4    future::Future,
5    io, mem, net,
6    pin::Pin,
7    rc::Rc,
8    task::{Context, Poll},
9};
10
11use actix_codec::{Framed, FramedParts};
12use actix_service::Service;
13use bitflags::bitflags;
14use bytes::{Buf, BytesMut};
15use futures_core::ready;
16use pin_project_lite::pin_project;
17use tokio::{
18    io::{AsyncRead, AsyncWrite},
19    time::sleep_until,
20};
21use tokio_util::codec::{Decoder as _, Encoder as _};
22use tracing::{error, trace};
23
24use super::{
25    codec::Codec,
26    decoder::MAX_BUFFER_SIZE,
27    payload::{Payload, PayloadSender, PayloadStatus},
28    timer::TimerState,
29    Message, MessageType,
30};
31use crate::{
32    body::{BodySize, BoxBody, MessageBody},
33    config::ServiceConfig,
34    error::{DispatchError, ParseError, PayloadError},
35    service::HttpFlow,
36    ConnectionType, Error, Extensions, HttpMessage, OnConnectData, Request, Response, StatusCode,
37};
38
39const LW_BUFFER_SIZE: usize = 1024;
40const HW_BUFFER_SIZE: usize = 1024 * 8;
41const MAX_PIPELINED_MESSAGES: usize = 16;
42
43/// Write buffer capacity at which we reallocate it after flushing.
44const WRITE_BUFFER_RETENTION_LIMIT: usize = 1024 * 128;
45
46bitflags! {
47    #[derive(Debug, Clone, Copy)]
48    pub struct Flags: u8 {
49        /// Set when stream is read for first time.
50        const STARTED          = 0b0000_0001;
51
52        /// Set when full request-response cycle has occurred.
53        const FINISHED         = 0b0000_0010;
54
55        /// Set if connection is in keep-alive (inactive) state.
56        const KEEP_ALIVE       = 0b0000_0100;
57
58        /// Set if in shutdown procedure.
59        const SHUTDOWN         = 0b0000_1000;
60
61        /// Set if read-half is disconnected.
62        const READ_DISCONNECT  = 0b0001_0000;
63
64        /// Set if write-half is disconnected.
65        const WRITE_DISCONNECT = 0b0010_0000;
66
67        /// Set while gracefully closing a connection after an early response.
68        const LINGER           = 0b0100_0000;
69
70        /// Set when the server is draining this connection during graceful shutdown.
71        ///
72        /// Unlike [`SHUTDOWN`](Self::SHUTDOWN), this state continues polling the current request
73        /// and response. It prevents queued requests from starting and transitions to `SHUTDOWN`
74        /// after the current response finishes. [`LINGER`](Self::LINGER) remains separate and is
75        /// used only to close cleanly after a response to an unread request payload.
76        const DRAINING         = 0b1000_0000;
77    }
78}
79
80// there's 2 versions of Dispatcher state because of:
81// https://github.com/taiki-e/pin-project-lite/issues/3
82//
83// tl;dr: pin-project-lite doesn't play well with other attribute macros
84
85#[cfg(not(test))]
86pin_project! {
87    /// Dispatcher for HTTP/1.1 protocol
88    pub struct Dispatcher<T, S, B, X, U>
89    where
90        S: Service<Request>,
91        S::Error: Into<Response<BoxBody>>,
92
93        B: MessageBody,
94
95        X: Service<Request, Response = Request>,
96        X::Error: Into<Response<BoxBody>>,
97
98        U: Service<(Request, Framed<T, Codec>), Response = ()>,
99        U::Error: fmt::Display,
100    {
101        #[pin]
102        inner: DispatcherState<T, S, B, X, U>,
103    }
104}
105
106#[cfg(test)]
107pin_project! {
108    /// Dispatcher for HTTP/1.1 protocol
109    pub struct Dispatcher<T, S, B, X, U>
110    where
111        S: Service<Request>,
112        S::Error: Into<Response<BoxBody>>,
113
114        B: MessageBody,
115
116        X: Service<Request, Response = Request>,
117        X::Error: Into<Response<BoxBody>>,
118
119        U: Service<(Request, Framed<T, Codec>), Response = ()>,
120        U::Error: fmt::Display,
121    {
122        #[pin]
123        pub(super) inner: DispatcherState<T, S, B, X, U>,
124
125        // used in tests
126        pub(super) poll_count: u64,
127    }
128}
129
130pin_project! {
131    #[project = DispatcherStateProj]
132    pub(super) enum DispatcherState<T, S, B, X, U>
133    where
134        S: Service<Request>,
135        S::Error: Into<Response<BoxBody>>,
136
137        B: MessageBody,
138
139        X: Service<Request, Response = Request>,
140        X::Error: Into<Response<BoxBody>>,
141
142        U: Service<(Request, Framed<T, Codec>), Response = ()>,
143        U::Error: fmt::Display,
144    {
145        Normal { #[pin] inner: InnerDispatcher<T, S, B, X, U> },
146        Upgrade { #[pin] fut: U::Future },
147    }
148}
149
150pin_project! {
151    #[project = InnerDispatcherProj]
152    pub(super) struct InnerDispatcher<T, S, B, X, U>
153    where
154        S: Service<Request>,
155        S::Error: Into<Response<BoxBody>>,
156
157        B: MessageBody,
158
159        X: Service<Request, Response = Request>,
160        X::Error: Into<Response<BoxBody>>,
161
162        U: Service<(Request, Framed<T, Codec>), Response = ()>,
163        U::Error: fmt::Display,
164    {
165        flow: Rc<HttpFlow<S, X, U>>,
166        pub(super) flags: Flags,
167        peer_addr: Option<net::SocketAddr>,
168        conn_data: Option<Rc<Extensions>>,
169        config: ServiceConfig,
170        error: Option<DispatchError>,
171
172        #[pin]
173        pub(super) state: State<S, B, X>,
174        // when Some(_) dispatcher is in state of receiving request payload
175        payload: Option<PayloadSender>,
176        // true when current request uses chunked transfer encoding (drainable when payload is dropped)
177        payload_drainable: bool,
178        messages: VecDeque<DispatcherMessage>,
179
180        head_timer: TimerState,
181        ka_timer: TimerState,
182        shutdown_timer: TimerState,
183        graceful_shutdown: Option<crate::config::GracefulShutdownFuture>,
184
185        pub(super) io: Option<T>,
186        read_buf: BytesMut,
187        write_buf: BytesMut,
188
189        // Number of bytes to busy-buffer before flushing.
190        h1_write_buffer_size: usize,
191
192        // True if backing allocation of `write_buf` needs to be released.
193        write_buf_needs_reset: bool,
194
195        codec: Codec,
196    }
197}
198
199enum DispatcherMessage {
200    Item(Request),
201    Upgrade(Request),
202    Error(Response<()>),
203}
204
205pin_project! {
206    #[project = StateProj]
207    pub(super) enum State<S, B, X>
208    where
209        S: Service<Request>,
210        X: Service<Request, Response = Request>,
211        B: MessageBody,
212    {
213        None,
214        ExpectCall { #[pin] fut: X::Future },
215        ServiceCall { #[pin] fut: S::Future },
216        SendPayload { #[pin] body: B },
217        SendErrorPayload { #[pin] body: BoxBody },
218    }
219}
220
221impl<S, B, X> State<S, B, X>
222where
223    S: Service<Request>,
224    X: Service<Request, Response = Request>,
225    B: MessageBody,
226{
227    pub(super) fn is_none(&self) -> bool {
228        matches!(self, State::None)
229    }
230}
231
232impl<S, B, X> fmt::Debug for State<S, B, X>
233where
234    S: Service<Request>,
235    X: Service<Request, Response = Request>,
236    B: MessageBody,
237{
238    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
239        match self {
240            Self::None => write!(f, "State::None"),
241            Self::ExpectCall { .. } => f.debug_struct("State::ExpectCall").finish_non_exhaustive(),
242            Self::ServiceCall { .. } => {
243                f.debug_struct("State::ServiceCall").finish_non_exhaustive()
244            }
245            Self::SendPayload { .. } => {
246                f.debug_struct("State::SendPayload").finish_non_exhaustive()
247            }
248            Self::SendErrorPayload { .. } => f
249                .debug_struct("State::SendErrorPayload")
250                .finish_non_exhaustive(),
251        }
252    }
253}
254
255#[derive(Debug)]
256enum PollResponse {
257    Upgrade(Request),
258    DoNothing,
259    DrainWriteBuf,
260}
261
262impl<T, S, B, X, U> Dispatcher<T, S, B, X, U>
263where
264    T: AsyncRead + AsyncWrite + Unpin,
265
266    S: Service<Request>,
267    S::Error: Into<Response<BoxBody>>,
268    S::Response: Into<Response<B>>,
269
270    B: MessageBody,
271
272    X: Service<Request, Response = Request>,
273    X::Error: Into<Response<BoxBody>>,
274
275    U: Service<(Request, Framed<T, Codec>), Response = ()>,
276    U::Error: fmt::Display,
277{
278    /// Create HTTP/1 dispatcher.
279    pub(crate) fn new(
280        io: T,
281        flow: Rc<HttpFlow<S, X, U>>,
282        config: ServiceConfig,
283        peer_addr: Option<net::SocketAddr>,
284        conn_data: OnConnectData,
285    ) -> Self {
286        Dispatcher {
287            inner: DispatcherState::Normal {
288                inner: InnerDispatcher {
289                    flow,
290                    flags: Flags::empty(),
291                    peer_addr,
292                    conn_data: conn_data.0.map(Rc::new),
293                    config: config.clone(),
294                    error: None,
295
296                    state: State::None,
297                    payload: None,
298                    payload_drainable: false,
299                    messages: VecDeque::new(),
300
301                    head_timer: TimerState::new(config.client_request_deadline().is_some()),
302                    ka_timer: TimerState::new(config.keep_alive().enabled()),
303                    shutdown_timer: TimerState::new(config.client_disconnect_deadline().is_some()),
304                    graceful_shutdown: config.graceful_shutdown(),
305
306                    io: Some(io),
307                    read_buf: BytesMut::with_capacity(HW_BUFFER_SIZE),
308                    write_buf: BytesMut::with_capacity(HW_BUFFER_SIZE),
309                    h1_write_buffer_size: config.h1_write_buffer_size(),
310                    write_buf_needs_reset: false,
311                    codec: Codec::new(config),
312                },
313            },
314
315            #[cfg(test)]
316            poll_count: 0,
317        }
318    }
319}
320
321impl<T, S, B, X, U> InnerDispatcher<T, S, B, X, U>
322where
323    T: AsyncRead + AsyncWrite + Unpin,
324
325    S: Service<Request>,
326    S::Error: Into<Response<BoxBody>>,
327    S::Response: Into<Response<B>>,
328
329    B: MessageBody,
330
331    X: Service<Request, Response = Request>,
332    X::Error: Into<Response<BoxBody>>,
333
334    U: Service<(Request, Framed<T, Codec>), Response = ()>,
335    U::Error: fmt::Display,
336{
337    fn can_read(&self, cx: &mut Context<'_>) -> bool {
338        if self.flags.contains(Flags::READ_DISCONNECT) {
339            false
340        } else if let Some(ref info) = self.payload {
341            matches!(
342                info.need_read(cx),
343                PayloadStatus::Read | PayloadStatus::Dropped
344            )
345        } else {
346            true
347        }
348    }
349
350    fn client_disconnected(self: Pin<&mut Self>) {
351        let this = self.project();
352
353        this.flags
354            .insert(Flags::READ_DISCONNECT | Flags::WRITE_DISCONNECT);
355
356        if let Some(mut payload) = this.payload.take() {
357            payload.set_error(PayloadError::Incomplete(None));
358        }
359    }
360
361    fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), io::Error>> {
362        let InnerDispatcherProj {
363            io,
364            write_buf,
365            h1_write_buffer_size,
366            write_buf_needs_reset,
367            ..
368        } = self.project();
369        let mut io = Pin::new(io.as_mut().unwrap());
370
371        // Allow normal buffer growth, but do not retain allocations caused by large response
372        // chunks on idle connections.
373        let retention_limit = (*h1_write_buffer_size).max(WRITE_BUFFER_RETENTION_LIMIT);
374
375        if write_buf.capacity() > retention_limit {
376            // Needs stored flag because `write_buf.advance(n)` reduces reported capacity without
377            // releasing the backing allocation.
378            *write_buf_needs_reset = true;
379        }
380
381        let len = write_buf.len();
382        let mut written = 0;
383
384        while written < len {
385            match io.as_mut().poll_write(cx, &write_buf[written..])? {
386                Poll::Ready(0) => {
387                    error!("write zero; closing");
388                    return Poll::Ready(Err(io::Error::new(io::ErrorKind::WriteZero, "")));
389                }
390
391                Poll::Ready(n) => written += n,
392
393                Poll::Pending => {
394                    write_buf.advance(written);
395                    return Poll::Pending;
396                }
397            }
398        }
399
400        // All bytes have been accepted by the I/O stream, so the buffer can be reused or released.
401        if *write_buf_needs_reset {
402            *write_buf = BytesMut::with_capacity(HW_BUFFER_SIZE);
403            *write_buf_needs_reset = false;
404        } else {
405            write_buf.clear();
406        }
407
408        // flush the I/O and check if get blocked
409        io.poll_flush(cx)
410    }
411
412    fn enter_linger(flags: &mut Flags) {
413        flags.remove(Flags::KEEP_ALIVE);
414        flags.insert(Flags::LINGER | Flags::FINISHED);
415    }
416
417    fn ensure_linger_timer(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> bool {
418        let this = self.as_mut().project();
419
420        if matches!(this.shutdown_timer, TimerState::Active { .. }) {
421            return true;
422        }
423
424        if let Some(deadline) = this.config.client_disconnect_deadline() {
425            this.shutdown_timer
426                .set_and_init(cx, sleep_until(deadline.into()), line!());
427            true
428        } else {
429            false
430        }
431    }
432
433    fn poll_linger(
434        mut self: Pin<&mut Self>,
435        cx: &mut Context<'_>,
436    ) -> Result<Poll<()>, DispatchError> {
437        if self.as_mut().poll_flush(cx)?.is_pending() {
438            return Ok(Poll::Pending);
439        }
440
441        if !self.as_mut().ensure_linger_timer(cx) {
442            let this = self.as_mut().project();
443            this.flags.remove(Flags::LINGER);
444            this.flags.insert(Flags::SHUTDOWN);
445            return Ok(Poll::Ready(()));
446        }
447
448        loop {
449            let should_disconnect = self.as_mut().read_available(cx)?;
450            let this = self.as_mut().project();
451            let mut progressed = false;
452
453            if !this.read_buf.is_empty() {
454                this.read_buf.clear();
455                progressed = true;
456            }
457
458            if should_disconnect {
459                this.flags.remove(Flags::LINGER);
460                this.flags.insert(Flags::READ_DISCONNECT | Flags::SHUTDOWN);
461                return Ok(Poll::Ready(()));
462            }
463
464            if !progressed {
465                return Ok(Poll::Pending);
466            }
467        }
468    }
469
470    fn send_response_inner(
471        self: Pin<&mut Self>,
472        res: Response<()>,
473        body: &impl MessageBody,
474    ) -> Result<BodySize, DispatchError> {
475        let this = self.project();
476
477        let size = body.size();
478
479        this.codec
480            .encode(Message::Item((res, size)), this.write_buf)
481            .map_err(|err| {
482                if let Some(mut payload) = this.payload.take() {
483                    payload.set_error(PayloadError::Incomplete(None));
484                }
485
486                DispatchError::Io(err)
487            })?;
488
489        Ok(size)
490    }
491
492    fn send_response(
493        mut self: Pin<&mut Self>,
494        mut res: Response<()>,
495        body: B,
496    ) -> Result<(), DispatchError> {
497        let is_upgrade = res.upgrade();
498        let (draining, close_for_unread_payload) = {
499            let this = self.as_mut().project();
500            (
501                this.flags.contains(Flags::DRAINING),
502                !is_upgrade
503                    && should_close_for_unread_payload(
504                        this.payload.as_ref(),
505                        *this.payload_drainable,
506                    ),
507            )
508        };
509        let close_after_response = (!is_upgrade && draining) || close_for_unread_payload;
510
511        if close_after_response {
512            res.head_mut().set_connection_type(ConnectionType::Close);
513        }
514
515        let size = self.as_mut().send_response_inner(res, &body)?;
516        match size {
517            BodySize::None | BodySize::Sized(0) => {
518                let mut this = self.as_mut().project();
519
520                if close_for_unread_payload {
521                    if this.config.client_disconnect_deadline().is_some() {
522                        Self::enter_linger(this.flags);
523                    } else {
524                        this.flags.insert(Flags::SHUTDOWN | Flags::FINISHED);
525                    }
526                } else {
527                    this.flags.insert(Flags::FINISHED);
528                }
529
530                this.state.set(State::None);
531            }
532            _ => self
533                .as_mut()
534                .project()
535                .state
536                .set(State::SendPayload { body }),
537        }
538
539        Ok(())
540    }
541
542    fn send_error_response(
543        mut self: Pin<&mut Self>,
544        mut res: Response<()>,
545        body: BoxBody,
546    ) -> Result<(), DispatchError> {
547        let is_upgrade = res.upgrade();
548        let (draining, close_for_unread_payload) = {
549            let this = self.as_mut().project();
550            (
551                this.flags.contains(Flags::DRAINING),
552                !is_upgrade
553                    && should_close_for_unread_payload(
554                        this.payload.as_ref(),
555                        *this.payload_drainable,
556                    ),
557            )
558        };
559        let close_after_response = (!is_upgrade && draining) || close_for_unread_payload;
560
561        if close_after_response {
562            res.head_mut().set_connection_type(ConnectionType::Close);
563        }
564
565        let size = self.as_mut().send_response_inner(res, &body)?;
566        match size {
567            BodySize::None | BodySize::Sized(0) => {
568                let mut this = self.as_mut().project();
569
570                if close_for_unread_payload {
571                    if this.config.client_disconnect_deadline().is_some() {
572                        Self::enter_linger(this.flags);
573                    } else {
574                        this.flags.insert(Flags::SHUTDOWN | Flags::FINISHED);
575                    }
576                } else {
577                    this.flags.insert(Flags::FINISHED);
578                }
579
580                this.state.set(State::None);
581            }
582            _ => self
583                .as_mut()
584                .project()
585                .state
586                .set(State::SendErrorPayload { body }),
587        }
588
589        Ok(())
590    }
591
592    fn send_continue(self: Pin<&mut Self>) {
593        self.project()
594            .write_buf
595            .extend_from_slice(b"HTTP/1.1 100 Continue\r\n\r\n");
596    }
597
598    fn poll_response(
599        mut self: Pin<&mut Self>,
600        cx: &mut Context<'_>,
601    ) -> Result<PollResponse, DispatchError> {
602        'res: loop {
603            let mut this = self.as_mut().project();
604            match this.state.as_mut().project() {
605                StateProj::None if this.flags.contains(Flags::DRAINING) => {
606                    this.messages.clear();
607                    this.flags.remove(Flags::KEEP_ALIVE);
608
609                    if !this.flags.contains(Flags::LINGER) {
610                        this.flags.insert(Flags::SHUTDOWN);
611                    }
612
613                    return Ok(PollResponse::DoNothing);
614                }
615
616                // no future is in InnerDispatcher state; pop next message
617                StateProj::None => match this.messages.pop_front() {
618                    // handle request message
619                    Some(DispatcherMessage::Item(req)) => {
620                        // Handle `EXPECT: 100-Continue` header
621                        if req.head().expect() {
622                            // set InnerDispatcher state and continue loop to poll it
623                            let fut = this.flow.expect.call(req);
624                            this.state.set(State::ExpectCall { fut });
625                        } else {
626                            // set InnerDispatcher state and continue loop to poll it
627                            let fut = this.flow.service.call(req);
628                            this.state.set(State::ServiceCall { fut });
629                        };
630                    }
631
632                    // handle error message
633                    Some(DispatcherMessage::Error(res)) => {
634                        // send_response would update InnerDispatcher state to SendPayload or None
635                        // (If response body is empty)
636                        // continue loop to poll it
637                        self.as_mut().send_error_response(res, BoxBody::new(()))?;
638                    }
639
640                    // return with upgrade request and poll it exclusively
641                    Some(DispatcherMessage::Upgrade(req)) => return Ok(PollResponse::Upgrade(req)),
642
643                    // all messages are dealt with
644                    None => {
645                        // start keep-alive only if request payload is fully read/drained
646                        this.flags.set(
647                            Flags::KEEP_ALIVE,
648                            this.payload.is_none() && this.codec.keep_alive(),
649                        );
650
651                        return Ok(PollResponse::DoNothing);
652                    }
653                },
654
655                StateProj::ServiceCall { fut } => {
656                    match fut.poll(cx) {
657                        // service call resolved. send response.
658                        Poll::Ready(Ok(res)) => {
659                            let (res, body) = res.into().replace_body(());
660                            self.as_mut().send_response(res, body)?;
661                        }
662
663                        // send service call error as response
664                        Poll::Ready(Err(err)) => {
665                            let res: Response<BoxBody> = err.into();
666                            let (res, body) = res.replace_body(());
667                            self.as_mut().send_error_response(res, body)?;
668                        }
669
670                        // service call pending and could be waiting for more chunk messages
671                        // (pipeline message limit and/or payload can_read limit)
672                        Poll::Pending => {
673                            // no new message is decoded and no new payload is fed
674                            // nothing to do except waiting for new incoming data from client
675                            if !self.as_mut().poll_request(cx)? {
676                                return Ok(PollResponse::DoNothing);
677                            }
678                            // else loop
679                        }
680                    }
681                }
682
683                StateProj::SendPayload { mut body } => {
684                    // keep populate writer buffer until buffer size limit hit,
685                    // get blocked or finished.
686                    while this.write_buf.len() < *this.h1_write_buffer_size {
687                        match body.as_mut().poll_next(cx) {
688                            Poll::Ready(Some(Ok(item))) => {
689                                this.codec
690                                    .encode(Message::Chunk(Some(item)), this.write_buf)?;
691                            }
692
693                            Poll::Ready(None) => {
694                                this.codec.encode(Message::Chunk(None), this.write_buf)?;
695
696                                // if we have not yet pipelined to the next request, then
697                                // this.payload was the payload for the request we just finished
698                                // responding to. We can check to see if we finished reading it
699                                // yet, and if not, shutdown the connection.
700                                let close_for_unread_payload = should_close_for_unread_payload(
701                                    this.payload.as_ref(),
702                                    *this.payload_drainable,
703                                );
704                                let not_pipelined = this.messages.is_empty();
705
706                                // payload stream finished.
707                                // set state to None and handle next message
708                                this.state.set(State::None);
709
710                                if not_pipelined && close_for_unread_payload {
711                                    if this.config.client_disconnect_deadline().is_some() {
712                                        Self::enter_linger(this.flags);
713                                    } else {
714                                        this.flags.insert(Flags::SHUTDOWN | Flags::FINISHED);
715                                    }
716                                } else {
717                                    this.flags.insert(Flags::FINISHED);
718                                }
719
720                                continue 'res;
721                            }
722
723                            Poll::Ready(Some(Err(err))) => {
724                                let err = err.into();
725                                tracing::error!("Response payload stream error: {err:?}");
726                                this.flags.insert(Flags::FINISHED);
727                                return Err(DispatchError::Body(err));
728                            }
729
730                            Poll::Pending => return Ok(PollResponse::DoNothing),
731                        }
732                    }
733
734                    // buffer is beyond max size
735                    // return and try to write the whole buffer to I/O stream.
736                    return Ok(PollResponse::DrainWriteBuf);
737                }
738
739                StateProj::SendErrorPayload { mut body } => {
740                    // TODO: de-dupe impl with SendPayload
741
742                    // keep populate writer buffer until buffer size limit hit,
743                    // get blocked or finished.
744                    while this.write_buf.len() < *this.h1_write_buffer_size {
745                        match body.as_mut().poll_next(cx) {
746                            Poll::Ready(Some(Ok(item))) => {
747                                this.codec
748                                    .encode(Message::Chunk(Some(item)), this.write_buf)?;
749                            }
750
751                            Poll::Ready(None) => {
752                                this.codec.encode(Message::Chunk(None), this.write_buf)?;
753
754                                // if we have not yet pipelined to the next request, then
755                                // this.payload was the payload for the request we just finished
756                                // responding to. We can check to see if we finished reading it
757                                // yet, and if not, shutdown the connection.
758                                let close_for_unread_payload = should_close_for_unread_payload(
759                                    this.payload.as_ref(),
760                                    *this.payload_drainable,
761                                );
762                                let not_pipelined = this.messages.is_empty();
763
764                                // payload stream finished.
765                                // set state to None and handle next message
766                                this.state.set(State::None);
767
768                                if not_pipelined && close_for_unread_payload {
769                                    if this.config.client_disconnect_deadline().is_some() {
770                                        Self::enter_linger(this.flags);
771                                    } else {
772                                        this.flags.insert(Flags::SHUTDOWN | Flags::FINISHED);
773                                    }
774                                } else {
775                                    this.flags.insert(Flags::FINISHED);
776                                }
777
778                                continue 'res;
779                            }
780
781                            Poll::Ready(Some(Err(err))) => {
782                                tracing::error!("Response payload stream error: {err:?}");
783                                this.flags.insert(Flags::FINISHED);
784                                return Err(DispatchError::Body(
785                                    Error::new_body().with_cause(err).into(),
786                                ));
787                            }
788
789                            Poll::Pending => return Ok(PollResponse::DoNothing),
790                        }
791                    }
792
793                    // buffer is beyond max size
794                    // return and try to write the whole buffer to stream
795                    return Ok(PollResponse::DrainWriteBuf);
796                }
797
798                StateProj::ExpectCall { fut } => {
799                    trace!("  calling expect service");
800
801                    match fut.poll(cx) {
802                        // expect resolved. write continue to buffer and set InnerDispatcher state
803                        // to service call.
804                        Poll::Ready(Ok(req)) => {
805                            this.write_buf
806                                .extend_from_slice(b"HTTP/1.1 100 Continue\r\n\r\n");
807                            let fut = this.flow.service.call(req);
808                            this.state.set(State::ServiceCall { fut });
809                        }
810
811                        // send expect error as response
812                        Poll::Ready(Err(err)) => {
813                            let res: Response<BoxBody> = err.into();
814                            let (res, body) = res.replace_body(());
815                            self.as_mut().send_error_response(res, body)?;
816                        }
817
818                        // expect must be solved before progress can be made.
819                        Poll::Pending => return Ok(PollResponse::DoNothing),
820                    }
821                }
822            }
823        }
824    }
825
826    fn handle_request(
827        mut self: Pin<&mut Self>,
828        req: Request,
829        cx: &mut Context<'_>,
830    ) -> Result<(), DispatchError> {
831        // initialize dispatcher state
832        {
833            let mut this = self.as_mut().project();
834
835            // Handle `EXPECT: 100-Continue` header
836            if req.head().expect() {
837                // set dispatcher state to call expect handler
838                let fut = this.flow.expect.call(req);
839                this.state.set(State::ExpectCall { fut });
840            } else {
841                // set dispatcher state to call service handler
842                let fut = this.flow.service.call(req);
843                this.state.set(State::ServiceCall { fut });
844            };
845        };
846
847        // eagerly poll the future once (or twice if expect is resolved immediately).
848        loop {
849            match self.as_mut().project().state.project() {
850                StateProj::ExpectCall { fut } => {
851                    match fut.poll(cx) {
852                        // expect is resolved; continue loop and poll the service call branch.
853                        Poll::Ready(Ok(req)) => {
854                            self.as_mut().send_continue();
855
856                            let mut this = self.as_mut().project();
857                            let fut = this.flow.service.call(req);
858                            this.state.set(State::ServiceCall { fut });
859
860                            continue;
861                        }
862
863                        // future is error; send response and return a result
864                        // on success to notify the dispatcher a new state is set and the outer loop
865                        // should be continued
866                        Poll::Ready(Err(err)) => {
867                            let res: Response<BoxBody> = err.into();
868                            let (res, body) = res.replace_body(());
869                            return self.send_error_response(res, body);
870                        }
871
872                        // future is pending; return Ok(()) to notify that a new state is
873                        // set and the outer loop should be continue.
874                        Poll::Pending => return Ok(()),
875                    }
876                }
877
878                StateProj::ServiceCall { fut } => {
879                    // return no matter the service call future's result.
880                    return match fut.poll(cx) {
881                        // Future is resolved. Send response and return a result. On success
882                        // to notify the dispatcher a new state is set and the outer loop
883                        // should be continue.
884                        Poll::Ready(Ok(res)) => {
885                            let (res, body) = res.into().replace_body(());
886                            self.as_mut().send_response(res, body)
887                        }
888
889                        // see the comment on ExpectCall state branch's Pending
890                        Poll::Pending => Ok(()),
891
892                        // see the comment on ExpectCall state branch's Ready(Err(_))
893                        Poll::Ready(Err(err)) => {
894                            let res: Response<BoxBody> = err.into();
895                            let (res, body) = res.replace_body(());
896                            self.as_mut().send_error_response(res, body)
897                        }
898                    };
899                }
900
901                _ => {
902                    unreachable!("State must be set to ServiceCall or ExceptCall in handle_request")
903                }
904            }
905        }
906    }
907
908    /// Process one incoming request.
909    ///
910    /// Returns true if any meaningful work was done.
911    fn poll_request(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Result<bool, DispatchError> {
912        if self.flags.contains(Flags::DRAINING) && self.state.is_none() {
913            return Ok(false);
914        }
915
916        let pipeline_queue_full = self.messages.len() >= MAX_PIPELINED_MESSAGES;
917        let can_not_read = !self.can_read(cx);
918
919        // limit amount of non-processed requests
920        if pipeline_queue_full || can_not_read {
921            return Ok(false);
922        }
923
924        let mut this = self.as_mut().project();
925
926        let mut updated = false;
927
928        // decode from read buf as many full requests as possible
929        loop {
930            match this.codec.decode(this.read_buf) {
931                Ok(Some(msg)) => {
932                    updated = true;
933
934                    match msg {
935                        Message::Item(mut req) => {
936                            // head timer only applies to first request on connection
937                            this.head_timer.clear(line!());
938
939                            req.head_mut().peer_addr = *this.peer_addr;
940
941                            req.conn_data.clone_from(this.conn_data);
942
943                            match this.codec.message_type() {
944                                // request has no payload
945                                MessageType::None => *this.payload_drainable = false,
946
947                                // Request is upgradable. Add upgrade message and break.
948                                // Everything remaining in read buffer will be handed to
949                                // upgraded Request.
950                                MessageType::Stream if this.flow.upgrade.is_some() => {
951                                    *this.payload_drainable = false;
952                                    this.messages.push_back(DispatcherMessage::Upgrade(req));
953                                    break;
954                                }
955
956                                // request is not upgradable
957                                MessageType::Payload | MessageType::Stream => {
958                                    // PayloadSender and Payload are smart pointers share the
959                                    // same state. PayloadSender is attached to dispatcher and used
960                                    // to sink new chunked request data to state. Payload is
961                                    // attached to Request and passed to Service::call where the
962                                    // state can be collected and consumed.
963                                    let (sender, payload) = Payload::create(false);
964                                    *req.payload() = crate::Payload::H1 { payload };
965                                    *this.payload = Some(sender);
966                                    *this.payload_drainable = req.chunked().unwrap_or(false);
967                                }
968                            }
969
970                            // handle request early when no future in InnerDispatcher state.
971                            if this.state.is_none() {
972                                self.as_mut().handle_request(req, cx)?;
973                                this = self.as_mut().project();
974                            } else {
975                                this.messages.push_back(DispatcherMessage::Item(req));
976                            }
977                        }
978
979                        Message::Chunk(Some(chunk)) => {
980                            if let Some(ref mut payload) = this.payload {
981                                payload.feed_data(chunk);
982                            } else {
983                                error!("Internal server error: unexpected payload chunk");
984                                this.flags.insert(Flags::READ_DISCONNECT);
985                                this.messages.push_back(DispatcherMessage::Error(
986                                    Response::internal_server_error().drop_body(),
987                                ));
988                                *this.error = Some(DispatchError::InternalError);
989                                break;
990                            }
991                        }
992
993                        Message::Chunk(None) => {
994                            if let Some(mut payload) = this.payload.take() {
995                                payload.feed_eof();
996                                *this.payload_drainable = false;
997                            } else {
998                                error!("Internal server error: unexpected eof");
999                                this.flags.insert(Flags::READ_DISCONNECT);
1000                                this.messages.push_back(DispatcherMessage::Error(
1001                                    Response::internal_server_error().drop_body(),
1002                                ));
1003                                *this.error = Some(DispatchError::InternalError);
1004                                break;
1005                            }
1006                        }
1007                    }
1008                }
1009
1010                // decode is partial and buffer is not full yet
1011                // break and wait for more read
1012                Ok(None) => break,
1013
1014                Err(ParseError::Io(err)) => {
1015                    trace!("I/O error: {}", &err);
1016                    self.as_mut().client_disconnected();
1017                    this = self.as_mut().project();
1018                    *this.error = Some(DispatchError::Io(err));
1019                    break;
1020                }
1021
1022                Err(ParseError::TooLarge) => {
1023                    trace!("request head was too big; returning 431 response");
1024
1025                    if let Some(mut payload) = this.payload.take() {
1026                        payload.set_error(PayloadError::Overflow);
1027                    }
1028
1029                    // request heads that overflow buffer size return a 431 error
1030                    this.messages
1031                        .push_back(DispatcherMessage::Error(Response::with_body(
1032                            StatusCode::REQUEST_HEADER_FIELDS_TOO_LARGE,
1033                            (),
1034                        )));
1035
1036                    this.flags.insert(Flags::READ_DISCONNECT);
1037                    *this.error = Some(ParseError::TooLarge.into());
1038
1039                    break;
1040                }
1041
1042                Err(err) => {
1043                    trace!("parse error {}", &err);
1044
1045                    if let Some(mut payload) = this.payload.take() {
1046                        payload.set_error(PayloadError::EncodingCorrupted);
1047                    }
1048
1049                    // malformed requests should be responded with 400
1050                    this.messages.push_back(DispatcherMessage::Error(
1051                        Response::bad_request().drop_body(),
1052                    ));
1053
1054                    this.flags.insert(Flags::READ_DISCONNECT);
1055                    *this.error = Some(err.into());
1056                    break;
1057                }
1058            }
1059        }
1060
1061        Ok(updated)
1062    }
1063
1064    fn poll_head_timer(
1065        mut self: Pin<&mut Self>,
1066        cx: &mut Context<'_>,
1067    ) -> Result<(), DispatchError> {
1068        let this = self.as_mut().project();
1069
1070        if let TimerState::Active { timer } = this.head_timer {
1071            if timer.as_mut().poll(cx).is_ready() {
1072                // timeout on first request (slow request) return 408
1073
1074                trace!("timed out on slow request; replying with 408 and closing connection");
1075
1076                let _ = self.as_mut().send_error_response(
1077                    Response::with_body(StatusCode::REQUEST_TIMEOUT, ()),
1078                    BoxBody::new(()),
1079                );
1080
1081                self.project().flags.insert(Flags::SHUTDOWN);
1082            }
1083        };
1084
1085        Ok(())
1086    }
1087
1088    fn poll_ka_timer(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Result<(), DispatchError> {
1089        let this = self.as_mut().project();
1090        if let TimerState::Active { timer } = this.ka_timer {
1091            debug_assert!(
1092                this.flags.contains(Flags::KEEP_ALIVE),
1093                "keep-alive flag should be set when timer is active",
1094            );
1095            debug_assert!(
1096                this.state.is_none(),
1097                "dispatcher should not be in keep-alive phase if state is not none: {:?}",
1098                this.state,
1099            );
1100
1101            // Assert removed by @robjtede on account of issue #2655. There are cases where an I/O
1102            // flush can be pending after entering the keep-alive state causing the subsequent flush
1103            // wake up to panic here. This appears to be a Linux-only problem. Leaving original code
1104            // below for posterity because a simple and reliable test could not be found to trigger
1105            // the behavior.
1106            // debug_assert!(
1107            //     this.write_buf.is_empty(),
1108            //     "dispatcher should not be in keep-alive phase if write_buf is not empty",
1109            // );
1110
1111            // keep-alive timer has timed out
1112            if timer.as_mut().poll(cx).is_ready() {
1113                // no tasks at hand
1114                trace!("timer timed out; closing connection");
1115                this.flags.insert(Flags::SHUTDOWN);
1116
1117                if let Some(deadline) = this.config.client_disconnect_deadline() {
1118                    // start shutdown timeout if enabled
1119                    this.shutdown_timer
1120                        .set_and_init(cx, sleep_until(deadline.into()), line!());
1121                } else {
1122                    // no shutdown timeout, drop socket
1123                    this.flags.insert(Flags::WRITE_DISCONNECT);
1124                }
1125            }
1126        }
1127
1128        Ok(())
1129    }
1130
1131    fn poll_shutdown_timer(
1132        mut self: Pin<&mut Self>,
1133        cx: &mut Context<'_>,
1134    ) -> Result<(), DispatchError> {
1135        let this = self.as_mut().project();
1136        if let TimerState::Active { timer } = this.shutdown_timer {
1137            debug_assert!(
1138                this.flags.intersects(Flags::LINGER | Flags::SHUTDOWN),
1139                "shutdown or linger flag should be set when timer is active",
1140            );
1141
1142            if timer.as_mut().poll(cx).is_ready() {
1143                if this.flags.contains(Flags::LINGER) {
1144                    trace!("timed-out during linger; shutting down connection");
1145                    this.flags.remove(Flags::LINGER);
1146                    this.flags.insert(Flags::SHUTDOWN);
1147                    this.shutdown_timer.clear(line!());
1148                } else {
1149                    trace!("timed-out during shutdown");
1150                    return Err(DispatchError::DisconnectTimeout);
1151                }
1152            }
1153        }
1154
1155        Ok(())
1156    }
1157
1158    fn poll_graceful_shutdown(mut self: Pin<&mut Self>, cx: &mut Context<'_>) {
1159        let this = self.as_mut().project();
1160
1161        let notified = this
1162            .graceful_shutdown
1163            .as_mut()
1164            .is_some_and(|signal| signal.as_mut().poll(cx).is_ready());
1165
1166        if notified {
1167            *this.graceful_shutdown = None;
1168            this.flags.remove(Flags::KEEP_ALIVE);
1169            this.flags.insert(Flags::DRAINING);
1170
1171            if this.ka_timer.is_enabled() {
1172                this.ka_timer.clear(line!());
1173            }
1174        }
1175    }
1176
1177    /// Poll head, keep-alive, and disconnect timer.
1178    fn poll_timers(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Result<(), DispatchError> {
1179        self.as_mut().poll_head_timer(cx)?;
1180        self.as_mut().poll_ka_timer(cx)?;
1181        self.as_mut().poll_shutdown_timer(cx)?;
1182
1183        Ok(())
1184    }
1185
1186    /// Returns true when I/O stream can be disconnected after write to it.
1187    ///
1188    /// It covers these conditions:
1189    /// - `std::io::ErrorKind::ConnectionReset` after partial read;
1190    /// - all data read done.
1191    #[inline(always)] // TODO: bench this inline
1192    fn read_available(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Result<bool, DispatchError> {
1193        let this = self.project();
1194
1195        if this.flags.contains(Flags::READ_DISCONNECT) {
1196            return Ok(false);
1197        };
1198
1199        let mut io = Pin::new(this.io.as_mut().unwrap());
1200
1201        let mut read_some = false;
1202
1203        loop {
1204            // Return early when read buf exceed decoder's max buffer size.
1205            if this.read_buf.len() >= MAX_BUFFER_SIZE {
1206                // At this point it's not known IO stream is still scheduled to be waked up so
1207                // force wake up dispatcher just in case.
1208                //
1209                // Reason:
1210                // AsyncRead mostly would only have guarantee wake up when the poll_read
1211                // return Poll::Pending.
1212                //
1213                // Case:
1214                // When read_buf is beyond max buffer size the early return could be successfully
1215                // be parsed as a new Request. This case would not generate ParseError::TooLarge and
1216                // at this point IO stream is not fully read to Pending and would result in
1217                // dispatcher stuck until timeout (keep-alive).
1218                //
1219                // Note:
1220                // This is a perf choice to reduce branch on <Request as MessageType>::decode.
1221                //
1222                // A Request head too large to parse is only checked on `httparse::Status::Partial`.
1223
1224                match this.payload.as_ref().map(|p| p.need_read(cx)) {
1225                    // Payload consumer is alive but applying backpressure. Wait for its waker.
1226                    Some(PayloadStatus::Pause) => {}
1227
1228                    // Consumer dropped means drain/discard mode; keep polling to make progress.
1229                    Some(PayloadStatus::Dropped) | Some(PayloadStatus::Read) | None => {
1230                        cx.waker().wake_by_ref()
1231                    }
1232                }
1233
1234                return Ok(false);
1235            }
1236
1237            // grow buffer if necessary.
1238            let remaining = this.read_buf.capacity() - this.read_buf.len();
1239            if remaining < LW_BUFFER_SIZE {
1240                this.read_buf.reserve(HW_BUFFER_SIZE - remaining);
1241            }
1242
1243            match tokio_util::io::poll_read_buf(io.as_mut(), cx, this.read_buf) {
1244                Poll::Ready(Ok(n)) => {
1245                    // When draining a dropped request payload, keep FINISHED set so the
1246                    // disconnect/keep-alive decision can be made once the payload is fully drained.
1247                    if !this.payload.as_ref().is_some_and(|pl| pl.is_dropped()) {
1248                        this.flags.remove(Flags::FINISHED);
1249                    }
1250
1251                    if n == 0 {
1252                        return Ok(true);
1253                    }
1254
1255                    read_some = true;
1256                }
1257
1258                Poll::Pending => {
1259                    return Ok(false);
1260                }
1261
1262                Poll::Ready(Err(err)) => {
1263                    return match err.kind() {
1264                        // convert WouldBlock error to the same as Pending return
1265                        io::ErrorKind::WouldBlock => Ok(false),
1266
1267                        // connection reset after partial read
1268                        io::ErrorKind::ConnectionReset if read_some => Ok(true),
1269
1270                        _ => Err(DispatchError::Io(err)),
1271                    };
1272                }
1273            }
1274        }
1275    }
1276
1277    /// call upgrade service with request.
1278    fn upgrade(self: Pin<&mut Self>, req: Request) -> U::Future {
1279        let this = self.project();
1280        let mut parts = FramedParts::with_read_buf(
1281            this.io.take().unwrap(),
1282            mem::take(this.codec),
1283            mem::take(this.read_buf),
1284        );
1285        parts.write_buf = mem::take(this.write_buf);
1286        let framed = Framed::from_parts(parts);
1287        this.flow.upgrade.as_ref().unwrap().call((req, framed))
1288    }
1289}
1290
1291impl<T, S, B, X, U> Future for Dispatcher<T, S, B, X, U>
1292where
1293    T: AsyncRead + AsyncWrite + Unpin,
1294
1295    S: Service<Request>,
1296    S::Error: Into<Response<BoxBody>>,
1297    S::Response: Into<Response<B>>,
1298
1299    B: MessageBody,
1300
1301    X: Service<Request, Response = Request>,
1302    X::Error: Into<Response<BoxBody>>,
1303
1304    U: Service<(Request, Framed<T, Codec>), Response = ()>,
1305    U::Error: fmt::Display,
1306{
1307    type Output = Result<(), DispatchError>;
1308
1309    #[inline]
1310    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
1311        let this = self.as_mut().project();
1312
1313        #[cfg(test)]
1314        {
1315            *this.poll_count += 1;
1316        }
1317
1318        match this.inner.project() {
1319            DispatcherStateProj::Upgrade { fut: upgrade } => upgrade.poll(cx).map_err(|err| {
1320                error!("Upgrade handler error: {}", err);
1321                DispatchError::Upgrade
1322            }),
1323
1324            DispatcherStateProj::Normal { mut inner } => {
1325                trace!("start flags: {:?}", &inner.flags);
1326
1327                trace_timer_states(
1328                    "start",
1329                    &inner.head_timer,
1330                    &inner.ka_timer,
1331                    &inner.shutdown_timer,
1332                );
1333
1334                inner.as_mut().poll_graceful_shutdown(cx);
1335                inner.as_mut().poll_timers(cx)?;
1336
1337                let poll = if inner.flags.contains(Flags::LINGER) {
1338                    match inner.as_mut().poll_linger(cx)? {
1339                        Poll::Ready(()) => {
1340                            cx.waker().wake_by_ref();
1341                            Poll::Pending
1342                        }
1343                        Poll::Pending => Poll::Pending,
1344                    }
1345                } else if inner.flags.contains(Flags::SHUTDOWN) {
1346                    if inner.flags.contains(Flags::WRITE_DISCONNECT) {
1347                        Poll::Ready(Ok(()))
1348                    } else {
1349                        // flush buffer and wait on blocked
1350                        ready!(inner.as_mut().poll_flush(cx))?;
1351                        Pin::new(inner.as_mut().project().io.as_mut().unwrap())
1352                            .poll_shutdown(cx)
1353                            .map_err(DispatchError::from)
1354                    }
1355                } else {
1356                    // read from I/O stream and fill read buffer
1357                    let should_disconnect = inner.as_mut().read_available(cx)?;
1358
1359                    // after reading something from stream, clear keep-alive timer
1360                    if !inner.read_buf.is_empty() && inner.flags.contains(Flags::KEEP_ALIVE) {
1361                        let inner = inner.as_mut().project();
1362                        inner.flags.remove(Flags::KEEP_ALIVE);
1363                        inner.ka_timer.clear(line!());
1364                    }
1365
1366                    if !inner.flags.contains(Flags::STARTED) {
1367                        inner.as_mut().project().flags.insert(Flags::STARTED);
1368
1369                        if let Some(deadline) = inner.config.client_request_deadline() {
1370                            inner.as_mut().project().head_timer.set_and_init(
1371                                cx,
1372                                sleep_until(deadline.into()),
1373                                line!(),
1374                            );
1375                        }
1376                    }
1377
1378                    inner.as_mut().poll_request(cx)?;
1379
1380                    if should_disconnect {
1381                        // I/O stream should to be closed
1382                        let inner = inner.as_mut().project();
1383                        inner.flags.insert(Flags::READ_DISCONNECT);
1384                        if let Some(mut payload) = inner.payload.take() {
1385                            payload.set_error(PayloadError::Incomplete(None));
1386                            payload.feed_eof();
1387                        }
1388                    };
1389
1390                    loop {
1391                        // poll response to populate write buffer
1392                        // drain indicates whether write buffer should be emptied before next run
1393                        let drain = match inner.as_mut().poll_response(cx)? {
1394                            PollResponse::DrainWriteBuf => true,
1395
1396                            PollResponse::DoNothing => {
1397                                // KEEP_ALIVE is set in send_response_inner if client allows it
1398                                // FINISHED is set after writing last chunk of response
1399                                if inner.flags.contains(Flags::KEEP_ALIVE | Flags::FINISHED) {
1400                                    if let Some(timer) = inner.config.keep_alive_deadline() {
1401                                        inner.as_mut().project().ka_timer.set_and_init(
1402                                            cx,
1403                                            sleep_until(timer.into()),
1404                                            line!(),
1405                                        );
1406                                    }
1407                                }
1408
1409                                false
1410                            }
1411
1412                            // upgrade request and goes Upgrade variant of DispatcherState.
1413                            PollResponse::Upgrade(req) => {
1414                                let upgrade = inner.upgrade(req);
1415                                self.as_mut()
1416                                    .project()
1417                                    .inner
1418                                    .set(DispatcherState::Upgrade { fut: upgrade });
1419                                return self.poll(cx);
1420                            }
1421                        };
1422
1423                        // we didn't get WouldBlock from write operation, so data get written to
1424                        // kernel completely (macOS) and we have to write again otherwise response
1425                        // can get stuck
1426                        //
1427                        // TODO: want to find a reference for this behavior
1428                        // see introduced commit: 3872d3ba
1429                        let flush_was_ready = inner.as_mut().poll_flush(cx)?.is_ready();
1430
1431                        // this assert seems to always be true but not willing to commit to it until
1432                        // we understand what Nikolay meant when writing the above comment
1433                        // debug_assert!(flush_was_ready);
1434
1435                        if !flush_was_ready || !drain {
1436                            break;
1437                        }
1438                    }
1439
1440                    // client is gone
1441                    if inner.flags.contains(Flags::WRITE_DISCONNECT) {
1442                        trace!("client is gone; disconnecting");
1443                        return Poll::Ready(Ok(()));
1444                    }
1445
1446                    let inner_p = inner.as_mut().project();
1447                    let state_is_none = inner_p.state.is_none();
1448
1449                    // If the read-half is closed, we start the shutdown procedure if either is
1450                    // true:
1451                    //
1452                    // - state is [`State::None`], which means that we're done with request
1453                    //   processing, so if the client closed its writer-side it means that it won't
1454                    //   send more requests.
1455                    // - The user requested to not allow half-closures
1456                    if inner_p.flags.contains(Flags::READ_DISCONNECT)
1457                        && (!inner_p.config.h1_allow_half_closed() || state_is_none)
1458                    {
1459                        trace!("read half closed; start shutdown");
1460                        inner_p.flags.insert(Flags::SHUTDOWN);
1461                    }
1462
1463                    // keep-alive and stream errors
1464                    if state_is_none && inner_p.write_buf.is_empty() {
1465                        if let Some(err) = inner_p.error.take() {
1466                            error!("stream error: {}", &err);
1467                            return Poll::Ready(Err(err));
1468                        }
1469
1470                        // disconnect if keep-alive is not enabled
1471                        if inner_p.flags.contains(Flags::FINISHED)
1472                            && !inner_p.flags.contains(Flags::KEEP_ALIVE)
1473                            && inner_p.payload.is_none()
1474                        {
1475                            inner_p.flags.remove(Flags::FINISHED);
1476                            inner_p.flags.insert(Flags::SHUTDOWN);
1477                            return self.poll(cx);
1478                        }
1479
1480                        // disconnect if shutdown
1481                        if inner_p.flags.contains(Flags::SHUTDOWN) {
1482                            return self.poll(cx);
1483                        }
1484                    }
1485
1486                    trace_timer_states(
1487                        "end",
1488                        inner_p.head_timer,
1489                        inner_p.ka_timer,
1490                        inner_p.shutdown_timer,
1491                    );
1492
1493                    if inner_p.flags.intersects(Flags::LINGER | Flags::SHUTDOWN) {
1494                        cx.waker().wake_by_ref();
1495                    }
1496                    Poll::Pending
1497                };
1498
1499                trace!("end flags: {:?}", &inner.flags);
1500
1501                poll
1502            }
1503        }
1504    }
1505}
1506
1507fn should_close_for_unread_payload(
1508    payload: Option<&PayloadSender>,
1509    payload_drainable: bool,
1510) -> bool {
1511    let payload_unfinished = payload.is_some();
1512    let drain_payload = payload.is_some_and(|pl| pl.is_dropped()) && payload_drainable;
1513
1514    payload_unfinished && !drain_payload
1515}
1516
1517#[allow(dead_code)]
1518fn trace_timer_states(
1519    label: &str,
1520    head_timer: &TimerState,
1521    ka_timer: &TimerState,
1522    shutdown_timer: &TimerState,
1523) {
1524    trace!("{} timers:", label);
1525
1526    if head_timer.is_enabled() {
1527        trace!("  head {}", &head_timer);
1528    }
1529
1530    if ka_timer.is_enabled() {
1531        trace!("  keep-alive {}", &ka_timer);
1532    }
1533
1534    if shutdown_timer.is_enabled() {
1535        trace!("  shutdown {}", &shutdown_timer);
1536    }
1537}
1538
1539#[cfg(test)]
1540#[path = "dispatcher_tests.rs"]
1541mod dispatcher_tests;
1542
1543#[cfg(test)]
1544#[path = "dispatcher_buffer_tests.rs"]
1545mod buffer_tests;