1use std::fmt;
2#[cfg(all(feature = "http1", any(feature = "client", feature = "server")))]
3use std::future::Future;
4use std::pin::Pin;
5use std::task::{Context, Poll};
6
7use bytes::Bytes;
8#[cfg(all(feature = "http1", any(feature = "client", feature = "server")))]
9use futures_channel::{mpsc, oneshot};
10#[cfg(all(
11 any(feature = "http1", feature = "http2"),
12 any(feature = "client", feature = "server")
13))]
14use futures_core::ready;
15#[cfg(all(feature = "http1", any(feature = "client", feature = "server")))]
16use futures_core::{stream::FusedStream, Stream}; #[cfg(all(feature = "http1", any(feature = "client", feature = "server")))]
18use http::HeaderMap;
19use http_body::{Body, Frame, SizeHint};
20
21#[cfg(all(
22 any(feature = "http1", feature = "http2"),
23 any(feature = "client", feature = "server")
24))]
25use super::DecodedLength;
26#[cfg(all(feature = "http1", any(feature = "client", feature = "server")))]
27use crate::common::watch;
28#[cfg(all(feature = "http2", any(feature = "client", feature = "server")))]
29use crate::proto::h2::ping;
30
31#[cfg(all(feature = "http1", any(feature = "client", feature = "server")))]
32type BodySender = mpsc::Sender<Result<Bytes, crate::Error>>;
33#[cfg(all(feature = "http1", any(feature = "client", feature = "server")))]
34type TrailersSender = oneshot::Sender<HeaderMap>;
35
36#[must_use = "streams do nothing unless polled"]
52pub struct Incoming {
53 kind: Kind,
54}
55
56enum Kind {
57 Empty,
58 #[cfg(all(feature = "http1", any(feature = "client", feature = "server")))]
59 Chan {
60 content_length: DecodedLength,
61 want_tx: watch::Sender,
62 data_rx: mpsc::Receiver<Result<Bytes, crate::Error>>,
63 trailers_rx: oneshot::Receiver<HeaderMap>,
64 },
65 #[cfg(all(feature = "http2", any(feature = "client", feature = "server")))]
66 H2 {
67 content_length: DecodedLength,
68 data_done: bool,
69 ping: ping::Recorder,
70 recv: h2::RecvStream,
71 },
72 #[cfg(feature = "ffi")]
73 Ffi(crate::ffi::UserBody),
74}
75
76#[must_use = "Sender does nothing unless sent on"]
90#[cfg(all(feature = "http1", any(feature = "client", feature = "server")))]
91pub(crate) struct Sender {
92 want_rx: watch::Receiver,
93 data_tx: BodySender,
94 trailers_tx: Option<TrailersSender>,
95}
96
97#[cfg(all(feature = "http1", any(feature = "client", feature = "server")))]
98const WANT_PENDING: usize = 1;
99#[cfg(all(feature = "http1", any(feature = "client", feature = "server")))]
100const WANT_READY: usize = 2;
101
102impl Incoming {
103 #[cfg(all(feature = "http1", any(feature = "client", feature = "server")))]
107 #[inline]
108 #[cfg(test)]
109 pub(crate) fn channel() -> (Sender, Incoming) {
110 Self::new_channel(DecodedLength::CHUNKED, false)
111 }
112
113 #[cfg(all(feature = "http1", any(feature = "client", feature = "server")))]
114 pub(crate) fn new_channel(content_length: DecodedLength, wanter: bool) -> (Sender, Incoming) {
115 let (data_tx, data_rx) = mpsc::channel(0);
116 let (trailers_tx, trailers_rx) = oneshot::channel();
117
118 let want = if wanter { WANT_PENDING } else { WANT_READY };
121
122 let (want_tx, want_rx) = watch::channel(want);
123
124 let tx = Sender {
125 want_rx,
126 data_tx,
127 trailers_tx: Some(trailers_tx),
128 };
129 let rx = Incoming::new(Kind::Chan {
130 content_length,
131 want_tx,
132 data_rx,
133 trailers_rx,
134 });
135
136 (tx, rx)
137 }
138
139 fn new(kind: Kind) -> Incoming {
140 Incoming { kind }
141 }
142
143 #[allow(dead_code)]
144 pub(crate) fn empty() -> Incoming {
145 Incoming::new(Kind::Empty)
146 }
147
148 #[cfg(feature = "ffi")]
149 pub(crate) fn ffi() -> Incoming {
150 Incoming::new(Kind::Ffi(crate::ffi::UserBody::new()))
151 }
152
153 #[cfg(all(feature = "http2", any(feature = "client", feature = "server")))]
154 pub(crate) fn h2(
155 recv: h2::RecvStream,
156 mut content_length: DecodedLength,
157 ping: ping::Recorder,
158 ) -> Self {
159 if !content_length.is_exact() && recv.is_end_stream() {
162 content_length = DecodedLength::ZERO;
163 }
164
165 Incoming::new(Kind::H2 {
166 data_done: false,
167 ping,
168 content_length,
169 recv,
170 })
171 }
172
173 #[cfg(feature = "ffi")]
174 pub(crate) fn as_ffi_mut(&mut self) -> &mut crate::ffi::UserBody {
175 if !matches!(self.kind, Kind::Ffi(_)) {
176 self.kind = Kind::Ffi(crate::ffi::UserBody::new());
177 }
178
179 match &mut self.kind {
180 Kind::Ffi(body) => body,
181 _ => unreachable!(),
182 }
183 }
184}
185
186impl Body for Incoming {
187 type Data = Bytes;
188 type Error = crate::Error;
189
190 fn poll_frame(
191 #[cfg_attr(
192 not(all(
193 any(feature = "http1", feature = "http2"),
194 any(feature = "client", feature = "server")
195 )),
196 allow(unused_mut)
197 )]
198 mut self: Pin<&mut Self>,
199 #[cfg_attr(
200 not(all(
201 any(feature = "http1", feature = "http2"),
202 any(feature = "client", feature = "server")
203 )),
204 allow(unused_variables)
205 )]
206 cx: &mut Context<'_>,
207 ) -> Poll<Option<Result<Frame<Self::Data>, Self::Error>>> {
208 match &mut self.kind {
209 Kind::Empty => Poll::Ready(None),
210 #[cfg(all(feature = "http1", any(feature = "client", feature = "server")))]
211 Kind::Chan {
212 content_length: len,
213 data_rx,
214 want_tx,
215 trailers_rx,
216 } => {
217 want_tx.send(WANT_READY);
218
219 if !data_rx.is_terminated() {
220 if let Some(chunk) = ready!(Pin::new(data_rx).poll_next(cx)?) {
221 len.sub_if(chunk.len() as u64);
222 return Poll::Ready(Some(Ok(Frame::data(chunk))));
223 }
224 }
225
226 match ready!(Pin::new(trailers_rx).poll(cx)) {
228 Ok(t) => Poll::Ready(Some(Ok(Frame::trailers(t)))),
229 Err(_) => Poll::Ready(None),
230 }
231 }
232 #[cfg(all(feature = "http2", any(feature = "client", feature = "server")))]
233 Kind::H2 {
234 data_done,
235 ping,
236 recv: h2,
237 content_length: len,
238 } => {
239 if !*data_done {
240 match ready!(h2.poll_data(cx)) {
241 Some(Ok(bytes)) => {
242 let _ = h2.flow_control().release_capacity(bytes.len());
243 len.sub_if(bytes.len() as u64);
244 ping.record_data(bytes.len());
245 return Poll::Ready(Some(Ok(Frame::data(bytes))));
246 }
247 Some(Err(e)) => {
248 if let Some(h2::Reason::NO_ERROR) = e.reason() {
249 return Poll::Ready(None);
253 } else {
254 return Poll::Ready(Some(Err(crate::Error::new_body(e))));
255 }
256 }
257 None => {
258 *data_done = true;
259 }
261 }
262 }
263
264 match ready!(h2.poll_trailers(cx)) {
266 Ok(t) => {
267 ping.record_non_data();
268 Poll::Ready(Ok(t.map(Frame::trailers)).transpose())
269 }
270 Err(e) => {
271 if let Some(h2::Reason::NO_ERROR) = e.reason() {
272 Poll::Ready(None)
276 } else {
277 Poll::Ready(Some(Err(crate::Error::new_h2(e))))
278 }
279 }
280 }
281 }
282
283 #[cfg(feature = "ffi")]
284 Kind::Ffi(body) => body.poll_data(cx),
285 }
286 }
287
288 fn is_end_stream(&self) -> bool {
289 match &self.kind {
290 Kind::Empty => true,
291 #[cfg(all(feature = "http1", any(feature = "client", feature = "server")))]
292 Kind::Chan { content_length, .. } => *content_length == DecodedLength::ZERO,
293 #[cfg(all(feature = "http2", any(feature = "client", feature = "server")))]
294 Kind::H2 { recv: h2, .. } => h2.is_end_stream(),
295 #[cfg(feature = "ffi")]
296 Kind::Ffi(..) => false,
297 }
298 }
299
300 fn size_hint(&self) -> SizeHint {
301 #[cfg(all(
302 any(feature = "http1", feature = "http2"),
303 any(feature = "client", feature = "server")
304 ))]
305 fn opt_len(decoded_length: DecodedLength) -> SizeHint {
306 if let Some(content_length) = decoded_length.into_opt() {
307 SizeHint::with_exact(content_length)
308 } else {
309 SizeHint::default()
310 }
311 }
312
313 match self.kind {
314 Kind::Empty => SizeHint::with_exact(0),
315 #[cfg(all(feature = "http1", any(feature = "client", feature = "server")))]
316 Kind::Chan { content_length, .. } => opt_len(content_length),
317 #[cfg(all(feature = "http2", any(feature = "client", feature = "server")))]
318 Kind::H2 { content_length, .. } => opt_len(content_length),
319 #[cfg(feature = "ffi")]
320 Kind::Ffi(..) => SizeHint::default(),
321 }
322 }
323}
324
325impl fmt::Debug for Incoming {
326 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
327 #[cfg(any(
328 all(
329 any(feature = "http1", feature = "http2"),
330 any(feature = "client", feature = "server")
331 ),
332 feature = "ffi"
333 ))]
334 #[derive(Debug)]
335 struct Streaming;
336 #[derive(Debug)]
337 struct Empty;
338
339 let mut builder = f.debug_tuple("Body");
340 match self.kind {
341 Kind::Empty => builder.field(&Empty),
342 #[cfg(any(
343 all(
344 any(feature = "http1", feature = "http2"),
345 any(feature = "client", feature = "server")
346 ),
347 feature = "ffi"
348 ))]
349 _ => builder.field(&Streaming),
350 };
351
352 builder.finish()
353 }
354}
355
356#[cfg(all(feature = "http1", any(feature = "client", feature = "server")))]
357impl Sender {
358 pub(crate) fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<crate::Result<()>> {
360 ready!(self.poll_want(cx)?);
362 self.data_tx
363 .poll_ready(cx)
364 .map_err(|_| crate::Error::new_closed())
365 }
366
367 fn poll_want(&mut self, cx: &mut Context<'_>) -> Poll<crate::Result<()>> {
368 match self.want_rx.load(cx) {
369 WANT_READY => Poll::Ready(Ok(())),
370 WANT_PENDING => Poll::Pending,
371 watch::CLOSED => Poll::Ready(Err(crate::Error::new_closed())),
372 unexpected => unreachable!("want_rx value: {}", unexpected),
373 }
374 }
375
376 #[cfg(test)]
377 async fn ready(&mut self) -> crate::Result<()> {
378 futures_util::future::poll_fn(|cx| self.poll_ready(cx)).await
379 }
380
381 #[cfg(test)]
383 #[allow(unused)]
384 pub(crate) async fn send_data(&mut self, chunk: Bytes) -> crate::Result<()> {
385 self.ready().await?;
386 self.data_tx
387 .try_send(Ok(chunk))
388 .map_err(|_| crate::Error::new_closed())
389 }
390
391 #[allow(unused)]
393 #[allow(clippy::unused_async_trait_impl)]
394 pub(crate) async fn send_trailers(&mut self, trailers: HeaderMap) -> crate::Result<()> {
395 let tx = match self.trailers_tx.take() {
396 Some(tx) => tx,
397 None => return Err(crate::Error::new_closed()),
398 };
399 tx.send(trailers).map_err(|_| crate::Error::new_closed())
400 }
401
402 #[cfg(feature = "http1")]
415 pub(crate) fn try_send_data(&mut self, chunk: Bytes) -> Result<(), Bytes> {
416 self.data_tx
417 .try_send(Ok(chunk))
418 .map_err(|err| err.into_inner().expect("just sent Ok"))
419 }
420
421 #[cfg(feature = "http1")]
422 pub(crate) fn try_send_trailers(
423 &mut self,
424 trailers: HeaderMap,
425 ) -> Result<(), Option<HeaderMap>> {
426 let tx = match self.trailers_tx.take() {
427 Some(tx) => tx,
428 None => return Err(None),
429 };
430
431 tx.send(trailers).map_err(Some)
432 }
433
434 #[cfg(test)]
435 pub(crate) fn abort(mut self) {
436 self.send_error(crate::Error::new_body_write_aborted());
437 }
438
439 pub(crate) fn send_error(&mut self, err: crate::Error) {
440 let _ = self
441 .data_tx
442 .clone()
444 .try_send(Err(err));
445 }
446}
447
448#[cfg(all(feature = "http1", any(feature = "client", feature = "server")))]
449impl fmt::Debug for Sender {
450 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
451 #[derive(Debug)]
452 struct Open;
453 #[derive(Debug)]
454 struct Closed;
455
456 let mut builder = f.debug_tuple("Sender");
457 match self.want_rx.peek() {
458 watch::CLOSED => builder.field(&Closed),
459 _ => builder.field(&Open),
460 };
461
462 builder.finish()
463 }
464}
465
466#[cfg(test)]
467mod tests {
468 #[cfg(all(feature = "http1", any(feature = "client", feature = "server")))]
469 use std::mem;
470 #[cfg(all(feature = "http1", any(feature = "client", feature = "server")))]
471 use std::task::Poll;
472
473 #[cfg(all(feature = "http1", any(feature = "client", feature = "server")))]
474 use super::{Body, Incoming, SizeHint};
475 #[cfg(all(feature = "http1", any(feature = "client", feature = "server")))]
476 use super::{DecodedLength, Sender};
477 #[cfg(all(feature = "http1", any(feature = "client", feature = "server")))]
478 use http_body_util::BodyExt;
479
480 #[cfg(all(feature = "http1", any(feature = "client", feature = "server")))]
481 #[test]
482 fn test_size_of() {
483 let body_size = mem::size_of::<Incoming>();
487 let body_expected_size = mem::size_of::<u64>() * 5;
488 assert!(
489 body_size <= body_expected_size,
490 "Body size = {} <= {}",
491 body_size,
492 body_expected_size,
493 );
494
495 assert_eq!(
496 mem::size_of::<Sender>(),
497 mem::size_of::<usize>() * 5,
498 "Sender"
499 );
500
501 assert_eq!(
502 mem::size_of::<Sender>(),
503 mem::size_of::<Option<Sender>>(),
504 "Option<Sender>"
505 );
506 }
507
508 #[cfg(all(feature = "http1", any(feature = "client", feature = "server")))]
509 #[test]
510 fn size_hint() {
511 fn eq(body: Incoming, b: SizeHint, note: &str) {
512 let a = body.size_hint();
513 assert_eq!(a.lower(), b.lower(), "lower for {:?}", note);
514 assert_eq!(a.upper(), b.upper(), "upper for {:?}", note);
515 }
516
517 eq(Incoming::empty(), SizeHint::with_exact(0), "empty");
518
519 eq(Incoming::channel().1, SizeHint::new(), "channel");
520
521 eq(
522 Incoming::new_channel(DecodedLength::new(4), false).1,
523 SizeHint::with_exact(4),
524 "channel with length",
525 );
526 }
527
528 #[cfg(all(feature = "http1", any(feature = "client", feature = "server")))]
529 #[cfg(not(miri))]
530 #[tokio::test]
531 async fn channel_abort() {
532 let (tx, mut rx) = Incoming::channel();
533
534 tx.abort();
535
536 let err = rx.frame().await.unwrap().unwrap_err();
537 assert!(err.is_body_write_aborted(), "{:?}", err);
538 }
539
540 #[cfg(all(feature = "http1", any(feature = "client", feature = "server")))]
541 #[cfg(all(not(miri), feature = "http1"))]
542 #[tokio::test]
543 async fn channel_abort_when_buffer_is_full() {
544 let (mut tx, mut rx) = Incoming::channel();
545
546 tx.try_send_data("chunk 1".into()).expect("send 1");
547 tx.abort();
549
550 let chunk1 = rx
551 .frame()
552 .await
553 .expect("item 1")
554 .expect("chunk 1")
555 .into_data()
556 .unwrap();
557 assert_eq!(chunk1, "chunk 1");
558
559 let err = rx.frame().await.unwrap().unwrap_err();
560 assert!(err.is_body_write_aborted(), "{:?}", err);
561 }
562
563 #[cfg(feature = "http1")]
564 #[test]
565 fn channel_buffers_one() {
566 let (mut tx, _rx) = Incoming::channel();
567
568 tx.try_send_data("chunk 1".into()).expect("send 1");
569
570 let chunk2 = tx.try_send_data("chunk 2".into()).expect_err("send 2");
572 assert_eq!(chunk2, "chunk 2");
573 }
574
575 #[cfg(all(feature = "http1", any(feature = "client", feature = "server")))]
576 #[cfg(not(miri))]
577 #[tokio::test]
578 async fn channel_empty() {
579 let (_, mut rx) = Incoming::channel();
580
581 assert!(rx.frame().await.is_none());
582 }
583
584 #[cfg(all(feature = "http1", any(feature = "client", feature = "server")))]
585 #[test]
586 fn channel_ready() {
587 let (mut tx, _rx) = Incoming::new_channel(DecodedLength::CHUNKED, false);
588
589 let mut tx_ready = tokio_test::task::spawn(tx.ready());
590
591 assert!(tx_ready.poll().is_ready(), "tx is ready immediately");
592 }
593
594 #[cfg(all(feature = "http1", any(feature = "client", feature = "server")))]
595 #[test]
596 fn channel_wanter() {
597 let (mut tx, mut rx) =
598 Incoming::new_channel(DecodedLength::CHUNKED, true);
599
600 let mut tx_ready = tokio_test::task::spawn(tx.ready());
601 let mut rx_data = tokio_test::task::spawn(rx.frame());
602
603 assert!(
604 tx_ready.poll().is_pending(),
605 "tx isn't ready before rx has been polled"
606 );
607
608 assert!(rx_data.poll().is_pending(), "poll rx.data");
609 assert!(tx_ready.is_woken(), "rx poll wakes tx");
610
611 assert!(
612 tx_ready.poll().is_ready(),
613 "tx is ready after rx has been polled"
614 );
615 }
616
617 #[cfg(all(feature = "http1", any(feature = "client", feature = "server")))]
618 #[test]
619 fn channel_notices_closure() {
620 let (mut tx, rx) = Incoming::new_channel(DecodedLength::CHUNKED, true);
621
622 let mut tx_ready = tokio_test::task::spawn(tx.ready());
623
624 assert!(
625 tx_ready.poll().is_pending(),
626 "tx isn't ready before rx has been polled"
627 );
628
629 drop(rx);
630 assert!(tx_ready.is_woken(), "dropping rx wakes tx");
631
632 match &tx_ready.poll() {
633 Poll::Ready(Err(e)) if e.is_closed() => (),
634 unexpected => panic!("tx poll ready unexpected: {:?}", unexpected),
635 }
636 }
637}