noq/recv_stream.rs
1use std::{
2 future::{Future, poll_fn},
3 io,
4 pin::Pin,
5 task::{Context, Poll, ready},
6};
7
8use bytes::Bytes;
9use proto::{Chunk, Chunks, ClosedStream, ConnectionError, ReadableError, StreamId};
10use thiserror::Error;
11use tokio::io::ReadBuf;
12
13use crate::{VarInt, connection::ConnectionRef};
14
15/// A stream that can only be used to receive data
16///
17/// `stop(0)` is implicitly called on drop unless:
18/// - A variant of [`ReadError`] has been yielded by a read call
19/// - [`stop()`] was called explicitly
20///
21/// # Cancellation
22///
23/// A `read` method is said to be *cancel-safe* when dropping its future before the future becomes
24/// ready cannot lead to loss of stream data. This is true of methods which succeed immediately when
25/// any progress is made, and is not true of methods which might need to perform multiple reads
26/// internally before succeeding. Each `read` method documents whether it is cancel-safe.
27///
28/// # Common issues
29///
30/// ## Data never received on a locally-opened stream
31///
32/// Peers are not notified of streams until they or a later-numbered stream are used to send
33/// data. If a bidirectional stream is locally opened but never used to send, then the peer may
34/// never see it. Application protocols should always arrange for the endpoint which will first
35/// transmit on a stream to be the endpoint responsible for opening it.
36///
37/// ## Data never received on a remotely-opened stream
38///
39/// Verify that the stream you are receiving is the same one that the server is sending on, e.g. by
40/// logging the [`id`] of each. Streams are always accepted in the same order as they are created,
41/// i.e. ascending order by [`StreamId`]. For example, even if a sender first transmits on
42/// bidirectional stream 1, the first stream yielded by [`Connection::accept_bi`] on the receiver
43/// will be bidirectional stream 0.
44///
45/// [`ReadError`]: crate::ReadError
46/// [`stop()`]: RecvStream::stop
47/// [`SendStream::finish`]: crate::SendStream::finish
48/// [`WriteError::Stopped`]: crate::WriteError::Stopped
49/// [`id`]: RecvStream::id
50/// [`Connection::accept_bi`]: crate::Connection::accept_bi
51#[derive(Debug)]
52pub struct RecvStream {
53 conn: ConnectionRef,
54 stream: StreamId,
55 is_0rtt: bool,
56 all_data_read: bool,
57 reset: Option<VarInt>,
58}
59
60impl RecvStream {
61 pub(crate) fn new(conn: ConnectionRef, stream: StreamId, is_0rtt: bool) -> Self {
62 Self {
63 conn,
64 stream,
65 is_0rtt,
66 all_data_read: false,
67 reset: None,
68 }
69 }
70
71 /// Read data contiguously from the stream.
72 ///
73 /// Yields the number of bytes read into `buf` on success, or `None` if the stream was finished.
74 ///
75 /// This operation is cancel-safe.
76 pub async fn read(&mut self, buf: &mut [u8]) -> Result<Option<usize>, ReadError> {
77 Read {
78 stream: self,
79 buf: ReadBuf::new(buf),
80 }
81 .await
82 }
83
84 /// Read an exact number of bytes contiguously from the stream.
85 ///
86 /// See [`read()`] for details. This operation is *not* cancel-safe.
87 ///
88 /// [`read()`]: RecvStream::read
89 pub async fn read_exact(&mut self, buf: &mut [u8]) -> Result<(), ReadExactError> {
90 ReadExact {
91 stream: self,
92 buf: ReadBuf::new(buf),
93 }
94 .await
95 }
96
97 /// Attempts to read from the stream into the provided buffer
98 ///
99 /// On success, returns `Poll::Ready(Ok(num_bytes_read))` and places data into `buf`. If this
100 /// returns zero bytes read (and `buf` has a non-zero length), that indicates that the remote
101 /// side has [`finish`]ed the stream and the local side has already read all bytes.
102 ///
103 /// If no data is available for reading, this returns `Poll::Pending` and arranges for the
104 /// current task (via `cx.waker()`) to be notified when the stream becomes readable or is
105 /// closed.
106 ///
107 /// [`finish`]: crate::SendStream::finish
108 pub fn poll_read(
109 &mut self,
110 cx: &mut Context<'_>,
111 buf: &mut [u8],
112 ) -> Poll<Result<usize, ReadError>> {
113 let mut buf = ReadBuf::new(buf);
114 ready!(self.poll_read_buf(cx, &mut buf))?;
115 Poll::Ready(Ok(buf.filled().len()))
116 }
117
118 /// Attempts to read from the stream into the provided buffer, which may be uninitialized
119 ///
120 /// On success, returns `Poll::Ready(Ok(()))` and places data into the unfilled portion of
121 /// `buf`. If this does not write any bytes to `buf` (and `buf.remaining()` is non-zero), that
122 /// indicates that the remote side has [`finish`]ed the stream and the local side has already
123 /// read all bytes.
124 ///
125 /// If no data is available for reading, this returns `Poll::Pending` and arranges for the
126 /// current task (via `cx.waker()`) to be notified when the stream becomes readable or is
127 /// closed.
128 ///
129 /// [`finish`]: crate::SendStream::finish
130 pub(crate) fn poll_read_buf(
131 &mut self,
132 cx: &mut Context<'_>,
133 buf: &mut ReadBuf<'_>,
134 ) -> Poll<Result<(), ReadError>> {
135 if buf.remaining() == 0 {
136 return Poll::Ready(Ok(()));
137 }
138
139 self.poll_read_generic(cx, true, |chunks| {
140 let mut read = false;
141 loop {
142 if buf.remaining() == 0 {
143 // We know `read` is `true` because `buf.remaining()` was not 0 before
144 return ReadStatus::Readable(());
145 }
146
147 match chunks.next(buf.remaining()) {
148 Ok(Some(chunk)) => {
149 buf.put_slice(&chunk.bytes);
150 read = true;
151 }
152 res => return (if read { Some(()) } else { None }, res.err()).into(),
153 }
154 }
155 })
156 .map(|res| res.map(|_| ()))
157 }
158
159 /// Reads the next segment of data as zero-copy [`Bytes`].
160 ///
161 /// Yields `None` if the stream was finished. Otherwise, yields the next segment of data. The
162 /// chunk's offset will be immediately after the last data yielded by [`RecvStream::read`] or
163 /// [`RecvStream::read_chunk`]; use [`bytes_read()`](Self::bytes_read) to query that offset
164 /// explicitly.
165 ///
166 /// For unordered reads, convert the stream into an unordered stream using
167 /// [`Self::into_unordered`].
168 ///
169 /// Slightly more efficient than [`RecvStream::read`] due to not copying. Chunk boundaries do
170 /// not correspond to peer writes, and hence cannot be used as framing.
171 ///
172 /// This operation is cancel-safe.
173 pub async fn read_chunk(&mut self, max_length: usize) -> Result<Option<Bytes>, ReadError> {
174 Ok(ReadChunk {
175 stream: self,
176 max_length,
177 ordered: true,
178 }
179 .await?
180 .map(|chunk| chunk.bytes))
181 }
182
183 /// Attempts to read a chunk from the stream.
184 ///
185 /// On success, returns `Poll::Ready(Ok(Some(chunk)))`. If `Poll::Ready(Ok(None))`
186 /// is returned, it implies that EOF has been reached.
187 ///
188 /// If no data is available for reading, the method returns `Poll::Pending`
189 /// and arranges for the current task (via cx.waker()) to receive a notification
190 /// when the stream becomes readable or is closed.
191 fn poll_read_chunk(
192 &mut self,
193 cx: &mut Context<'_>,
194 max_length: usize,
195 ordered: bool,
196 ) -> Poll<Result<Option<Chunk>, ReadError>> {
197 self.poll_read_generic(cx, ordered, |chunks| match chunks.next(max_length) {
198 Ok(Some(chunk)) => ReadStatus::Readable(chunk),
199 res => (None, res.err()).into(),
200 })
201 }
202
203 /// Reads the next segments of data.
204 ///
205 /// Fills `bufs` with the segments of data beginning immediately after the last data yielded
206 /// by [`read`](Self::read), [`read_chunk`](Self::read_chunk), or
207 /// [`read_many_chunks`](Self::read_many_chunks), or `None` if the stream was finished.
208 ///
209 /// Slightly more efficient than [`read`](Self::read) due to not copying. Chunk boundaries do
210 /// not correspond to peer writes, and hence cannot be used as framing.
211 ///
212 /// This operation is cancel-safe.
213 pub async fn read_many_chunks(
214 &mut self,
215 bufs: &mut [Bytes],
216 ) -> Result<Option<usize>, ReadError> {
217 ReadChunks { stream: self, bufs }.await
218 }
219
220 /// Foundation of [`Self::read_many_chunks`]
221 fn poll_read_chunks(
222 &mut self,
223 cx: &mut Context<'_>,
224 bufs: &mut [Bytes],
225 ) -> Poll<Result<Option<usize>, ReadError>> {
226 if bufs.is_empty() {
227 return Poll::Ready(Ok(Some(0)));
228 }
229
230 self.poll_read_generic(cx, true, |chunks| {
231 let mut read = 0;
232 loop {
233 if read >= bufs.len() {
234 // We know `read > 0` because `bufs` cannot be empty here
235 return ReadStatus::Readable(read);
236 }
237
238 match chunks.next(usize::MAX) {
239 Ok(Some(chunk)) => {
240 bufs[read] = chunk.bytes;
241 read += 1;
242 }
243 res => return (if read == 0 { None } else { Some(read) }, res.err()).into(),
244 }
245 }
246 })
247 }
248
249 /// Convenience method to read all remaining data into a buffer
250 ///
251 /// Fails with [`ReadToEndError::TooLong`] on reading more than `size_limit` bytes, discarding
252 /// all data read. Uses unordered reads to be more efficient than using `AsyncRead` would
253 /// allow. `size_limit` should be set to limit worst-case memory use.
254 ///
255 /// If unordered reads have already been made, the resulting buffer may have gaps containing
256 /// arbitrary data.
257 ///
258 /// This operation is *not* cancel-safe.
259 ///
260 /// [`ReadToEndError::TooLong`]: crate::ReadToEndError::TooLong
261 pub async fn read_to_end(&mut self, size_limit: usize) -> Result<Vec<u8>, ReadToEndError> {
262 ReadToEnd {
263 stream: self,
264 size_limit,
265 read: Vec::new(),
266 start: u64::MAX,
267 end: 0,
268 }
269 .await
270 }
271
272 /// Stop accepting data
273 ///
274 /// Discards unread data and notifies the peer to stop transmitting. Once stopped, further
275 /// attempts to operate on a stream will yield `ClosedStream` errors.
276 pub fn stop(&mut self, error_code: VarInt) -> Result<(), ClosedStream> {
277 let mut conn = self.conn.lock_and_wake("RecvStream::stop");
278 if self.is_0rtt && conn.check_0rtt().is_err() {
279 conn.skip_waking();
280 return Ok(());
281 }
282 conn.inner.recv_stream(self.stream).stop(error_code)?;
283 self.all_data_read = true;
284 // Clean up shared state that might be left over from a cancelled read
285 // operation, so `drop` doesn't have to
286 conn.blocked_readers.remove(&self.stream);
287 Ok(())
288 }
289
290 /// Check if this stream predates completion of the handshake on an incoming connection.
291 ///
292 /// True only if the stream was accepted before the handshake completed, which is only possible
293 /// if you successfully called [`Connecting::into_0rtt`](crate::Connecting::into_0rtt) and the
294 /// client chose to send 0-RTT data.
295 ///
296 /// Under those conditions, depending on cryptographic layer configuration, 0-RTT application
297 /// data may be a replay attack. To guard against this, applications should not execute
298 /// non-idempotent operations until
299 /// [`Connection::authenticated`](crate::Connection::authenticated) succeeds.
300 pub fn is_0rtt(&self) -> bool {
301 self.is_0rtt
302 }
303
304 /// Get the identity of this stream
305 pub fn id(&self) -> StreamId {
306 self.stream
307 }
308
309 /// Returns the number of bytes read from this stream.
310 ///
311 /// This is the offset of the next byte to be read, i.e. the length of the contiguous
312 /// prefix of the stream consumed by the application.
313 pub fn bytes_read(&self) -> Result<u64, ClosedStream> {
314 let mut conn = self.conn.lock_without_waking("RecvStream::bytes_read");
315 conn.inner.recv_stream(self.stream).bytes_read()
316 }
317
318 /// Completes when the stream has been reset by the peer or otherwise closed
319 ///
320 /// Yields `Some` with the reset error code when the stream is reset by the peer. Yields `None`
321 /// when the stream was previously [`stop()`](Self::stop)ed, or when the stream was
322 /// [`finish()`](crate::SendStream::finish)ed by the peer and all data has been received, after
323 /// which it is no longer meaningful for the stream to be reset.
324 ///
325 /// This operation is cancel-safe.
326 pub async fn received_reset(&mut self) -> Result<Option<VarInt>, ResetError> {
327 poll_fn(|cx| {
328 let mut conn = self.conn.lock_without_waking("RecvStream::reset");
329 if self.is_0rtt && conn.check_0rtt().is_err() {
330 return Poll::Ready(Err(ResetError::ZeroRttRejected));
331 }
332
333 if let Some(code) = self.reset {
334 return Poll::Ready(Ok(Some(code)));
335 }
336
337 match conn.inner.recv_stream(self.stream).received_reset() {
338 Err(_) => Poll::Ready(Ok(None)),
339 Ok(Some(error_code)) => {
340 // Stream state has just now been freed, so the connection may need to issue new
341 // stream ID flow control credit
342 conn.wake();
343 Poll::Ready(Ok(Some(error_code)))
344 }
345 Ok(None) => {
346 if let Some(e) = &conn.error {
347 return Poll::Ready(Err(e.clone().into()));
348 }
349 // Resets always notify readers, since a reset is an immediate read error. We
350 // could introduce a dedicated channel to reduce the risk of spurious wakeups,
351 // but that increased complexity is probably not justified, as an application
352 // that is expecting a reset is not likely to receive large amounts of data.
353 conn.blocked_readers.insert(self.stream, cx.waker().clone());
354 Poll::Pending
355 }
356 }
357 })
358 .await
359 }
360
361 /// Handle common logic related to reading out of a receive stream
362 ///
363 /// This takes an `FnMut` closure that takes care of the actual reading process, matching
364 /// the detailed read semantics for the calling function with a particular return type.
365 /// The closure can read from the passed `&mut Chunks` and has to return the status after
366 /// reading: the amount of data read, and the status after the final read call.
367 fn poll_read_generic<T, U>(
368 &mut self,
369 cx: &mut Context<'_>,
370 ordered: bool,
371 mut read_fn: T,
372 ) -> Poll<Result<Option<U>, ReadError>>
373 where
374 T: FnMut(&mut Chunks<'_>) -> ReadStatus<U>,
375 {
376 use proto::ReadError::*;
377 if self.all_data_read {
378 return Poll::Ready(Ok(None));
379 }
380
381 let mut conn = self.conn.lock_without_waking("RecvStream::poll_read");
382 if self.is_0rtt {
383 conn.check_0rtt().map_err(|()| ReadError::ZeroRttRejected)?;
384 }
385
386 // If we stored an error during a previous call, return it now. This can happen if a
387 // `read_fn` both wants to return data and also returns an error in its final stream status.
388 let status = match self.reset {
389 Some(code) => ReadStatus::Failed(None, Reset(code)),
390 None => {
391 let mut recv = conn.inner.recv_stream(self.stream);
392 let mut chunks = recv.read(ordered).map_err(|e| match e {
393 ReadableError::ClosedStream => ReadError::ClosedStream,
394 ReadableError::IllegalOrderedRead => {
395 // We should never get here because the only way to do unordered reads is
396 // via UnorderedRecvStream, which allows only unordered reads. It is not
397 // possible to get a RecvStream from an UnorderedRecvStream.
398 unreachable!("ordered read after unordered read")
399 }
400 })?;
401 let status = read_fn(&mut chunks);
402 if chunks.finalize().should_transmit() {
403 conn.wake();
404 }
405 status
406 }
407 };
408
409 match status {
410 ReadStatus::Readable(read) => Poll::Ready(Ok(Some(read))),
411 ReadStatus::Finished(read) => {
412 self.all_data_read = true;
413 Poll::Ready(Ok(read))
414 }
415 ReadStatus::Failed(read, Blocked) => match read {
416 Some(val) => Poll::Ready(Ok(Some(val))),
417 None => {
418 if let Some(ref x) = conn.error {
419 return Poll::Ready(Err(ReadError::ConnectionLost(x.clone())));
420 }
421 conn.blocked_readers.insert(self.stream, cx.waker().clone());
422 Poll::Pending
423 }
424 },
425 ReadStatus::Failed(read, Reset(error_code)) => match read {
426 None => {
427 self.all_data_read = true;
428 self.reset = Some(error_code);
429 Poll::Ready(Err(ReadError::Reset(error_code)))
430 }
431 done => {
432 self.reset = Some(error_code);
433 Poll::Ready(Ok(done))
434 }
435 },
436 }
437 }
438
439 /// Converts this stream into an unordered stream.
440 pub fn into_unordered(self) -> UnorderedRecvStream {
441 UnorderedRecvStream { inner: self }
442 }
443}
444
445/// A stream that can be used to receive data out-of-order.
446///
447/// Obtained by converting a [`RecvStream`] via [`RecvStream::into_unordered`].
448///
449/// This variant of `RecvStream` allows reading chunks of data *exclusively*
450/// out of order. Once you have done an unordered read, ordered reads are no
451/// longer possible since data may have been consumed out of order.
452///
453/// The stream state related fns like [`Self::id`], [`Self::is_0rtt`], [`Self::stop`], and
454/// [`Self::received_reset`] behave exactly as on [`RecvStream`].
455#[derive(Debug)]
456pub struct UnorderedRecvStream {
457 inner: RecvStream,
458}
459
460impl UnorderedRecvStream {
461 /// Reads the next segment of data.
462 ///
463 /// Yields `None` if the stream was finished. Otherwise, yields a segment of data and its
464 /// offset in the stream. Segments may be received in any order, and the `Chunk`'s `offset`
465 /// field can be used to determine ordering in the caller. Unordered reads are less prone
466 /// to head-of-line blocking within a stream, but require the application to manage
467 /// reassembling the original data.
468 ///
469 /// This operation is cancel-safe.
470 pub async fn read_chunk(&mut self, max_length: usize) -> Result<Option<Chunk>, ReadError> {
471 ReadChunk {
472 stream: &mut self.inner,
473 max_length,
474 ordered: false,
475 }
476 .await
477 }
478
479 /// Get the identity of this stream
480 pub fn id(&self) -> StreamId {
481 self.inner.id()
482 }
483
484 /// Check if this stream has been opened during 0-RTT.
485 ///
486 /// In which case any non-idempotent request should be considered dangerous at the application
487 /// level. Because read data is subject to replay attacks.
488 pub fn is_0rtt(&self) -> bool {
489 self.inner.is_0rtt()
490 }
491
492 /// Stop accepting data
493 ///
494 /// Discards unread data and notifies the peer to stop transmitting. Once stopped, further
495 /// attempts to operate on a stream will yield `ClosedStream` errors.
496 pub fn stop(&mut self, error_code: VarInt) -> Result<(), ClosedStream> {
497 self.inner.stop(error_code)
498 }
499
500 /// Completes when the stream has been reset by the peer or otherwise closed
501 ///
502 /// Yields `Some` with the reset error code when the stream is reset by the peer. Yields `None`
503 /// when the stream was previously [`stop()`](Self::stop)ed, or when the stream was
504 /// [`finish()`](crate::SendStream::finish)ed by the peer and all data has been received, after
505 /// which it is no longer meaningful for the stream to be reset.
506 ///
507 /// This operation is cancel-safe.
508 pub async fn received_reset(&mut self) -> Result<Option<VarInt>, ResetError> {
509 self.inner.received_reset().await
510 }
511}
512
513enum ReadStatus<T> {
514 Readable(T),
515 Finished(Option<T>),
516 Failed(Option<T>, proto::ReadError),
517}
518
519impl<T> From<(Option<T>, Option<proto::ReadError>)> for ReadStatus<T> {
520 fn from(status: (Option<T>, Option<proto::ReadError>)) -> Self {
521 match status {
522 (read, None) => Self::Finished(read),
523 (read, Some(e)) => Self::Failed(read, e),
524 }
525 }
526}
527
528/// Future produced by [`RecvStream::read_to_end()`].
529///
530/// [`RecvStream::read_to_end()`]: crate::RecvStream::read_to_end
531struct ReadToEnd<'a> {
532 stream: &'a mut RecvStream,
533 read: Vec<(Bytes, u64)>,
534 start: u64,
535 end: u64,
536 size_limit: usize,
537}
538
539impl Future for ReadToEnd<'_> {
540 type Output = Result<Vec<u8>, ReadToEndError>;
541 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
542 loop {
543 match ready!(self.stream.poll_read_chunk(cx, usize::MAX, false))? {
544 Some(chunk) => {
545 self.start = self.start.min(chunk.offset);
546 let end = chunk.bytes.len() as u64 + chunk.offset;
547 if (end - self.start) > self.size_limit as u64 {
548 return Poll::Ready(Err(ReadToEndError::TooLong));
549 }
550 self.end = self.end.max(end);
551 self.read.push((chunk.bytes, chunk.offset));
552 }
553 None => {
554 if self.end == 0 {
555 // Never received anything
556 return Poll::Ready(Ok(Vec::new()));
557 }
558 let start = self.start;
559 let mut buffer = vec![0; (self.end - start) as usize];
560 for (data, offset) in self.read.drain(..) {
561 let offset = (offset - start) as usize;
562 buffer[offset..offset + data.len()].copy_from_slice(&data);
563 }
564 return Poll::Ready(Ok(buffer));
565 }
566 }
567 }
568 }
569}
570
571/// Errors from [`RecvStream::read_to_end`]
572#[derive(Debug, Error, Clone, PartialEq, Eq)]
573pub enum ReadToEndError {
574 /// An error occurred during reading
575 #[error("read error: {0}")]
576 Read(#[from] ReadError),
577 /// The stream is larger than the user-supplied limit
578 #[error("stream too long")]
579 TooLong,
580}
581
582#[cfg(feature = "futures-io")]
583impl futures_io::AsyncRead for RecvStream {
584 fn poll_read(
585 self: Pin<&mut Self>,
586 cx: &mut Context<'_>,
587 buf: &mut [u8],
588 ) -> Poll<io::Result<usize>> {
589 let mut buf = ReadBuf::new(buf);
590 ready!(Self::poll_read_buf(self.get_mut(), cx, &mut buf))?;
591 Poll::Ready(Ok(buf.filled().len()))
592 }
593}
594
595impl tokio::io::AsyncRead for RecvStream {
596 fn poll_read(
597 self: Pin<&mut Self>,
598 cx: &mut Context<'_>,
599 buf: &mut ReadBuf<'_>,
600 ) -> Poll<io::Result<()>> {
601 ready!(Self::poll_read_buf(self.get_mut(), cx, buf))?;
602 Poll::Ready(Ok(()))
603 }
604}
605
606impl Drop for RecvStream {
607 fn drop(&mut self) {
608 if self.all_data_read {
609 debug_assert!(
610 !self
611 .conn
612 .lock_without_waking("RecvStream:drop")
613 .blocked_readers
614 .contains_key(&self.stream),
615 "Stream {} should not have a blocked reader when all data read is true",
616 self.stream
617 );
618 return;
619 }
620 let mut conn = self.conn.lock_and_wake("RecvStream::drop");
621
622 // clean up any previously registered wakers
623 conn.blocked_readers.remove(&self.stream);
624
625 if conn.error.is_some() || (self.is_0rtt && conn.check_0rtt().is_err()) {
626 conn.skip_waking();
627 return;
628 }
629
630 // Ignore ClosedStream errors
631 let _ = conn.inner.recv_stream(self.stream).stop(0u32.into());
632 }
633}
634
635/// Errors that arise from reading from a stream.
636#[derive(Debug, Error, Clone, PartialEq, Eq)]
637pub enum ReadError {
638 /// The peer abandoned transmitting data on this stream
639 ///
640 /// Carries an application-defined error code.
641 #[error("stream reset by peer: error {0}")]
642 Reset(VarInt),
643 /// The connection was lost
644 #[error("connection lost")]
645 ConnectionLost(#[from] ConnectionError),
646 /// The stream has already been stopped, finished, or reset
647 #[error("closed stream")]
648 ClosedStream,
649 /// This was a 0-RTT stream and the server rejected it
650 ///
651 /// Can only occur on clients for 0-RTT streams, which can be opened using
652 /// [`Connecting::into_0rtt()`].
653 ///
654 /// [`Connecting::into_0rtt()`]: crate::Connecting::into_0rtt()
655 #[error("0-RTT rejected")]
656 ZeroRttRejected,
657}
658
659impl From<ResetError> for ReadError {
660 fn from(e: ResetError) -> Self {
661 match e {
662 ResetError::ConnectionLost(e) => Self::ConnectionLost(e),
663 ResetError::ZeroRttRejected => Self::ZeroRttRejected,
664 }
665 }
666}
667
668impl From<ReadError> for io::Error {
669 fn from(x: ReadError) -> Self {
670 use ReadError::*;
671 let kind = match x {
672 Reset { .. } | ZeroRttRejected => io::ErrorKind::ConnectionReset,
673 ConnectionLost(_) | ClosedStream => io::ErrorKind::NotConnected,
674 };
675 Self::new(kind, x)
676 }
677}
678
679/// Errors that arise while waiting for a stream to be reset
680#[derive(Debug, Error, Clone, PartialEq, Eq)]
681pub enum ResetError {
682 /// The connection was lost
683 #[error("connection lost")]
684 ConnectionLost(#[from] ConnectionError),
685 /// This was a 0-RTT stream and the server rejected it
686 ///
687 /// Can only occur on clients for 0-RTT streams, which can be opened using
688 /// [`Connecting::into_0rtt()`].
689 ///
690 /// [`Connecting::into_0rtt()`]: crate::Connecting::into_0rtt()
691 #[error("0-RTT rejected")]
692 ZeroRttRejected,
693}
694
695impl From<ResetError> for io::Error {
696 fn from(x: ResetError) -> Self {
697 use ResetError::*;
698 let kind = match x {
699 ZeroRttRejected => io::ErrorKind::ConnectionReset,
700 ConnectionLost(_) => io::ErrorKind::NotConnected,
701 };
702 Self::new(kind, x)
703 }
704}
705
706/// Future produced by [`RecvStream::read()`].
707///
708/// [`RecvStream::read()`]: crate::RecvStream::read
709struct Read<'a> {
710 stream: &'a mut RecvStream,
711 buf: ReadBuf<'a>,
712}
713
714impl Future for Read<'_> {
715 type Output = Result<Option<usize>, ReadError>;
716
717 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
718 let this = self.get_mut();
719 ready!(this.stream.poll_read_buf(cx, &mut this.buf))?;
720 match this.buf.filled().len() {
721 0 if this.buf.capacity() != 0 => Poll::Ready(Ok(None)),
722 n => Poll::Ready(Ok(Some(n))),
723 }
724 }
725}
726
727/// Future produced by [`RecvStream::read_exact()`].
728///
729/// [`RecvStream::read_exact()`]: crate::RecvStream::read_exact
730struct ReadExact<'a> {
731 stream: &'a mut RecvStream,
732 buf: ReadBuf<'a>,
733}
734
735impl Future for ReadExact<'_> {
736 type Output = Result<(), ReadExactError>;
737 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
738 let this = self.get_mut();
739 let mut remaining = this.buf.remaining();
740 while remaining > 0 {
741 ready!(this.stream.poll_read_buf(cx, &mut this.buf))?;
742 let new = this.buf.remaining();
743 if new == remaining {
744 return Poll::Ready(Err(ReadExactError::FinishedEarly(this.buf.filled().len())));
745 }
746 remaining = new;
747 }
748 Poll::Ready(Ok(()))
749 }
750}
751
752/// Errors that arise from reading from a stream.
753#[derive(Debug, Error, Clone, PartialEq, Eq)]
754pub enum ReadExactError {
755 /// The stream finished before all bytes were read
756 #[error("stream finished early ({0} bytes read)")]
757 FinishedEarly(usize),
758 /// A read error occurred
759 #[error(transparent)]
760 ReadError(#[from] ReadError),
761}
762
763/// Future produced by [`RecvStream::read_chunk()`] or [`UnorderedRecvStream::read_chunk()`].
764///
765/// [`RecvStream::read_chunk()`]: crate::RecvStream::read_chunk
766/// [`UnorderedRecvStream::read_chunk()`]: crate::UnorderedRecvStream::read_chunk
767struct ReadChunk<'a> {
768 stream: &'a mut RecvStream,
769 max_length: usize,
770 ordered: bool,
771}
772
773impl Future for ReadChunk<'_> {
774 type Output = Result<Option<Chunk>, ReadError>;
775 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
776 let (max_length, ordered) = (self.max_length, self.ordered);
777 self.stream.poll_read_chunk(cx, max_length, ordered)
778 }
779}
780
781/// Future produced by [`RecvStream::read_many_chunks()`].
782///
783/// [`RecvStream::read_many_chunks()`]: crate::RecvStream::read_many_chunks
784struct ReadChunks<'a> {
785 stream: &'a mut RecvStream,
786 bufs: &'a mut [Bytes],
787}
788
789impl Future for ReadChunks<'_> {
790 type Output = Result<Option<usize>, ReadError>;
791 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
792 let this = self.get_mut();
793 this.stream.poll_read_chunks(cx, this.bufs)
794 }
795}