Skip to main content

hyper/proto/h1/
dispatch.rs

1use std::{
2    error::Error as StdError,
3    future::Future,
4    marker::Unpin,
5    pin::Pin,
6    task::{Context, Poll},
7};
8
9use crate::rt::{Read, Write};
10use bytes::{Buf, Bytes};
11use futures_core::ready;
12use http::Request;
13
14use super::{Http1Transaction, Wants};
15use crate::body::{Body, DecodedLength, Incoming as IncomingBody};
16#[cfg(feature = "client")]
17use crate::client::dispatch::TrySendError;
18use crate::common::task;
19use crate::proto::{BodyLength, Conn, Dispatched, MessageHead, RequestHead};
20use crate::upgrade::OnUpgrade;
21
22pub(crate) struct Dispatcher<D, Bs: Body, I, T> {
23    conn: Conn<I, Bs::Data, T>,
24    dispatch: D,
25    body_tx: SenderDropGuard,
26    body_rx: Pin<Box<Option<Bs>>>,
27    is_closing: bool,
28}
29
30pub(crate) trait Dispatch {
31    type PollItem;
32    type PollBody;
33    type PollError;
34    type RecvItem;
35    fn poll_msg(
36        self: Pin<&mut Self>,
37        cx: &mut Context<'_>,
38    ) -> Poll<Option<Result<(Self::PollItem, Self::PollBody), Self::PollError>>>;
39    fn recv_msg(&mut self, msg: crate::Result<(Self::RecvItem, IncomingBody)>)
40        -> crate::Result<()>;
41    fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), ()>>;
42    fn should_poll(&self) -> bool;
43}
44
45cfg_server! {
46    use crate::service::HttpService;
47
48    pub(crate) struct Server<S: HttpService<B>, B> {
49        in_flight: Pin<Box<Option<S::Future>>>,
50        pub(crate) service: S,
51    }
52}
53
54cfg_client! {
55    pin_project_lite::pin_project! {
56        pub(crate) struct Client<B> {
57            callback: Option<crate::client::dispatch::Callback<Request<B>, http::Response<IncomingBody>>>,
58            #[pin]
59            rx: ClientRx<B>,
60            rx_closed: bool,
61        }
62    }
63
64    type ClientRx<B> = crate::client::dispatch::Receiver<Request<B>, http::Response<IncomingBody>>;
65}
66
67impl<D, Bs, I, T> Dispatcher<D, Bs, I, T>
68where
69    D: Dispatch<
70            PollItem = MessageHead<T::Outgoing>,
71            PollBody = Bs,
72            RecvItem = MessageHead<T::Incoming>,
73        > + Unpin,
74    D::PollError: Into<Box<dyn StdError + Send + Sync>>,
75    I: Read + Write + Unpin,
76    T: Http1Transaction + Unpin,
77    Bs: Body + 'static,
78    Bs::Error: Into<Box<dyn StdError + Send + Sync>>,
79{
80    pub(crate) fn new(dispatch: D, conn: Conn<I, Bs::Data, T>) -> Self {
81        Dispatcher {
82            conn,
83            dispatch,
84            body_tx: SenderDropGuard::none(),
85            body_rx: Box::pin(None),
86            is_closing: false,
87        }
88    }
89
90    #[cfg(feature = "server")]
91    pub(crate) fn disable_keep_alive(&mut self) {
92        self.conn.disable_keep_alive();
93
94        // If keep alive has been disabled and no read or write has been seen on
95        // the connection yet, we must be in a state where the server is being asked to
96        // shut down before any data has been seen on the connection
97        if self.conn.is_write_closed() || self.conn.has_initial_read_write_state() {
98            self.close();
99        }
100    }
101
102    pub(crate) fn into_inner(self) -> (I, Bytes, D) {
103        let (io, buf) = self.conn.into_inner();
104        (io, buf, self.dispatch)
105    }
106
107    /// Run this dispatcher until HTTP says this connection is done,
108    /// but don't call `Write::shutdown` on the underlying IO.
109    ///
110    /// This is useful for old-style HTTP upgrades, but ignores
111    /// newer-style upgrade API.
112    pub(crate) fn poll_without_shutdown(
113        &mut self,
114        cx: &mut Context<'_>,
115    ) -> Poll<crate::Result<()>> {
116        Pin::new(self).poll_catch(cx, false).map_ok(|ds| {
117            if let Dispatched::Upgrade(pending) = ds {
118                pending.manual();
119            }
120        })
121    }
122
123    fn poll_catch(
124        &mut self,
125        cx: &mut Context<'_>,
126        should_shutdown: bool,
127    ) -> Poll<crate::Result<Dispatched>> {
128        Poll::Ready(ready!(self.poll_inner(cx, should_shutdown)).or_else(|e| {
129            // Be sure to alert a streaming body of the failure with a
130            // more specific error than the drop guard would provide.
131            if let Some(mut body) = self.body_tx.take() {
132                body.send_error(crate::Error::new_body("connection error"));
133            }
134            // An error means we're shutting down either way.
135            // We just try to give the error to the user,
136            // and close the connection with an Ok. If we
137            // cannot give it to the user, then return the Err.
138            self.dispatch.recv_msg(Err(e))?;
139            Ok(Dispatched::Shutdown)
140        }))
141    }
142
143    fn poll_inner(
144        &mut self,
145        cx: &mut Context<'_>,
146        should_shutdown: bool,
147    ) -> Poll<crate::Result<Dispatched>> {
148        T::update_date();
149
150        ready!(self.poll_loop(cx))?;
151
152        if self.is_done() {
153            if let Some(pending) = self.conn.pending_upgrade() {
154                self.conn.take_error()?;
155                return Poll::Ready(Ok(Dispatched::Upgrade(pending)));
156            } else if should_shutdown {
157                ready!(self.conn.poll_shutdown(cx)).map_err(crate::Error::new_shutdown)?;
158            }
159            self.conn.take_error()?;
160            Poll::Ready(Ok(Dispatched::Shutdown))
161        } else {
162            Poll::Pending
163        }
164    }
165
166    fn poll_loop(&mut self, cx: &mut Context<'_>) -> Poll<crate::Result<()>> {
167        // Limit the looping on this connection, in case it is ready far too
168        // often, so that other futures don't starve.
169        //
170        // 16 was chosen arbitrarily, as that is number of pipelined requests
171        // benchmarks often use. Perhaps it should be a config option instead.
172        for _ in 0..16 {
173            let _ = self.poll_read(cx)?;
174            let write_ready = self.poll_write(cx)?.is_ready();
175            let flush_ready = self.poll_flush(cx)?.is_ready();
176
177            // If we can write more body and the connection is ready, we should
178            // write again. If we return `Ready(Ok(())` here, we will yield
179            // without a guaranteed wake-up from the write side of the connection.
180            // This would lead to a deadlock if we also don't expect reads.
181            let wants_write_again = self.can_write_again() && (write_ready || flush_ready);
182
183            // This could happen if reading paused before blocking on IO,
184            // such as getting to the end of a framed message, but then
185            // writing/flushing set the state back to Init. In that case,
186            // if the read buffer still had bytes, we'd want to try poll_read
187            // again, or else we wouldn't ever be woken up again.
188            //
189            // Using this instead of task::current() and notify() inside
190            // the Conn is noticeably faster in pipelined benchmarks.
191            let wants_read_again = self.conn.wants_read_again();
192
193            // If we cannot write or read again, we yield and rely on the
194            // wake-up from the connection futures.
195            if !(wants_write_again || wants_read_again) {
196                return Poll::Ready(Ok(()));
197            }
198
199            // If we are continuing only because "wants_write_again", re-check whether a second
200            // write poll can make progress. `poll_flush` can be ready even when there is no
201            // buffered data and the request body is still pending, so relying on the previous
202            // readiness can hot-loop.
203            if !wants_read_again && wants_write_again {
204                // Write was previously pending, but may have become ready since polling flush, so
205                // we need to check it again. If it is still pending, it is safe to yield and rely
206                // on wake-up from the connection futures.
207                if self.poll_write(cx)?.is_pending() {
208                    return Poll::Ready(Ok(()));
209                }
210            }
211        }
212        trace!("poll_loop yielding (self = {:p})", self);
213        task::yield_now(cx).map(|never| match never {})
214    }
215
216    fn poll_read(&mut self, cx: &mut Context<'_>) -> Poll<crate::Result<()>> {
217        loop {
218            if self.is_closing {
219                return Poll::Ready(Ok(()));
220            } else if self.conn.can_read_head() {
221                ready!(self.poll_read_head(cx))?;
222            } else if let Some(mut body) = self.body_tx.take() {
223                if self.conn.can_read_body() {
224                    match body.poll_ready(cx) {
225                        Poll::Ready(Ok(())) => (),
226                        Poll::Pending => {
227                            self.body_tx.set(body);
228                            return Poll::Pending;
229                        }
230                        Poll::Ready(Err(_canceled)) => {
231                            // user doesn't care about the body
232                            // so we should stop reading
233                            trace!("body receiver dropped before eof, draining or closing");
234                            self.conn.poll_drain_or_close_read(cx);
235                            continue;
236                        }
237                    }
238                    match self.conn.poll_read_body(cx) {
239                        Poll::Ready(Some(Ok(frame))) => {
240                            if frame.is_data() {
241                                let chunk = frame.into_data().unwrap_or_else(|_| unreachable!());
242                                match body.try_send_data(chunk) {
243                                    Ok(()) => {
244                                        self.body_tx.set(body);
245                                    }
246                                    Err(_canceled) => {
247                                        if self.conn.can_read_body() {
248                                            trace!("body receiver dropped before eof, closing");
249                                            self.conn.close_read();
250                                        }
251                                    }
252                                }
253                            } else if frame.is_trailers() {
254                                let trailers =
255                                    frame.into_trailers().unwrap_or_else(|_| unreachable!());
256                                match body.try_send_trailers(trailers) {
257                                    Ok(()) => {
258                                        self.body_tx.set(body);
259                                    }
260                                    Err(_canceled) => {
261                                        if self.conn.can_read_body() {
262                                            trace!("body receiver dropped before eof, closing");
263                                            self.conn.close_read();
264                                        }
265                                    }
266                                }
267                            } else {
268                                // we should have dropped all unknown frames in poll_read_body
269                                error!("unexpected frame");
270                            }
271                        }
272                        Poll::Ready(None) => {
273                            // just drop, the body will close automatically
274                        }
275                        Poll::Pending => {
276                            self.body_tx.set(body);
277                            return Poll::Pending;
278                        }
279                        Poll::Ready(Some(Err(e))) => {
280                            body.send_error(crate::Error::new_body(e));
281                        }
282                    }
283                } else {
284                    // just drop, the body will close automatically
285                }
286            } else {
287                return self.conn.poll_read_keep_alive(cx);
288            }
289        }
290    }
291
292    fn poll_read_head(&mut self, cx: &mut Context<'_>) -> Poll<crate::Result<()>> {
293        // can dispatch receive, or does it still care about other incoming message?
294        if let Ok(()) = ready!(self.dispatch.poll_ready(cx)) {
295        } else {
296            trace!("dispatch no longer receiving messages");
297            self.close();
298            return Poll::Ready(Ok(()));
299        }
300
301        // dispatch is ready for a message, try to read one
302        match ready!(self.conn.poll_read_head(cx)) {
303            Some(Ok((mut head, body_len, wants))) => {
304                let body = match body_len {
305                    DecodedLength::ZERO => IncomingBody::empty(),
306                    other => {
307                        let (tx, rx) =
308                            IncomingBody::new_channel(other, wants.contains(Wants::EXPECT));
309                        self.body_tx.set(tx);
310                        rx
311                    }
312                };
313                if wants.contains(Wants::UPGRADE) {
314                    let upgrade = self.conn.on_upgrade();
315                    debug_assert!(!upgrade.is_none(), "empty upgrade");
316                    debug_assert!(
317                        head.extensions.get::<OnUpgrade>().is_none(),
318                        "OnUpgrade already set"
319                    );
320                    head.extensions.insert(upgrade);
321                }
322                self.dispatch.recv_msg(Ok((head, body)))?;
323                Poll::Ready(Ok(()))
324            }
325            Some(Err(err)) => {
326                debug!("read_head error: {}", err);
327                self.dispatch.recv_msg(Err(err))?;
328                // if here, the dispatcher gave the user the error
329                // somewhere else. we still need to shutdown, but
330                // not as a second error.
331                self.close();
332                Poll::Ready(Ok(()))
333            }
334            None => {
335                // read eof, the write side will have been closed too unless
336                // allow_read_close was set to true, in which case just do
337                // nothing...
338                debug_assert!(self.conn.is_read_closed());
339                if self.conn.is_write_closed() {
340                    self.close();
341                }
342                Poll::Ready(Ok(()))
343            }
344        }
345    }
346
347    fn poll_write(&mut self, cx: &mut Context<'_>) -> Poll<crate::Result<()>> {
348        loop {
349            if self.is_closing {
350                return Poll::Ready(Ok(()));
351            } else if self.body_rx.is_none()
352                && self.conn.can_write_head()
353                && self.dispatch.should_poll()
354            {
355                if let Some(msg) = ready!(Pin::new(&mut self.dispatch).poll_msg(cx)) {
356                    let (head, body) = msg.map_err(crate::Error::new_user_service)?;
357
358                    let body_type = if body.is_end_stream() {
359                        self.body_rx.set(None);
360                        None
361                    } else {
362                        let btype = body
363                            .size_hint()
364                            .exact()
365                            .map(BodyLength::Known)
366                            .or(Some(BodyLength::Unknown));
367                        self.body_rx.set(Some(body));
368                        btype
369                    };
370                    self.conn.write_head(head, body_type);
371                } else {
372                    self.close();
373                    return Poll::Ready(Ok(()));
374                }
375            } else if !self.conn.can_buffer_body() {
376                ready!(self.poll_flush(cx))?;
377            } else {
378                // A new scope is needed :(
379                if let (Some(mut body), clear_body) =
380                    OptGuard::new(self.body_rx.as_mut()).guard_mut()
381                {
382                    debug_assert!(!*clear_body, "opt guard defaults to keeping body");
383                    if !self.conn.can_write_body() {
384                        trace!(
385                            "no more write body allowed, user body is_end_stream = {}",
386                            body.is_end_stream(),
387                        );
388                        *clear_body = true;
389                        continue;
390                    }
391
392                    let item = ready!(body.as_mut().poll_frame(cx));
393                    if let Some(item) = item {
394                        let frame = item.map_err(|e| {
395                            *clear_body = true;
396                            crate::Error::new_user_body(e)
397                        })?;
398
399                        if frame.is_data() {
400                            let chunk = frame.into_data().unwrap_or_else(|_| unreachable!());
401                            let eos = body.is_end_stream();
402                            if eos {
403                                *clear_body = true;
404                                if chunk.remaining() == 0 {
405                                    trace!("discarding empty chunk");
406                                    self.conn.end_body()?;
407                                } else {
408                                    self.conn.write_body_and_end(chunk);
409                                }
410                            } else {
411                                if chunk.remaining() == 0 {
412                                    trace!("discarding empty chunk");
413                                    continue;
414                                }
415                                self.conn.write_body(chunk);
416                            }
417                        } else if frame.is_trailers() {
418                            *clear_body = true;
419                            self.conn.write_trailers(
420                                frame.into_trailers().unwrap_or_else(|_| unreachable!()),
421                            );
422                        } else {
423                            trace!("discarding unknown frame");
424                            continue;
425                        }
426                    } else {
427                        *clear_body = true;
428                        self.conn.end_body()?;
429                    }
430                } else {
431                    // If there's no body_rx, end the body
432                    if self.conn.can_write_body() {
433                        self.conn.end_body()?;
434                    } else {
435                        return Poll::Pending;
436                    }
437                }
438            }
439        }
440    }
441
442    fn poll_flush(&mut self, cx: &mut Context<'_>) -> Poll<crate::Result<()>> {
443        self.conn.poll_flush(cx).map_err(|err| {
444            debug!("error writing: {}", err);
445            crate::Error::new_body_write(err)
446        })
447    }
448
449    fn close(&mut self) {
450        self.is_closing = true;
451        self.conn.close_read();
452        self.conn.close_write();
453    }
454
455    /// If there is pending data in `body_rx`, and the connection is still in a body-writing state,
456    /// we can make progress writing if the connection is ready.
457    fn can_write_again(&mut self) -> bool {
458        !self.is_closing && self.body_rx.is_some() && self.conn.can_write_body()
459    }
460
461    fn is_done(&self) -> bool {
462        if self.is_closing {
463            return true;
464        }
465
466        let read_done = self.conn.is_read_closed();
467
468        if !T::should_read_first() && read_done {
469            // a client that cannot read may was well be done.
470            true
471        } else {
472            let write_done = self.conn.is_write_closed()
473                || (!self.dispatch.should_poll() && self.body_rx.is_none());
474            read_done && write_done
475        }
476    }
477}
478
479impl<D, Bs, I, T> Future for Dispatcher<D, Bs, I, T>
480where
481    D: Dispatch<
482            PollItem = MessageHead<T::Outgoing>,
483            PollBody = Bs,
484            RecvItem = MessageHead<T::Incoming>,
485        > + Unpin,
486    D::PollError: Into<Box<dyn StdError + Send + Sync>>,
487    I: Read + Write + Unpin,
488    T: Http1Transaction + Unpin,
489    Bs: Body + 'static,
490    Bs::Error: Into<Box<dyn StdError + Send + Sync>>,
491{
492    type Output = crate::Result<Dispatched>;
493
494    #[inline]
495    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
496        self.poll_catch(cx, true)
497    }
498}
499
500// ===== impl OptGuard =====
501
502/// A drop guard to allow a mutable borrow of an Option while being able to
503/// set whether the `Option` should be cleared on drop.
504struct OptGuard<'a, T>(Pin<&'a mut Option<T>>, bool);
505
506impl<'a, T> OptGuard<'a, T> {
507    fn new(pin: Pin<&'a mut Option<T>>) -> Self {
508        OptGuard(pin, false)
509    }
510
511    fn guard_mut(&mut self) -> (Option<Pin<&mut T>>, &mut bool) {
512        (self.0.as_mut().as_pin_mut(), &mut self.1)
513    }
514}
515
516impl<T> Drop for OptGuard<'_, T> {
517    fn drop(&mut self) {
518        if self.1 {
519            self.0.set(None);
520        }
521    }
522}
523
524// ===== impl SenderDropGuard =====
525
526/// A drop guard for the body `Sender`.
527///
528/// If the `Dispatcher` future is dropped (e.g. the runtime driving the
529/// connection is shut down) while it still owns a body `Sender`, the guard
530/// sends an incomplete-message error so the receiver sees an error instead
531/// of a silent, clean end-of-stream.
532struct SenderDropGuard(Option<crate::body::Sender>);
533
534impl SenderDropGuard {
535    fn none() -> Self {
536        SenderDropGuard(None)
537    }
538
539    fn set(&mut self, sender: crate::body::Sender) {
540        self.0 = Some(sender);
541    }
542
543    fn take(&mut self) -> Option<crate::body::Sender> {
544        self.0.take()
545    }
546}
547
548impl Drop for SenderDropGuard {
549    fn drop(&mut self) {
550        if let Some(mut sender) = self.0.take() {
551            sender.send_error(crate::Error::new_incomplete());
552        }
553    }
554}
555
556// ===== impl Server =====
557
558cfg_server! {
559    impl<S, B> Server<S, B>
560    where
561        S: HttpService<B>,
562    {
563        pub(crate) fn new(service: S) -> Server<S, B> {
564            Server {
565                in_flight: Box::pin(None),
566                service,
567            }
568        }
569
570        pub(crate) fn into_service(self) -> S {
571            self.service
572        }
573    }
574
575    // Service is never pinned
576    impl<S: HttpService<B>, B> Unpin for Server<S, B> {}
577
578    impl<S, Bs> Dispatch for Server<S, IncomingBody>
579    where
580        S: HttpService<IncomingBody, ResBody = Bs>,
581        S::Error: Into<Box<dyn StdError + Send + Sync>>,
582        Bs: Body,
583    {
584        type PollItem = MessageHead<http::StatusCode>;
585        type PollBody = Bs;
586        type PollError = S::Error;
587        type RecvItem = RequestHead;
588
589        fn poll_msg(
590            mut self: Pin<&mut Self>,
591            cx: &mut Context<'_>,
592        ) -> Poll<Option<Result<(Self::PollItem, Self::PollBody), Self::PollError>>> {
593            let mut this = self.as_mut();
594            let ret = if let Some(ref mut fut) = this.in_flight.as_mut().as_pin_mut() {
595                let resp = ready!(fut.as_mut().poll(cx)?);
596                let (parts, body) = resp.into_parts();
597                let head = MessageHead {
598                    version: parts.version,
599                    subject: parts.status,
600                    headers: parts.headers,
601                    extensions: parts.extensions,
602                };
603                Poll::Ready(Some(Ok((head, body))))
604            } else {
605                unreachable!("poll_msg shouldn't be called if no inflight");
606            };
607
608            // Since in_flight finished, remove it
609            this.in_flight.set(None);
610            ret
611        }
612
613        fn recv_msg(&mut self, msg: crate::Result<(Self::RecvItem, IncomingBody)>) -> crate::Result<()> {
614            let (msg, body) = msg?;
615            let mut req = Request::new(body);
616            *req.method_mut() = msg.subject.0;
617            *req.uri_mut() = msg.subject.1;
618            *req.headers_mut() = msg.headers;
619            *req.version_mut() = msg.version;
620            *req.extensions_mut() = msg.extensions;
621            let fut = self.service.call(req);
622            self.in_flight.set(Some(fut));
623            Ok(())
624        }
625
626        fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), ()>> {
627            if self.in_flight.is_some() {
628                Poll::Pending
629            } else {
630                Poll::Ready(Ok(()))
631            }
632        }
633
634        fn should_poll(&self) -> bool {
635            self.in_flight.is_some()
636        }
637    }
638}
639
640// ===== impl Client =====
641
642cfg_client! {
643    use std::convert::Infallible;
644
645    impl<B> Client<B> {
646        pub(crate) fn new(rx: ClientRx<B>) -> Client<B> {
647            Client {
648                callback: None,
649                rx,
650                rx_closed: false,
651            }
652        }
653    }
654
655    impl<B> Dispatch for Client<B>
656    where
657        B: Body,
658    {
659        type PollItem = RequestHead;
660        type PollBody = B;
661        type PollError = Infallible;
662        type RecvItem = crate::proto::ResponseHead;
663
664        fn poll_msg(
665            mut self: Pin<&mut Self>,
666            cx: &mut Context<'_>,
667        ) -> Poll<Option<Result<(Self::PollItem, Self::PollBody), Infallible>>> {
668            let mut this = self.as_mut();
669            debug_assert!(!this.rx_closed);
670            match this.rx.poll_recv(cx) {
671                Poll::Ready(Some((req, mut cb))) => {
672                    // check that future hasn't been canceled already
673                    match cb.poll_canceled(cx) {
674                        Poll::Ready(()) => {
675                            trace!("request canceled");
676                            Poll::Ready(None)
677                        }
678                        Poll::Pending => {
679                            let (parts, body) = req.into_parts();
680                            let head = RequestHead {
681                                version: parts.version,
682                                subject: crate::proto::RequestLine(parts.method, parts.uri),
683                                headers: parts.headers,
684                                extensions: parts.extensions,
685                            };
686                            this.callback = Some(cb);
687                            Poll::Ready(Some(Ok((head, body))))
688                        }
689                    }
690                }
691                Poll::Ready(None) => {
692                    // user has dropped sender handle
693                    trace!("client tx closed");
694                    this.rx_closed = true;
695                    Poll::Ready(None)
696                }
697                Poll::Pending => Poll::Pending,
698            }
699        }
700
701        fn recv_msg(&mut self, msg: crate::Result<(Self::RecvItem, IncomingBody)>) -> crate::Result<()> {
702            match msg {
703                Ok((msg, body)) => {
704                    if let Some(cb) = self.callback.take() {
705                        let res = msg.into_response(body);
706                        cb.send(Ok(res));
707                        Ok(())
708                    } else {
709                        // Getting here is likely a bug! An error should have happened
710                        // in Conn::require_empty_read() before ever parsing a
711                        // full message!
712                        Err(crate::Error::new_unexpected_message())
713                    }
714                }
715                Err(err) => {
716                    if let Some(cb) = self.callback.take() {
717                        cb.send(Err(TrySendError {
718                            error: err,
719                            message: None,
720                        }));
721                        Ok(())
722                    } else if !self.rx_closed {
723                        self.rx.close();
724                        if let Some((req, cb)) = self.rx.try_recv() {
725                            trace!("canceling queued request with connection error: {}", err);
726                            // in this case, the message was never even started, so it's safe to tell
727                            // the user that the request was completely canceled
728                            cb.send(Err(TrySendError {
729                                error: crate::Error::new_canceled().with(err),
730                                message: Some(req),
731                            }));
732                            Ok(())
733                        } else {
734                            Err(err)
735                        }
736                    } else {
737                        Err(err)
738                    }
739                }
740            }
741        }
742
743        fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), ()>> {
744            match self.callback {
745                Some(ref mut cb) => match cb.poll_canceled(cx) {
746                    Poll::Ready(()) => {
747                        trace!("callback receiver has dropped");
748                        Poll::Ready(Err(()))
749                    }
750                    Poll::Pending => Poll::Ready(Ok(())),
751                },
752                None => Poll::Ready(Err(())),
753            }
754        }
755
756        fn should_poll(&self) -> bool {
757            self.callback.is_none()
758        }
759    }
760}
761
762#[cfg(test)]
763mod tests {
764    use super::*;
765    use crate::common::io::Compat;
766    use crate::proto::h1::ClientTransaction;
767    use std::time::Duration;
768
769    #[test]
770    fn client_read_bytes_before_writing_request() {
771        let _ = pretty_env_logger::try_init();
772
773        tokio_test::task::spawn(()).enter(|cx, _| {
774            let (io, mut handle) = tokio_test::io::Builder::new().build_with_handle();
775
776            // Block at 0 for now, but we will release this response before
777            // the request is ready to write later...
778            let (mut tx, rx) = crate::client::dispatch::channel();
779            let conn = Conn::<_, bytes::Bytes, ClientTransaction>::new(Compat::new(io));
780            let mut dispatcher = Dispatcher::new(Client::new(rx), conn);
781
782            // First poll is needed to allow tx to send...
783            assert!(Pin::new(&mut dispatcher).poll(cx).is_pending());
784
785            // Unblock our IO, which has a response before we've sent request!
786            //
787            handle.read(b"HTTP/1.1 200 OK\r\n\r\n");
788
789            let mut res_rx = tx
790                .try_send(crate::Request::new(IncomingBody::empty()))
791                .unwrap();
792
793            tokio_test::assert_ready_ok!(Pin::new(&mut dispatcher).poll(cx));
794            let err = tokio_test::assert_ready_ok!(Pin::new(&mut res_rx).poll(cx))
795                .expect_err("callback should send error");
796
797            match (err.error.is_canceled(), err.message.as_ref()) {
798                (true, Some(_)) => (),
799                _ => panic!("expected Canceled, got {:?}", err),
800            }
801        });
802    }
803
804    #[cfg(not(miri))]
805    #[tokio::test]
806    async fn client_flushing_is_not_ready_for_next_request() {
807        let _ = pretty_env_logger::try_init();
808
809        let (io, _handle) = tokio_test::io::Builder::new()
810            .write(b"POST / HTTP/1.1\r\ncontent-length: 4\r\n\r\n")
811            .read(b"HTTP/1.1 200 OK\r\ncontent-length: 0\r\n\r\n")
812            .wait(std::time::Duration::from_secs(2))
813            .build_with_handle();
814
815        let (mut tx, rx) = crate::client::dispatch::channel();
816        let mut conn = Conn::<_, bytes::Bytes, ClientTransaction>::new(Compat::new(io));
817        conn.set_write_strategy_queue();
818
819        let dispatcher = Dispatcher::new(Client::new(rx), conn);
820        let _dispatcher = tokio::spawn(async move { dispatcher.await });
821
822        let body = {
823            let (mut tx, body) = IncomingBody::new_channel(DecodedLength::new(4), false);
824            tx.try_send_data("reee".into()).unwrap();
825            body
826        };
827
828        let req = crate::Request::builder().method("POST").body(body).unwrap();
829
830        let res = tx.try_send(req).unwrap().await.expect("response");
831        drop(res);
832
833        assert!(!tx.is_ready());
834    }
835
836    #[cfg(not(miri))]
837    #[tokio::test]
838    async fn body_empty_chunks_ignored() {
839        let _ = pretty_env_logger::try_init();
840
841        let io = tokio_test::io::Builder::new()
842            // no reading or writing, just be blocked for the test...
843            .wait(Duration::from_secs(5))
844            .build();
845
846        let (mut tx, rx) = crate::client::dispatch::channel();
847        let conn = Conn::<_, bytes::Bytes, ClientTransaction>::new(Compat::new(io));
848        let mut dispatcher = tokio_test::task::spawn(Dispatcher::new(Client::new(rx), conn));
849
850        // First poll is needed to allow tx to send...
851        assert!(dispatcher.poll().is_pending());
852
853        let body = {
854            let (mut tx, body) = IncomingBody::channel();
855            tx.try_send_data("".into()).unwrap();
856            body
857        };
858
859        let _res_rx = tx.try_send(crate::Request::new(body)).unwrap();
860
861        // Ensure conn.write_body wasn't called with the empty chunk.
862        // If it is, it will trigger an assertion.
863        assert!(dispatcher.poll().is_pending());
864    }
865}