1use std::task::{Context, Poll};
2#[cfg(feature = "http2")]
3use std::{future::Future, pin::Pin};
4
5#[cfg(feature = "http2")]
6use http::{Request, Response};
7#[cfg(feature = "http2")]
8use http_body::Body;
9#[cfg(feature = "http2")]
10use pin_project_lite::pin_project;
11use tokio::sync::{mpsc, oneshot};
12
13#[cfg(feature = "http2")]
14use crate::{body::Incoming, proto::h2::client::ResponseFutMap};
15
16pub(crate) type RetryPromise<T, U> = oneshot::Receiver<Result<U, TrySendError<T>>>;
17pub(crate) type Promise<T> = oneshot::Receiver<Result<T, crate::Error>>;
18
19#[derive(Debug)]
26pub struct TrySendError<T> {
27 pub(crate) error: crate::Error,
28 pub(crate) message: Option<T>,
29}
30
31pub(crate) fn channel<T, U>() -> (Sender<T, U>, Receiver<T, U>) {
32 let (tx, rx) = mpsc::unbounded_channel();
33 let (giver, taker) = want::new();
34 let tx = Sender {
35 #[cfg(feature = "http1")]
36 buffered_once: false,
37 giver,
38 inner: tx,
39 };
40 let rx = Receiver { inner: rx, taker };
41 (tx, rx)
42}
43
44pub(crate) struct Sender<T, U> {
49 #[cfg(feature = "http1")]
53 buffered_once: bool,
54 giver: want::Giver,
59 inner: mpsc::UnboundedSender<Envelope<T, U>>,
61}
62
63#[cfg(feature = "http2")]
68pub(crate) struct UnboundedSender<T, U> {
69 giver: want::SharedGiver,
71 inner: mpsc::UnboundedSender<Envelope<T, U>>,
72}
73
74impl<T, U> Sender<T, U> {
75 #[cfg(feature = "http1")]
76 pub(crate) fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<crate::Result<()>> {
77 self.giver
78 .poll_want(cx)
79 .map_err(|_| crate::Error::new_closed())
80 }
81
82 #[cfg(feature = "http1")]
83 pub(crate) fn is_ready(&self) -> bool {
84 self.giver.is_wanting()
85 }
86
87 #[cfg(feature = "http1")]
88 pub(crate) fn is_closed(&self) -> bool {
89 self.giver.is_canceled()
90 }
91
92 #[cfg(feature = "http1")]
93 fn can_send(&mut self) -> bool {
94 if self.giver.give() || !self.buffered_once {
95 self.buffered_once = true;
100 true
101 } else {
102 false
103 }
104 }
105
106 #[cfg(feature = "http1")]
107 pub(crate) fn try_send(&mut self, val: T) -> Result<RetryPromise<T, U>, T> {
108 if !self.can_send() {
109 return Err(val);
110 }
111 let (tx, rx) = oneshot::channel();
112 self.inner
113 .send(Envelope(Some((val, Callback::Retry(Some(tx))))))
114 .map(move |()| rx)
115 .map_err(|mut e| (e.0).0.take().expect("envelope not dropped").0)
116 }
117
118 #[cfg(feature = "http1")]
119 pub(crate) fn send(&mut self, val: T) -> Result<Promise<U>, T> {
120 if !self.can_send() {
121 return Err(val);
122 }
123 let (tx, rx) = oneshot::channel();
124 self.inner
125 .send(Envelope(Some((val, Callback::NoRetry(Some(tx))))))
126 .map(move |()| rx)
127 .map_err(|mut e| (e.0).0.take().expect("envelope not dropped").0)
128 }
129
130 #[cfg(feature = "http2")]
131 pub(crate) fn unbound(self) -> UnboundedSender<T, U> {
132 UnboundedSender {
133 giver: self.giver.shared(),
134 inner: self.inner,
135 }
136 }
137}
138
139#[cfg(feature = "http2")]
140impl<T, U> UnboundedSender<T, U> {
141 pub(crate) fn is_ready(&self) -> bool {
142 !self.giver.is_canceled()
143 }
144
145 pub(crate) fn is_closed(&self) -> bool {
146 self.giver.is_canceled()
147 }
148
149 pub(crate) fn try_send(&mut self, val: T) -> Result<RetryPromise<T, U>, T> {
150 let (tx, rx) = oneshot::channel();
151 self.inner
152 .send(Envelope(Some((val, Callback::Retry(Some(tx))))))
153 .map(move |()| rx)
154 .map_err(|mut e| (e.0).0.take().expect("envelope not dropped").0)
155 }
156
157 pub(crate) fn send(&mut self, val: T) -> Result<Promise<U>, T> {
158 let (tx, rx) = oneshot::channel();
159 self.inner
160 .send(Envelope(Some((val, Callback::NoRetry(Some(tx))))))
161 .map(move |()| rx)
162 .map_err(|mut e| (e.0).0.take().expect("envelope not dropped").0)
163 }
164}
165
166#[cfg(feature = "http2")]
167impl<T, U> Clone for UnboundedSender<T, U> {
168 fn clone(&self) -> Self {
169 UnboundedSender {
170 giver: self.giver.clone(),
171 inner: self.inner.clone(),
172 }
173 }
174}
175
176pub(crate) struct Receiver<T, U> {
177 inner: mpsc::UnboundedReceiver<Envelope<T, U>>,
178 taker: want::Taker,
179}
180
181impl<T, U> Receiver<T, U> {
182 pub(crate) fn poll_recv(&mut self, cx: &mut Context<'_>) -> Poll<Option<(T, Callback<T, U>)>> {
183 match self.inner.poll_recv(cx) {
184 Poll::Ready(item) => {
185 self.taker.unwant();
191 Poll::Ready(item.map(|mut env| env.0.take().expect("envelope not dropped")))
192 }
193 Poll::Pending => {
194 self.taker.want();
195 Poll::Pending
196 }
197 }
198 }
199
200 #[cfg(feature = "http1")]
201 pub(crate) fn close(&mut self) {
202 self.taker.cancel();
203 self.inner.close();
204 }
205
206 #[cfg(feature = "http1")]
207 pub(crate) fn try_recv(&mut self) -> Option<(T, Callback<T, U>)> {
208 match crate::common::task::now_or_never(self.inner.recv()) {
209 Some(Some(mut env)) => env.0.take(),
210 _ => None,
211 }
212 }
213}
214
215impl<T, U> Drop for Receiver<T, U> {
216 fn drop(&mut self) {
217 self.taker.cancel();
220 }
221}
222
223struct Envelope<T, U>(Option<(T, Callback<T, U>)>);
224
225impl<T, U> Drop for Envelope<T, U> {
226 fn drop(&mut self) {
227 if let Some((val, cb)) = self.0.take() {
228 cb.send(Err(TrySendError {
229 error: crate::Error::new_canceled().with("connection closed"),
230 message: Some(val),
231 }));
232 }
233 }
234}
235
236pub(crate) enum Callback<T, U> {
237 #[allow(unused)]
238 Retry(Option<oneshot::Sender<Result<U, TrySendError<T>>>>),
239 NoRetry(Option<oneshot::Sender<Result<U, crate::Error>>>),
240}
241
242impl<T, U> Drop for Callback<T, U> {
243 fn drop(&mut self) {
244 match self {
245 Callback::Retry(tx) => {
246 if let Some(tx) = tx.take() {
247 let _ = tx.send(Err(TrySendError {
248 error: dispatch_gone(),
249 message: None,
250 }));
251 }
252 }
253 Callback::NoRetry(tx) => {
254 if let Some(tx) = tx.take() {
255 let _ = tx.send(Err(dispatch_gone()));
256 }
257 }
258 }
259 }
260}
261
262#[cold]
263fn dispatch_gone() -> crate::Error {
264 crate::Error::new_user_dispatch_gone().with(if std::thread::panicking() {
266 "user code panicked"
267 } else {
268 "runtime dropped the dispatch task"
269 })
270}
271
272impl<T, U> Callback<T, U> {
273 #[cfg(feature = "http2")]
274 pub(crate) fn is_canceled(&self) -> bool {
275 match self {
276 Callback::Retry(Some(tx)) => tx.is_closed(),
277 Callback::NoRetry(Some(tx)) => tx.is_closed(),
278 _ => unreachable!(),
279 }
280 }
281
282 pub(crate) fn poll_canceled(&mut self, cx: &mut Context<'_>) -> Poll<()> {
283 match self {
284 Callback::Retry(Some(tx)) => tx.poll_closed(cx),
285 Callback::NoRetry(Some(tx)) => tx.poll_closed(cx),
286 _ => unreachable!(),
287 }
288 }
289
290 pub(crate) fn send(mut self, val: Result<U, TrySendError<T>>) {
291 match &mut self {
292 Callback::Retry(tx) => {
293 let _ = tx
294 .take()
295 .expect("callback sender not dropped before send")
296 .send(val);
297 }
298 Callback::NoRetry(tx) => {
299 let _ = tx
300 .take()
301 .expect("callback sender not dropped before send")
302 .send(val.map_err(|e| e.error));
303 }
304 }
305 }
306}
307
308impl<T> TrySendError<T> {
309 pub fn take_message(&mut self) -> Option<T> {
315 self.message.take()
316 }
317
318 pub fn message(&self) -> Option<&T> {
324 self.message.as_ref()
325 }
326
327 pub fn into_error(self) -> crate::Error {
329 self.error
330 }
331
332 pub fn error(&self) -> &crate::Error {
334 &self.error
335 }
336}
337
338#[cfg(feature = "http2")]
339pin_project! {
340 pub struct SendWhen<B, E>
341 where
342 B: Body,
343 B: 'static,
344 {
345 #[pin]
346 pub(crate) when: ResponseFutMap<B, E>,
347 #[pin]
348 pub(crate) call_back: Option<Callback<Request<B>, Response<Incoming>>>,
349 }
350}
351
352#[cfg(feature = "http2")]
353impl<B, E> Future for SendWhen<B, E>
354where
355 B: Body + 'static,
356 E: crate::rt::bounds::Http2UpgradedExec<B::Data>,
357{
358 type Output = ();
359
360 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
361 let mut this = self.project();
362
363 let mut call_back = this.call_back.take().expect("polled after complete");
364
365 match Pin::new(&mut this.when).poll(cx) {
366 Poll::Ready(Ok(res)) => {
367 call_back.send(Ok(res));
368 Poll::Ready(())
369 }
370 Poll::Pending => {
371 match call_back.poll_canceled(cx) {
373 Poll::Ready(v) => v,
374 Poll::Pending => {
375 this.call_back.set(Some(call_back));
377 return Poll::Pending;
378 }
379 }
380 trace!("send_when canceled");
381 this.when.as_mut().cancel();
384 Poll::Ready(())
385 }
386 Poll::Ready(Err((error, message))) => {
387 call_back.send(Err(TrySendError { error, message }));
388 Poll::Ready(())
389 }
390 }
391 }
392}
393
394#[cfg(test)]
395mod tests {
396 #[cfg(feature = "nightly")]
397 extern crate test;
398
399 use std::future::Future;
400 use std::pin::Pin;
401 use std::task::{Context, Poll};
402
403 use super::{channel, Callback, Receiver};
404
405 #[derive(Debug)]
406 struct Custom(#[allow(dead_code)] i32);
407
408 impl<T, U> Future for Receiver<T, U> {
409 type Output = Option<(T, Callback<T, U>)>;
410
411 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
412 self.poll_recv(cx)
413 }
414 }
415
416 struct PollOnce<'fut, F>(&'fut mut F);
418
419 impl<F, T> Future for PollOnce<'_, F>
420 where
421 F: Future<Output = T> + Unpin,
422 {
423 type Output = Option<()>;
424
425 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
426 match Pin::new(&mut self.0).poll(cx) {
427 Poll::Ready(_) => Poll::Ready(Some(())),
428 Poll::Pending => Poll::Ready(None),
429 }
430 }
431 }
432
433 #[cfg(not(miri))]
434 #[tokio::test]
435 async fn drop_receiver_sends_cancel_errors() {
436 let _ = pretty_env_logger::try_init();
437
438 let (mut tx, mut rx) = channel::<Custom, ()>();
439
440 assert!(PollOnce(&mut rx).await.is_none(), "rx empty");
442
443 let promise = tx.try_send(Custom(43)).unwrap();
444 drop(rx);
445
446 let fulfilled = promise.await;
447 let err = fulfilled
448 .expect("fulfilled")
449 .expect_err("promise should error");
450 match (err.error.is_canceled(), err.message) {
451 (true, Some(_)) => (),
452 e => panic!("expected Error::Cancel(_), found {:?}", e),
453 }
454 }
455
456 #[cfg(not(miri))]
457 #[tokio::test]
458 async fn sender_checks_for_want_on_send() {
459 let (mut tx, mut rx) = channel::<Custom, ()>();
460
461 tx.try_send(Custom(1)).expect("1 buffered");
463 tx.try_send(Custom(2)).expect_err("2 not ready");
464
465 assert!(PollOnce(&mut rx).await.is_some(), "rx once");
466
467 tx.try_send(Custom(2)).expect_err("2 still not ready");
470
471 assert!(PollOnce(&mut rx).await.is_none(), "rx empty");
472
473 tx.try_send(Custom(2)).expect("2 ready");
474 }
475
476 #[cfg(feature = "http2")]
477 #[test]
478 fn unbounded_sender_doesnt_bound_on_want() {
479 let (tx, rx) = channel::<Custom, ()>();
480 let mut tx = tx.unbound();
481
482 tx.try_send(Custom(1)).unwrap();
483 tx.try_send(Custom(2)).unwrap();
484 tx.try_send(Custom(3)).unwrap();
485
486 drop(rx);
487
488 tx.try_send(Custom(4)).unwrap_err();
489 }
490
491 #[cfg(feature = "nightly")]
492 #[bench]
493 fn giver_queue_throughput(b: &mut test::Bencher) {
494 use crate::{body::Incoming, Request, Response};
495
496 let rt = tokio::runtime::Builder::new_current_thread()
497 .build()
498 .unwrap();
499 let (mut tx, mut rx) = channel::<Request<Incoming>, Response<Incoming>>();
500
501 b.iter(move || {
502 tx.send(Request::new(Incoming::empty())).unwrap();
503 rt.block_on(async {
504 loop {
505 let poll_once = PollOnce(&mut rx);
506 let opt = poll_once.await;
507 if opt.is_none() {
508 break;
509 }
510 }
511 });
512 })
513 }
514
515 #[cfg(feature = "nightly")]
516 #[bench]
517 fn giver_queue_not_ready(b: &mut test::Bencher) {
518 let rt = tokio::runtime::Builder::new_current_thread()
519 .build()
520 .unwrap();
521 let (_tx, mut rx) = channel::<i32, ()>();
522 b.iter(move || {
523 rt.block_on(async {
524 let poll_once = PollOnce(&mut rx);
525 assert!(poll_once.await.is_none());
526 });
527 })
528 }
529
530 #[cfg(feature = "nightly")]
531 #[bench]
532 fn giver_queue_cancel(b: &mut test::Bencher) {
533 let (_tx, mut rx) = channel::<i32, ()>();
534
535 b.iter(move || {
536 rx.taker.cancel();
537 })
538 }
539}