pub enum ConnectionError {
+ConnectionError in iroh_quinn - Rust ConnectionError
pub enum ConnectionError {
VersionMismatch,
TransportError(Error),
ConnectionClosed(ConnectionClose),
@@ -20,8 +20,8 @@ and §LocallyClosed
The local application closed the connection
§CidsExhausted
The connection could not be created because not enough of the CID space is available
Try using longer connection IDs.
-Trait Implementations§
Source§impl Clone for ConnectionError
Source§fn clone(&self) -> ConnectionError
Returns a duplicate of the value. Read more1.0.0 · Source§fn clone_from(&mut self, source: &Self)
Performs copy-assignment from source. Read moreSource§impl Debug for ConnectionError
Source§impl Display for ConnectionError
Source§impl Error for ConnectionError
Source§fn source(&self) -> Option<&(dyn Error + 'static)>
Returns the lower-level source of this error, if any. Read more1.0.0 · Source§fn description(&self) -> &str
👎Deprecated since 1.42.0: use the Display impl or to_string()Source§impl From<Close> for ConnectionError
Source§fn from(x: Close) -> ConnectionError
Converts to this type from the input type.Source§impl From<CloseReason> for ConnectionError
Source§fn from(value: CloseReason) -> ConnectionError
Converts to this type from the input type.Source§impl From<ConnectionError> for ReadError
Source§fn from(source: ConnectionError) -> Self
Converts to this type from the input type.Source§impl From<ConnectionError> for ResetError
Source§fn from(source: ConnectionError) -> Self
Converts to this type from the input type.Source§impl From<ConnectionError> for SendDatagramError
Source§fn from(source: ConnectionError) -> Self
Converts to this type from the input type.Source§impl From<ConnectionError> for StoppedError
Source§fn from(source: ConnectionError) -> Self
Converts to this type from the input type.Source§impl From<ConnectionError> for WriteError
Source§fn from(source: ConnectionError) -> Self
Converts to this type from the input type.Source§impl From<Error> for ConnectionError
Source§fn from(source: Error) -> ConnectionError
Converts to this type from the input type.Source§impl PartialEq for ConnectionError
Source§impl Eq for ConnectionError
Source§impl StructuralPartialEq for ConnectionError
Auto Trait Implementations§
§impl !Freeze for ConnectionError
§impl !RefUnwindSafe for ConnectionError
§impl Send for ConnectionError
§impl Sync for ConnectionError
§impl Unpin for ConnectionError
§impl !UnwindSafe for ConnectionError
Blanket Implementations§
Trait Implementations§
Source§impl Clone for ConnectionError
Source§fn clone(&self) -> ConnectionError
Returns a duplicate of the value. Read more1.0.0 · Source§fn clone_from(&mut self, source: &Self)
Performs copy-assignment from source. Read moreSource§impl Debug for ConnectionError
Source§impl Display for ConnectionError
Source§impl Error for ConnectionError
Source§fn source(&self) -> Option<&(dyn Error + 'static)>
Returns the lower-level source of this error, if any. Read more1.0.0 · Source§fn description(&self) -> &str
👎Deprecated since 1.42.0: use the Display impl or to_string()Source§impl From<Close> for ConnectionError
Source§fn from(x: Close) -> ConnectionError
Converts to this type from the input type.Source§impl From<CloseReason> for ConnectionError
Source§fn from(value: CloseReason) -> ConnectionError
Converts to this type from the input type.Source§impl From<ConnectionError> for ReadError
Source§fn from(source: ConnectionError) -> Self
Converts to this type from the input type.Source§impl From<ConnectionError> for ResetError
Source§fn from(source: ConnectionError) -> Self
Converts to this type from the input type.Source§impl From<ConnectionError> for SendDatagramError
Source§fn from(source: ConnectionError) -> Self
Converts to this type from the input type.Source§impl From<ConnectionError> for StoppedError
Source§fn from(source: ConnectionError) -> Self
Converts to this type from the input type.Source§impl From<ConnectionError> for WriteError
Source§fn from(source: ConnectionError) -> Self
Converts to this type from the input type.Source§impl From<Error> for ConnectionError
Source§fn from(source: Error) -> ConnectionError
Converts to this type from the input type.Source§impl PartialEq for ConnectionError
Source§impl Eq for ConnectionError
Source§impl StructuralPartialEq for ConnectionError
Auto Trait Implementations§
§impl !Freeze for ConnectionError
§impl !RefUnwindSafe for ConnectionError
§impl Send for ConnectionError
§impl Sync for ConnectionError
§impl Unpin for ConnectionError
§impl !UnwindSafe for ConnectionError
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read moreSource§impl<T> CloneToUninit for Twhere
diff --git a/pr/257/docs/iroh_quinn/enum.ReadError.html b/pr/257/docs/iroh_quinn/enum.ReadError.html
index 3469c9669..8b21b002e 100644
--- a/pr/257/docs/iroh_quinn/enum.ReadError.html
+++ b/pr/257/docs/iroh_quinn/enum.ReadError.html
@@ -1,4 +1,4 @@
-ReadError in iroh_quinn - Rust ReadError
pub enum ReadError {
+ReadError in iroh_quinn - Rust ReadError
pub enum ReadError {
Reset(VarInt),
ConnectionLost(ConnectionError),
ClosedStream,
@@ -15,8 +15,8 @@ stream which cannot be recovered, making further ordered reads impossible.
§ZeroRttRejected
This was a 0-RTT stream and the server rejected it
Can only occur on clients for 0-RTT streams, which can be opened using
Connecting::into_0rtt().
-
Trait Implementations§
Source§impl Error for ReadError
Source§fn source(&self) -> Option<&(dyn Error + 'static)>
Returns the lower-level source of this error, if any. Read more1.0.0 · Source§fn description(&self) -> &str
👎Deprecated since 1.42.0: use the Display impl or to_string()Source§impl From<ConnectionError> for ReadError
Source§fn from(source: ConnectionError) -> Self
Converts to this type from the input type.Source§impl From<ReadError> for ReadExactError
Source§impl From<ReadError> for ReadToEndError
Source§impl From<ReadableError> for ReadError
Source§fn from(e: ReadableError) -> Self
Converts to this type from the input type.Source§impl From<ResetError> for ReadError
Source§fn from(e: ResetError) -> Self
Converts to this type from the input type.Source§impl Eq for ReadError
Source§impl StructuralPartialEq for ReadError
Auto Trait Implementations§
§impl !Freeze for ReadError
§impl !RefUnwindSafe for ReadError
§impl Send for ReadError
§impl Sync for ReadError
§impl Unpin for ReadError
§impl !UnwindSafe for ReadError
Blanket Implementations§
Trait Implementations§
Source§impl Error for ReadError
Source§fn source(&self) -> Option<&(dyn Error + 'static)>
Returns the lower-level source of this error, if any. Read more1.0.0 · Source§fn description(&self) -> &str
👎Deprecated since 1.42.0: use the Display impl or to_string()Source§impl From<ConnectionError> for ReadError
Source§fn from(source: ConnectionError) -> Self
Converts to this type from the input type.Source§impl From<ReadError> for ReadExactError
Source§impl From<ReadError> for ReadToEndError
Source§impl From<ReadableError> for ReadError
Source§fn from(e: ReadableError) -> Self
Converts to this type from the input type.Source§impl From<ResetError> for ReadError
Source§fn from(e: ResetError) -> Self
Converts to this type from the input type.Source§impl Eq for ReadError
Source§impl StructuralPartialEq for ReadError
Auto Trait Implementations§
§impl !Freeze for ReadError
§impl !RefUnwindSafe for ReadError
§impl Send for ReadError
§impl Sync for ReadError
§impl Unpin for ReadError
§impl !UnwindSafe for ReadError
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read moreSource§impl<T> CloneToUninit for Twhere
diff --git a/pr/257/docs/iroh_quinn/enum.ReadExactError.html b/pr/257/docs/iroh_quinn/enum.ReadExactError.html
index 49b168223..363d2810c 100644
--- a/pr/257/docs/iroh_quinn/enum.ReadExactError.html
+++ b/pr/257/docs/iroh_quinn/enum.ReadExactError.html
@@ -1,11 +1,11 @@
-ReadExactError in iroh_quinn - Rust ReadExactError
pub enum ReadExactError {
+ReadExactError in iroh_quinn - Rust ReadExactError
pub enum ReadExactError {
FinishedEarly(usize),
ReadError(ReadError),
}
Expand description
Errors that arise from reading from a stream.
Variants§
§FinishedEarly(usize)
The stream finished before all bytes were read
§ReadError(ReadError)
A read error occurred
-Trait Implementations§
Source§impl Clone for ReadExactError
Source§fn clone(&self) -> ReadExactError
Returns a duplicate of the value. Read more1.0.0 · Source§fn clone_from(&mut self, source: &Self)
Performs copy-assignment from source. Read moreSource§impl Debug for ReadExactError
Source§impl Display for ReadExactError
Source§impl Error for ReadExactError
Source§fn source(&self) -> Option<&(dyn Error + 'static)>
Returns the lower-level source of this error, if any. Read more1.0.0 · Source§fn description(&self) -> &str
👎Deprecated since 1.42.0: use the Display impl or to_string()Source§impl From<ReadError> for ReadExactError
Source§impl PartialEq for ReadExactError
Source§impl Eq for ReadExactError
Source§impl StructuralPartialEq for ReadExactError
Auto Trait Implementations§
§impl !Freeze for ReadExactError
§impl !RefUnwindSafe for ReadExactError
§impl Send for ReadExactError
§impl Sync for ReadExactError
§impl Unpin for ReadExactError
§impl !UnwindSafe for ReadExactError
Blanket Implementations§
Trait Implementations§
Source§impl Clone for ReadExactError
Source§fn clone(&self) -> ReadExactError
Returns a duplicate of the value. Read more1.0.0 · Source§fn clone_from(&mut self, source: &Self)
Performs copy-assignment from source. Read moreSource§impl Debug for ReadExactError
Source§impl Display for ReadExactError
Source§impl Error for ReadExactError
Source§fn source(&self) -> Option<&(dyn Error + 'static)>
Returns the lower-level source of this error, if any. Read more1.0.0 · Source§fn description(&self) -> &str
👎Deprecated since 1.42.0: use the Display impl or to_string()Source§impl From<ReadError> for ReadExactError
Source§impl PartialEq for ReadExactError
Source§impl Eq for ReadExactError
Source§impl StructuralPartialEq for ReadExactError
Auto Trait Implementations§
§impl !Freeze for ReadExactError
§impl !RefUnwindSafe for ReadExactError
§impl Send for ReadExactError
§impl Sync for ReadExactError
§impl Unpin for ReadExactError
§impl !UnwindSafe for ReadExactError
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read moreSource§impl<T> CloneToUninit for Twhere
diff --git a/pr/257/docs/iroh_quinn/enum.ReadToEndError.html b/pr/257/docs/iroh_quinn/enum.ReadToEndError.html
index 47cb88fd4..1a6a4298b 100644
--- a/pr/257/docs/iroh_quinn/enum.ReadToEndError.html
+++ b/pr/257/docs/iroh_quinn/enum.ReadToEndError.html
@@ -1,11 +1,11 @@
-ReadToEndError in iroh_quinn - Rust ReadToEndError
pub enum ReadToEndError {
+ReadToEndError in iroh_quinn - Rust ReadToEndError
pub enum ReadToEndError {
Read(ReadError),
TooLong,
}
Expand description
Errors from RecvStream::read_to_end
Variants§
§Read(ReadError)
An error occurred during reading
§TooLong
The stream is larger than the user-supplied limit
-Trait Implementations§
Source§impl Clone for ReadToEndError
Source§fn clone(&self) -> ReadToEndError
Returns a duplicate of the value. Read more1.0.0 · Source§fn clone_from(&mut self, source: &Self)
Performs copy-assignment from source. Read moreSource§impl Debug for ReadToEndError
Source§impl Display for ReadToEndError
Source§impl Error for ReadToEndError
Source§fn source(&self) -> Option<&(dyn Error + 'static)>
Returns the lower-level source of this error, if any. Read more1.0.0 · Source§fn description(&self) -> &str
👎Deprecated since 1.42.0: use the Display impl or to_string()Source§impl From<ReadError> for ReadToEndError
Source§impl PartialEq for ReadToEndError
Source§impl Eq for ReadToEndError
Source§impl StructuralPartialEq for ReadToEndError
Auto Trait Implementations§
§impl !Freeze for ReadToEndError
§impl !RefUnwindSafe for ReadToEndError
§impl Send for ReadToEndError
§impl Sync for ReadToEndError
§impl Unpin for ReadToEndError
§impl !UnwindSafe for ReadToEndError
Blanket Implementations§
Trait Implementations§
Source§impl Clone for ReadToEndError
Source§fn clone(&self) -> ReadToEndError
Returns a duplicate of the value. Read more1.0.0 · Source§fn clone_from(&mut self, source: &Self)
Performs copy-assignment from source. Read moreSource§impl Debug for ReadToEndError
Source§impl Display for ReadToEndError
Source§impl Error for ReadToEndError
Source§fn source(&self) -> Option<&(dyn Error + 'static)>
Returns the lower-level source of this error, if any. Read more1.0.0 · Source§fn description(&self) -> &str
👎Deprecated since 1.42.0: use the Display impl or to_string()Source§impl From<ReadError> for ReadToEndError
Source§impl PartialEq for ReadToEndError
Source§impl Eq for ReadToEndError
Source§impl StructuralPartialEq for ReadToEndError
Auto Trait Implementations§
§impl !Freeze for ReadToEndError
§impl !RefUnwindSafe for ReadToEndError
§impl Send for ReadToEndError
§impl Sync for ReadToEndError
§impl Unpin for ReadToEndError
§impl !UnwindSafe for ReadToEndError
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read moreSource§impl<T> CloneToUninit for Twhere
diff --git a/pr/257/docs/iroh_quinn/enum.ResetError.html b/pr/257/docs/iroh_quinn/enum.ResetError.html
index 5be9916a6..1fbf33fda 100644
--- a/pr/257/docs/iroh_quinn/enum.ResetError.html
+++ b/pr/257/docs/iroh_quinn/enum.ResetError.html
@@ -1,4 +1,4 @@
-ResetError in iroh_quinn - Rust ResetError
pub enum ResetError {
+ResetError in iroh_quinn - Rust ResetError
pub enum ResetError {
ConnectionLost(ConnectionError),
ZeroRttRejected,
}
Expand description
Errors that arise while waiting for a stream to be reset
@@ -6,8 +6,8 @@
§ZeroRttRejected
This was a 0-RTT stream and the server rejected it
Can only occur on clients for 0-RTT streams, which can be opened using
Connecting::into_0rtt().
-Trait Implementations§
Source§impl Clone for ResetError
Source§fn clone(&self) -> ResetError
Returns a duplicate of the value. Read more1.0.0 · Source§fn clone_from(&mut self, source: &Self)
Performs copy-assignment from source. Read moreSource§impl Debug for ResetError
Source§impl Display for ResetError
Source§impl Error for ResetError
Source§fn source(&self) -> Option<&(dyn Error + 'static)>
Returns the lower-level source of this error, if any. Read more1.0.0 · Source§fn description(&self) -> &str
👎Deprecated since 1.42.0: use the Display impl or to_string()Source§impl From<ConnectionError> for ResetError
Source§fn from(source: ConnectionError) -> Self
Converts to this type from the input type.Source§impl From<ResetError> for Error
Source§fn from(x: ResetError) -> Self
Converts to this type from the input type.Source§impl From<ResetError> for ReadError
Source§fn from(e: ResetError) -> Self
Converts to this type from the input type.Source§impl PartialEq for ResetError
Source§impl Eq for ResetError
Source§impl StructuralPartialEq for ResetError
Auto Trait Implementations§
§impl !Freeze for ResetError
§impl !RefUnwindSafe for ResetError
§impl Send for ResetError
§impl Sync for ResetError
§impl Unpin for ResetError
§impl !UnwindSafe for ResetError
Blanket Implementations§
Trait Implementations§
Source§impl Clone for ResetError
Source§fn clone(&self) -> ResetError
Returns a duplicate of the value. Read more1.0.0 · Source§fn clone_from(&mut self, source: &Self)
Performs copy-assignment from source. Read moreSource§impl Debug for ResetError
Source§impl Display for ResetError
Source§impl Error for ResetError
Source§fn source(&self) -> Option<&(dyn Error + 'static)>
Returns the lower-level source of this error, if any. Read more1.0.0 · Source§fn description(&self) -> &str
👎Deprecated since 1.42.0: use the Display impl or to_string()Source§impl From<ConnectionError> for ResetError
Source§fn from(source: ConnectionError) -> Self
Converts to this type from the input type.Source§impl From<ResetError> for Error
Source§fn from(x: ResetError) -> Self
Converts to this type from the input type.Source§impl From<ResetError> for ReadError
Source§fn from(e: ResetError) -> Self
Converts to this type from the input type.Source§impl PartialEq for ResetError
Source§impl Eq for ResetError
Source§impl StructuralPartialEq for ResetError
Auto Trait Implementations§
§impl !Freeze for ResetError
§impl !RefUnwindSafe for ResetError
§impl Send for ResetError
§impl Sync for ResetError
§impl Unpin for ResetError
§impl !UnwindSafe for ResetError
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read moreSource§impl<T> CloneToUninit for Twhere
diff --git a/pr/257/docs/iroh_quinn/struct.RecvStream.html b/pr/257/docs/iroh_quinn/struct.RecvStream.html
index b39b071f0..47ed709c0 100644
--- a/pr/257/docs/iroh_quinn/struct.RecvStream.html
+++ b/pr/257/docs/iroh_quinn/struct.RecvStream.html
@@ -20,12 +20,12 @@ logging the StreamId. For example, even if a sender first transmits on
bidirectional stream 1, the first stream yielded by Connection::accept_bi on the receiver
will be bidirectional stream 0.
-
Implementations§
Source§impl RecvStream
Sourcepub async fn read(&mut self, buf: &mut [u8]) -> Result<Option<usize>, ReadError>
Read data contiguously from the stream.
+Implementations§
Source§impl RecvStream
Sourcepub async fn read(&mut self, buf: &mut [u8]) -> Result<Option<usize>, ReadError>
Read data contiguously from the stream.
Yields the number of bytes read into buf on success, or None if the stream was finished.
This operation is cancel-safe.
-Sourcepub async fn read_exact(&mut self, buf: &mut [u8]) -> Result<(), ReadExactError>
Read an exact number of bytes contiguously from the stream.
+Sourcepub async fn read_exact(&mut self, buf: &mut [u8]) -> Result<(), ReadExactError>
Read an exact number of bytes contiguously from the stream.
See read() for details. This operation is not cancel-safe.
-Sourcepub fn poll_read(
&mut self,
cx: &mut Context<'_>,
buf: &mut [u8],
@@ -36,7 +36,7 @@ side has Sourcepub fn poll_read_buf(
+
Sourcepub fn poll_read_buf(
&mut self,
cx: &mut Context<'_>,
buf: &mut ReadBuf<'_>,
@@ -48,7 +48,7 @@ read all bytes.
If no data is available for reading, this returns Poll::Pending and arranges for the
current task (via cx.waker()) to be notified when the stream becomes readable or is
closed.
-
Sourcepub async fn read_chunk(
+
Sourcepub async fn read_chunk(
&mut self,
max_length: usize,
) -> Result<Option<Chunk>, ReadError>
Read the next segment of data
@@ -59,7 +59,7 @@ the last data yielded by RecvStream::read due to not copying. Chunk boundaries do not correspond
to peer writes, and hence cannot be used as framing.
This operation is cancel-safe.
-Sourcepub async fn read_chunks(
+
Sourcepub async fn read_chunks(
&mut self,
bufs: &mut [Bytes],
) -> Result<Option<usize>, ReadError>
Read the next segments of data
@@ -69,7 +69,7 @@ finished.
Slightly more efficient than read due to not copying. Chunk boundaries
do not correspond to peer writes, and hence cannot be used as framing.
This operation is cancel-safe.
-Sourcepub async fn read_to_end(
+
Sourcepub async fn read_to_end(
&mut self,
size_limit: usize,
) -> Result<Vec<u8>, ReadToEndError>
Convenience method to read all remaining data into a buffer
@@ -79,21 +79,21 @@ allow. size_limit should be set to limit worst-case memory use.
If unordered reads have already been made, the resulting buffer may have gaps containing
arbitrary data.
This operation is not cancel-safe.
-Sourcepub fn stop(&mut self, error_code: VarInt) -> Result<(), ClosedStream>
Stop accepting data
Discards unread data and notifies the peer to stop transmitting. Once stopped, further
attempts to operate on a stream will yield ClosedStream errors.
-Sourcepub fn is_0rtt(&self) -> bool
Check if this stream has been opened during 0-RTT.
In which case any non-idempotent request should be considered dangerous at the application
level. Because read data is subject to replay attacks.
-Sourcepub async fn received_reset(&mut self) -> Result<Option<VarInt>, ResetError>
Completes when the stream has been reset by the peer or otherwise closed
+Sourcepub async fn received_reset(&mut self) -> Result<Option<VarInt>, ResetError>
Completes when the stream has been reset by the peer or otherwise closed
Yields Some with the reset error code when the stream is reset by the peer. Yields None
when the stream was previously stop()ed, or when the stream was
finish()ed by the peer and all data has been received, after
which it is no longer meaningful for the stream to be reset.
This operation is cancel-safe.
-Sourcepub fn into_unordered(self) -> UnorderedRecvStream
Converts this stream into an unordered stream.
-
Trait Implementations§
Source§impl AsyncRead for RecvStream
Available on crate feature futures-io only.
Sourcepub fn into_unordered(self) -> UnorderedRecvStream
Converts this stream into an unordered stream.
+Trait Implementations§
Source§impl AsyncRead for RecvStream
Available on crate feature futures-io only.
Source§impl AsyncRead for RecvStream
Source§impl Debug for RecvStream
Auto Trait Implementations§
§impl Freeze for RecvStream
§impl RefUnwindSafe for RecvStream
§impl Send for RecvStream
§impl Sync for RecvStream
§impl Unpin for RecvStream
§impl UnwindSafe for RecvStream
Blanket Implementations§
Auto Trait Implementations§
§impl Freeze for RecvStream
§impl RefUnwindSafe for RecvStream
§impl Send for RecvStream
§impl Sync for RecvStream
§impl Unpin for RecvStream
§impl UnwindSafe for RecvStream
Blanket Implementations§
§impl<R> AsyncReadExt for Rwhere
R: AsyncRead + ?Sized,
§fn chain<R>(self, next: R) -> Chain<Self, R>where
Self: Sized,
diff --git a/pr/257/docs/iroh_quinn_proto/enum.ClosePathError.html b/pr/257/docs/iroh_quinn_proto/enum.ClosePathError.html
index ca551b0c3..15e570b33 100644
--- a/pr/257/docs/iroh_quinn_proto/enum.ClosePathError.html
+++ b/pr/257/docs/iroh_quinn_proto/enum.ClosePathError.html
@@ -1,11 +1,11 @@
-ClosePathError in iroh_quinn_proto - Rust ClosePathError
pub enum ClosePathError {
+ClosePathError in iroh_quinn_proto - Rust ClosePathError
pub enum ClosePathError {
ClosedPath,
LastOpenPath,
}
Expand description
Errors triggered when abandoning a path
Variants§
§ClosedPath
The path is already closed or was never opened
§LastOpenPath
This is the last path, which can not be abandoned
-Trait Implementations§
Source§impl Clone for ClosePathError
Source§fn clone(&self) -> ClosePathError
Returns a duplicate of the value. Read more1.0.0 · Source§fn clone_from(&mut self, source: &Self)
Performs copy-assignment from source. Read moreSource§impl Debug for ClosePathError
Source§impl Display for ClosePathError
Source§impl Error for ClosePathError
1.30.0 · Source§fn source(&self) -> Option<&(dyn Error + 'static)>
Returns the lower-level source of this error, if any. Read more1.0.0 · Source§fn description(&self) -> &str
👎Deprecated since 1.42.0: use the Display impl or to_string()Source§impl PartialEq for ClosePathError
Source§impl Eq for ClosePathError
Source§impl StructuralPartialEq for ClosePathError
Auto Trait Implementations§
§impl Freeze for ClosePathError
§impl RefUnwindSafe for ClosePathError
§impl Send for ClosePathError
§impl Sync for ClosePathError
§impl Unpin for ClosePathError
§impl UnwindSafe for ClosePathError
Blanket Implementations§
Trait Implementations§
Source§impl Clone for ClosePathError
Source§fn clone(&self) -> ClosePathError
Returns a duplicate of the value. Read more1.0.0 · Source§fn clone_from(&mut self, source: &Self)
Performs copy-assignment from source. Read moreSource§impl Debug for ClosePathError
Source§impl Display for ClosePathError
Source§impl Error for ClosePathError
1.30.0 · Source§fn source(&self) -> Option<&(dyn Error + 'static)>
Returns the lower-level source of this error, if any. Read more1.0.0 · Source§fn description(&self) -> &str
👎Deprecated since 1.42.0: use the Display impl or to_string()Source§impl PartialEq for ClosePathError
Source§impl Eq for ClosePathError
Source§impl StructuralPartialEq for ClosePathError
Auto Trait Implementations§
§impl Freeze for ClosePathError
§impl RefUnwindSafe for ClosePathError
§impl Send for ClosePathError
§impl Sync for ClosePathError
§impl Unpin for ClosePathError
§impl UnwindSafe for ClosePathError
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read moreSource§impl<T> CloneToUninit for Twhere
diff --git a/pr/257/docs/iroh_quinn_proto/enum.ConnectionError.html b/pr/257/docs/iroh_quinn_proto/enum.ConnectionError.html
index 19123c7b9..5cc562864 100644
--- a/pr/257/docs/iroh_quinn_proto/enum.ConnectionError.html
+++ b/pr/257/docs/iroh_quinn_proto/enum.ConnectionError.html
@@ -1,4 +1,4 @@
-ConnectionError in iroh_quinn_proto - Rust ConnectionError
pub enum ConnectionError {
+ConnectionError in iroh_quinn_proto - Rust ConnectionError
pub enum ConnectionError {
VersionMismatch,
TransportError(TransportError),
ConnectionClosed(ConnectionClose),
@@ -20,8 +20,8 @@ and §LocallyClosed
The local application closed the connection
§CidsExhausted
The connection could not be created because not enough of the CID space is available
Try using longer connection IDs.
-Trait Implementations§
Source§impl Clone for ConnectionError
Source§fn clone(&self) -> ConnectionError
Returns a duplicate of the value. Read more1.0.0 · Source§fn clone_from(&mut self, source: &Self)
Performs copy-assignment from source. Read moreSource§impl Debug for ConnectionError
Source§impl Display for ConnectionError
Source§impl Error for ConnectionError
Source§fn source(&self) -> Option<&(dyn Error + 'static)>
Returns the lower-level source of this error, if any. Read more1.0.0 · Source§fn description(&self) -> &str
👎Deprecated since 1.42.0: use the Display impl or to_string()Source§impl From<ConnectionError> for Error
Source§fn from(x: ConnectionError) -> Self
Converts to this type from the input type.Source§impl From<Error> for ConnectionError
Source§fn from(source: TransportError) -> Self
Converts to this type from the input type.Source§impl PartialEq for ConnectionError
Source§impl Eq for ConnectionError
Source§impl StructuralPartialEq for ConnectionError
Auto Trait Implementations§
§impl !Freeze for ConnectionError
§impl !RefUnwindSafe for ConnectionError
§impl Send for ConnectionError
§impl Sync for ConnectionError
§impl Unpin for ConnectionError
§impl !UnwindSafe for ConnectionError
Blanket Implementations§
Trait Implementations§
Source§impl Clone for ConnectionError
Source§fn clone(&self) -> ConnectionError
Returns a duplicate of the value. Read more1.0.0 · Source§fn clone_from(&mut self, source: &Self)
Performs copy-assignment from source. Read moreSource§impl Debug for ConnectionError
Source§impl Display for ConnectionError
Source§impl Error for ConnectionError
Source§fn source(&self) -> Option<&(dyn Error + 'static)>
Returns the lower-level source of this error, if any. Read more1.0.0 · Source§fn description(&self) -> &str
👎Deprecated since 1.42.0: use the Display impl or to_string()Source§impl From<ConnectionError> for Error
Source§fn from(x: ConnectionError) -> Self
Converts to this type from the input type.Source§impl From<Error> for ConnectionError
Source§fn from(source: TransportError) -> Self
Converts to this type from the input type.Source§impl PartialEq for ConnectionError
Source§impl Eq for ConnectionError
Source§impl StructuralPartialEq for ConnectionError
Auto Trait Implementations§
§impl !Freeze for ConnectionError
§impl !RefUnwindSafe for ConnectionError
§impl Send for ConnectionError
§impl Sync for ConnectionError
§impl Unpin for ConnectionError
§impl !UnwindSafe for ConnectionError
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read moreSource§impl<T> CloneToUninit for Twhere
diff --git a/pr/257/docs/iroh_quinn_proto/enum.Event.html b/pr/257/docs/iroh_quinn_proto/enum.Event.html
index da8f41a3d..a5d7ebae3 100644
--- a/pr/257/docs/iroh_quinn_proto/enum.Event.html
+++ b/pr/257/docs/iroh_quinn_proto/enum.Event.html
@@ -1,4 +1,4 @@
-Event in iroh_quinn_proto - Rust Event
pub enum Event {
+Event in iroh_quinn_proto - Rust Event
pub enum Event {
HandshakeDataReady,
Connected,
HandshakeConfirmed,
@@ -22,7 +22,7 @@
§DatagramsUnblocked
One or more application datagrams have been sent after blocking
§Path(PathEvent)
(Multi)Path events
§NatTraversal(Event)
Iroh’s nat traversal events
-
Trait Implementations§
Auto Trait Implementations§
§impl !Freeze for Event
§impl !RefUnwindSafe for Event
§impl Send for Event
§impl Sync for Event
§impl Unpin for Event
§impl !UnwindSafe for Event
Blanket Implementations§
Trait Implementations§
Auto Trait Implementations§
§impl !Freeze for Event
§impl !RefUnwindSafe for Event
§impl Send for Event
§impl Sync for Event
§impl Unpin for Event
§impl !UnwindSafe for Event
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read moreSource§impl<T> From<T> for T
Source§fn from(t: T) -> T
Returns the argument unchanged.
diff --git a/pr/257/docs/iroh_quinn_proto/enum.PathError.html b/pr/257/docs/iroh_quinn_proto/enum.PathError.html
index 08fec0580..ee36d9972 100644
--- a/pr/257/docs/iroh_quinn_proto/enum.PathError.html
+++ b/pr/257/docs/iroh_quinn_proto/enum.PathError.html
@@ -1,4 +1,4 @@
-PathError in iroh_quinn_proto - Rust PathError
pub enum PathError {
+PathError in iroh_quinn_proto - Rust PathError
pub enum PathError {
MultipathNotNegotiated,
ServerSideNotAllowed,
MaxPathIdReached,
@@ -12,8 +12,8 @@
§RemoteCidsExhausted
No remote CIDs available to open a new path
§ValidationFailed
Path could not be validated and will be abandoned
§InvalidRemoteAddress(SocketAddr)
The remote address for the path is not supported by the endpoint
-
Trait Implementations§
Source§impl Error for PathError
1.30.0 · Source§fn source(&self) -> Option<&(dyn Error + 'static)>
Returns the lower-level source of this error, if any. Read more1.0.0 · Source§fn description(&self) -> &str
👎Deprecated since 1.42.0: use the Display impl or to_string()Source§impl Copy for PathError
Source§impl Eq for PathError
Source§impl StructuralPartialEq for PathError
Auto Trait Implementations§
§impl Freeze for PathError
§impl RefUnwindSafe for PathError
§impl Send for PathError
§impl Sync for PathError
§impl Unpin for PathError
§impl UnwindSafe for PathError
Blanket Implementations§
Trait Implementations§
Source§impl Error for PathError
1.30.0 · Source§fn source(&self) -> Option<&(dyn Error + 'static)>
Returns the lower-level source of this error, if any. Read more1.0.0 · Source§fn description(&self) -> &str
👎Deprecated since 1.42.0: use the Display impl or to_string()Source§impl Copy for PathError
Source§impl Eq for PathError
Source§impl StructuralPartialEq for PathError
Auto Trait Implementations§
§impl Freeze for PathError
§impl RefUnwindSafe for PathError
§impl Send for PathError
§impl Sync for PathError
§impl Unpin for PathError
§impl UnwindSafe for PathError
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read moreSource§impl<T> CloneToUninit for Twhere
diff --git a/pr/257/docs/iroh_quinn_proto/enum.PathEvent.html b/pr/257/docs/iroh_quinn_proto/enum.PathEvent.html
index 8bb9341ce..6c19c57f6 100644
--- a/pr/257/docs/iroh_quinn_proto/enum.PathEvent.html
+++ b/pr/257/docs/iroh_quinn_proto/enum.PathEvent.html
@@ -47,7 +47,7 @@ changes the status.
Fields
§id: PathIdPath over which the observed address was reported, PathId::ZERO when multipath is
not negotiated
§addr: SocketAddrThe address observed by the remote over this path
-
Trait Implementations§
Trait Implementations§
Source§impl Eq for PathEvent
Source§impl StructuralPartialEq for PathEvent
Auto Trait Implementations§
§impl Freeze for PathEvent
§impl RefUnwindSafe for PathEvent
§impl Send for PathEvent
§impl Sync for PathEvent
§impl Unpin for PathEvent
§impl UnwindSafe for PathEvent
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
diff --git a/pr/257/docs/iroh_quinn_proto/struct.Connection.html b/pr/257/docs/iroh_quinn_proto/struct.Connection.html
index d574be254..f30d3b4ed 100644
--- a/pr/257/docs/iroh_quinn_proto/struct.Connection.html
+++ b/pr/257/docs/iroh_quinn_proto/struct.Connection.html
@@ -33,7 +33,7 @@ increasing time. Specifically, calling Instant may be interleaved in any order with a
call to handle_event at that same instant; however
events or timeouts with different instants must not be interleaved.
-
Implementations§
Source§impl Connection
Sourcepub fn poll_timeout(&mut self) -> Option<Instant>
Returns the next time at which handle_timeout should be called
+Implementations§
Source§impl Connection
Sourcepub fn poll_timeout(&mut self) -> Option<Instant>
Returns the next time at which handle_timeout should be called
The value returned may change after:
- the application performed some I/O on the connection
@@ -217,7 +217,7 @@ available paths
Sourcepub fn get_remote_nat_traversal_addresses(
&self,
) -> Result<Vec<SocketAddr>, Error>
Get the currently advertised nat traversal addresses by the server
-Sourcepub fn initiate_nat_traversal_round(
+
Sourcepub fn initiate_nat_traversal_round(
&mut self,
now: Instant,
) -> Result<Vec<SocketAddr>, Error>
Initiates a new nat traversal round
@@ -225,7 +225,7 @@ available paths
frames, and initiating probing of the known remote addresses. When a new round is
initiated, the previous one is cancelled, and paths that have not been opened are closed.
Returns the server addresses that are now being probed.
-Trait Implementations§
Auto Trait Implementations§
§impl !Freeze for Connection
§impl !RefUnwindSafe for Connection
§impl Send for Connection
§impl Sync for Connection
§impl Unpin for Connection
§impl !UnwindSafe for Connection
Blanket Implementations§
Trait Implementations§
Auto Trait Implementations§
§impl !Freeze for Connection
§impl !RefUnwindSafe for Connection
§impl Send for Connection
§impl Sync for Connection
§impl Unpin for Connection
§impl !UnwindSafe for Connection
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read moreSource§impl<T> From<T> for T
Source§fn from(t: T) -> T
Returns the argument unchanged.
diff --git a/pr/257/docs/iroh_quinn_proto/struct.TransportError.html b/pr/257/docs/iroh_quinn_proto/struct.TransportError.html
index 38d27e6cb..209ea0630 100644
--- a/pr/257/docs/iroh_quinn_proto/struct.TransportError.html
+++ b/pr/257/docs/iroh_quinn_proto/struct.TransportError.html
@@ -11,7 +11,7 @@
§reason: StringHuman-readable explanation of the reason
§crypto: Option<Arc<dyn Error + Send + Sync>>An underlying crypto (e.g. TLS) layer error
Implementations§
Trait Implementations§
Source§impl Error for Error
1.30.0 · Source§fn source(&self) -> Option<&(dyn Error + 'static)>
Returns the lower-level source of this error, if any. Read more1.0.0 · Source§fn description(&self) -> &str
👎Deprecated since 1.42.0: use the Display impl or to_string()Source§impl From<Error> for ConnectionClose
Source§fn from(x: TransportError) -> Self
Converts to this type from the input type.Source§impl From<Error> for ConnectionError
Source§fn from(source: TransportError) -> Self
Converts to this type from the input type.Source§impl From<Error> for TransportError
Trait Implementations§
Source§impl Error for Error
1.30.0 · Source§fn source(&self) -> Option<&(dyn Error + 'static)>
Returns the lower-level source of this error, if any. Read more1.0.0 · Source§fn description(&self) -> &str
👎Deprecated since 1.42.0: use the Display impl or to_string()Source§impl From<Error> for ConnectionClose
Source§fn from(x: TransportError) -> Self
Converts to this type from the input type.Source§impl From<Error> for ConnectionError
Source§fn from(source: TransportError) -> Self
Converts to this type from the input type.Source§impl From<Error> for TransportError
Source§impl Eq for Error
Auto Trait Implementations§
§impl Freeze for Error
§impl !RefUnwindSafe for Error
§impl Send for Error
§impl Sync for Error
§impl Unpin for Error
§impl !UnwindSafe for Error
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
diff --git a/pr/257/docs/src/iroh_quinn/recv_stream.rs.html b/pr/257/docs/src/iroh_quinn/recv_stream.rs.html
index 1620bf119..4e7dce4ed 100644
--- a/pr/257/docs/src/iroh_quinn/recv_stream.rs.html
+++ b/pr/257/docs/src/iroh_quinn/recv_stream.rs.html
@@ -57,702 +57,711 @@
57 reset: Option<VarInt>,
58}
59
-60#[derive(Debug)]
-61#[repr(transparent)]
-62pub struct UnorderedRecvStream {
-63 inner: RecvStream,
-64}
-65
-66impl RecvStream {
-67 pub(crate) fn new(conn: ConnectionRef, stream: StreamId, is_0rtt: bool) -> Self {
-68 Self {
-69 conn,
-70 stream,
-71 is_0rtt,
-72 all_data_read: false,
-73 reset: None,
-74 }
-75 }
-76
-77 /// Read data contiguously from the stream.
-78 ///
-79 /// Yields the number of bytes read into `buf` on success, or `None` if the stream was finished.
-80 ///
-81 /// This operation is cancel-safe.
-82 pub async fn read(&mut self, buf: &mut [u8]) -> Result<Option<usize>, ReadError> {
-83 Read {
-84 stream: self,
-85 buf: ReadBuf::new(buf),
-86 }
-87 .await
-88 }
-89
-90 /// Read an exact number of bytes contiguously from the stream.
-91 ///
-92 /// See [`read()`] for details. This operation is *not* cancel-safe.
-93 ///
-94 /// [`read()`]: RecvStream::read
-95 pub async fn read_exact(&mut self, buf: &mut [u8]) -> Result<(), ReadExactError> {
-96 ReadExact {
-97 stream: self,
-98 buf: ReadBuf::new(buf),
-99 }
-100 .await
-101 }
-102
-103 /// Attempts to read from the stream into the provided buffer
-104 ///
-105 /// On success, returns `Poll::Ready(Ok(num_bytes_read))` and places data into `buf`. If this
-106 /// returns zero bytes read (and `buf` has a non-zero length), that indicates that the remote
-107 /// side has [`finish`]ed the stream and the local side has already read all bytes.
-108 ///
-109 /// If no data is available for reading, this returns `Poll::Pending` and arranges for the
-110 /// current task (via `cx.waker()`) to be notified when the stream becomes readable or is
-111 /// closed.
-112 ///
-113 /// [`finish`]: crate::SendStream::finish
-114 pub fn poll_read(
-115 &mut self,
-116 cx: &mut Context,
-117 buf: &mut [u8],
-118 ) -> Poll<Result<usize, ReadError>> {
-119 let mut buf = ReadBuf::new(buf);
-120 ready!(self.poll_read_buf(cx, &mut buf))?;
-121 Poll::Ready(Ok(buf.filled().len()))
-122 }
-123
-124 /// Attempts to read from the stream into the provided buffer, which may be uninitialized
-125 ///
-126 /// On success, returns `Poll::Ready(Ok(()))` and places data into the unfilled portion of
-127 /// `buf`. If this does not write any bytes to `buf` (and `buf.remaining()` is non-zero), that
-128 /// indicates that the remote side has [`finish`]ed the stream and the local side has already
-129 /// read all bytes.
-130 ///
-131 /// If no data is available for reading, this returns `Poll::Pending` and arranges for the
-132 /// current task (via `cx.waker()`) to be notified when the stream becomes readable or is
-133 /// closed.
+60/// A stream that can be used to receive data out-of-order.
+61///
+62/// Obtained by converting a [`RecvStream`] via [`RecvStream::into_unordered`].
+63///
+64/// This variant of `RecvStream` allows reading chunks of data *exclusively*
+65/// out of order. Once you have done an unordered read, ordered reads are no
+66/// longer possible since data may have been consumed out of order.
+67///
+68/// The stream state related fns like [`Self::id`], [`Self::is_0rtt`], [`Self::stop`], and
+69/// [`Self::received_reset`] behave exactly as on [`RecvStream`].
+70#[derive(Debug)]
+71pub struct UnorderedRecvStream {
+72 inner: RecvStream,
+73}
+74
+75impl RecvStream {
+76 pub(crate) fn new(conn: ConnectionRef, stream: StreamId, is_0rtt: bool) -> Self {
+77 Self {
+78 conn,
+79 stream,
+80 is_0rtt,
+81 all_data_read: false,
+82 reset: None,
+83 }
+84 }
+85
+86 /// Read data contiguously from the stream.
+87 ///
+88 /// Yields the number of bytes read into `buf` on success, or `None` if the stream was finished.
+89 ///
+90 /// This operation is cancel-safe.
+91 pub async fn read(&mut self, buf: &mut [u8]) -> Result<Option<usize>, ReadError> {
+92 Read {
+93 stream: self,
+94 buf: ReadBuf::new(buf),
+95 }
+96 .await
+97 }
+98
+99 /// Read an exact number of bytes contiguously from the stream.
+100 ///
+101 /// See [`read()`] for details. This operation is *not* cancel-safe.
+102 ///
+103 /// [`read()`]: RecvStream::read
+104 pub async fn read_exact(&mut self, buf: &mut [u8]) -> Result<(), ReadExactError> {
+105 ReadExact {
+106 stream: self,
+107 buf: ReadBuf::new(buf),
+108 }
+109 .await
+110 }
+111
+112 /// Attempts to read from the stream into the provided buffer
+113 ///
+114 /// On success, returns `Poll::Ready(Ok(num_bytes_read))` and places data into `buf`. If this
+115 /// returns zero bytes read (and `buf` has a non-zero length), that indicates that the remote
+116 /// side has [`finish`]ed the stream and the local side has already read all bytes.
+117 ///
+118 /// If no data is available for reading, this returns `Poll::Pending` and arranges for the
+119 /// current task (via `cx.waker()`) to be notified when the stream becomes readable or is
+120 /// closed.
+121 ///
+122 /// [`finish`]: crate::SendStream::finish
+123 pub fn poll_read(
+124 &mut self,
+125 cx: &mut Context,
+126 buf: &mut [u8],
+127 ) -> Poll<Result<usize, ReadError>> {
+128 let mut buf = ReadBuf::new(buf);
+129 ready!(self.poll_read_buf(cx, &mut buf))?;
+130 Poll::Ready(Ok(buf.filled().len()))
+131 }
+132
+133 /// Attempts to read from the stream into the provided buffer, which may be uninitialized
134 ///
-135 /// [`finish`]: crate::SendStream::finish
-136 pub fn poll_read_buf(
-137 &mut self,
-138 cx: &mut Context,
-139 buf: &mut ReadBuf<'_>,
-140 ) -> Poll<Result<(), ReadError>> {
-141 if buf.remaining() == 0 {
-142 return Poll::Ready(Ok(()));
-143 }
-144
-145 self.poll_read_generic(cx, true, |chunks| {
-146 let mut read = false;
-147 loop {
-148 if buf.remaining() == 0 {
-149 // We know `read` is `true` because `buf.remaining()` was not 0 before
-150 return ReadStatus::Readable(());
-151 }
-152
-153 match chunks.next(buf.remaining()) {
-154 Ok(Some(chunk)) => {
-155 buf.put_slice(&chunk.bytes);
-156 read = true;
-157 }
-158 res => return (if read { Some(()) } else { None }, res.err()).into(),
-159 }
-160 }
-161 })
-162 .map(|res| res.map(|_| ()))
-163 }
-164
-165 /// Read the next segment of data
-166 ///
-167 /// Yields `None` if the stream was finished. Otherwise, yields a segment of data and its
-168 /// offset in the stream. The chunk's offset will be immediately after
-169 /// the last data yielded by [`RecvStream::read`] or [`RecvStream::read_chunk`].
-170 ///
-171 /// For unordered reads, convert the stream into an unordered stream using [`Self::into_unordered`].
-172 ///
-173 /// Slightly more efficient than [`RecvStream::read`] due to not copying. Chunk boundaries do not correspond
-174 /// to peer writes, and hence cannot be used as framing.
+135 /// On success, returns `Poll::Ready(Ok(()))` and places data into the unfilled portion of
+136 /// `buf`. If this does not write any bytes to `buf` (and `buf.remaining()` is non-zero), that
+137 /// indicates that the remote side has [`finish`]ed the stream and the local side has already
+138 /// read all bytes.
+139 ///
+140 /// If no data is available for reading, this returns `Poll::Pending` and arranges for the
+141 /// current task (via `cx.waker()`) to be notified when the stream becomes readable or is
+142 /// closed.
+143 ///
+144 /// [`finish`]: crate::SendStream::finish
+145 pub fn poll_read_buf(
+146 &mut self,
+147 cx: &mut Context,
+148 buf: &mut ReadBuf<'_>,
+149 ) -> Poll<Result<(), ReadError>> {
+150 if buf.remaining() == 0 {
+151 return Poll::Ready(Ok(()));
+152 }
+153
+154 self.poll_read_generic(cx, true, |chunks| {
+155 let mut read = false;
+156 loop {
+157 if buf.remaining() == 0 {
+158 // We know `read` is `true` because `buf.remaining()` was not 0 before
+159 return ReadStatus::Readable(());
+160 }
+161
+162 match chunks.next(buf.remaining()) {
+163 Ok(Some(chunk)) => {
+164 buf.put_slice(&chunk.bytes);
+165 read = true;
+166 }
+167 res => return (if read { Some(()) } else { None }, res.err()).into(),
+168 }
+169 }
+170 })
+171 .map(|res| res.map(|_| ()))
+172 }
+173
+174 /// Read the next segment of data
175 ///
-176 /// This operation is cancel-safe.
-177 pub async fn read_chunk(&mut self, max_length: usize) -> Result<Option<Chunk>, ReadError> {
-178 ReadChunk {
-179 stream: self,
-180 max_length,
-181 ordered: true,
-182 }
-183 .await
-184 }
-185
-186 /// Attempts to read a chunk from the stream.
-187 ///
-188 /// On success, returns `Poll::Ready(Ok(Some(chunk)))`. If `Poll::Ready(Ok(None))`
-189 /// is returned, it implies that EOF has been reached.
-190 ///
-191 /// If no data is available for reading, the method returns `Poll::Pending`
-192 /// and arranges for the current task (via cx.waker()) to receive a notification
-193 /// when the stream becomes readable or is closed.
-194 fn poll_read_chunk(
-195 &mut self,
-196 cx: &mut Context,
-197 max_length: usize,
-198 ordered: bool,
-199 ) -> Poll<Result<Option<Chunk>, ReadError>> {
-200 self.poll_read_generic(cx, ordered, |chunks| match chunks.next(max_length) {
-201 Ok(Some(chunk)) => ReadStatus::Readable(chunk),
-202 res => (None, res.err()).into(),
-203 })
-204 }
-205
-206 /// Read the next segments of data
-207 ///
-208 /// Fills `bufs` with the segments of data beginning immediately after the
-209 /// last data yielded by `read` or `read_chunk`, or `None` if the stream was
-210 /// finished.
-211 ///
-212 /// Slightly more efficient than `read` due to not copying. Chunk boundaries
-213 /// do not correspond to peer writes, and hence cannot be used as framing.
-214 ///
-215 /// This operation is cancel-safe.
-216 pub async fn read_chunks(&mut self, bufs: &mut [Bytes]) -> Result<Option<usize>, ReadError> {
-217 ReadChunks { stream: self, bufs }.await
-218 }
-219
-220 /// Foundation of [`Self::read_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.
+176 /// Yields `None` if the stream was finished. Otherwise, yields a segment of data and its
+177 /// offset in the stream. The chunk's offset will be immediately after
+178 /// the last data yielded by [`RecvStream::read`] or [`RecvStream::read_chunk`].
+179 ///
+180 /// For unordered reads, convert the stream into an unordered stream using [`Self::into_unordered`].
+181 ///
+182 /// Slightly more efficient than [`RecvStream::read`] due to not copying. Chunk boundaries do not correspond
+183 /// to peer writes, and hence cannot be used as framing.
+184 ///
+185 /// This operation is cancel-safe.
+186 pub async fn read_chunk(&mut self, max_length: usize) -> Result<Option<Chunk>, ReadError> {
+187 ReadChunk {
+188 stream: self,
+189 max_length,
+190 ordered: true,
+191 }
+192 .await
+193 }
+194
+195 /// Attempts to read a chunk from the stream.
+196 ///
+197 /// On success, returns `Poll::Ready(Ok(Some(chunk)))`. If `Poll::Ready(Ok(None))`
+198 /// is returned, it implies that EOF has been reached.
+199 ///
+200 /// If no data is available for reading, the method returns `Poll::Pending`
+201 /// and arranges for the current task (via cx.waker()) to receive a notification
+202 /// when the stream becomes readable or is closed.
+203 fn poll_read_chunk(
+204 &mut self,
+205 cx: &mut Context,
+206 max_length: usize,
+207 ordered: bool,
+208 ) -> Poll<Result<Option<Chunk>, ReadError>> {
+209 self.poll_read_generic(cx, ordered, |chunks| match chunks.next(max_length) {
+210 Ok(Some(chunk)) => ReadStatus::Readable(chunk),
+211 res => (None, res.err()).into(),
+212 })
+213 }
+214
+215 /// Read the next segments of data
+216 ///
+217 /// Fills `bufs` with the segments of data beginning immediately after the
+218 /// last data yielded by `read` or `read_chunk`, or `None` if the stream was
+219 /// finished.
+220 ///
+221 /// Slightly more efficient than `read` due to not copying. Chunk boundaries
+222 /// do not correspond to peer writes, and hence cannot be used as framing.
+223 ///
+224 /// This operation is cancel-safe.
+225 pub async fn read_chunks(&mut self, bufs: &mut [Bytes]) -> Result<Option<usize>, ReadError> {
+226 ReadChunks { stream: self, bufs }.await
+227 }
+228
+229 /// Foundation of [`Self::read_chunks`]
+230 fn poll_read_chunks(
+231 &mut self,
+232 cx: &mut Context,
+233 bufs: &mut [Bytes],
+234 ) -> Poll<Result<Option<usize>, ReadError>> {
+235 if bufs.is_empty() {
+236 return Poll::Ready(Ok(Some(0)));
+237 }
+238
+239 self.poll_read_generic(cx, true, |chunks| {
+240 let mut read = 0;
+241 loop {
+242 if read >= bufs.len() {
+243 // We know `read > 0` because `bufs` cannot be empty here
+244 return ReadStatus::Readable(read);
+245 }
+246
+247 match chunks.next(usize::MAX) {
+248 Ok(Some(chunk)) => {
+249 bufs[read] = chunk.bytes;
+250 read += 1;
+251 }
+252 res => return (if read == 0 { None } else { Some(read) }, res.err()).into(),
+253 }
+254 }
+255 })
+256 }
+257
+258 /// Convenience method to read all remaining data into a buffer
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.state.lock("RecvStream::stop");
-278 if self.is_0rtt && conn.check_0rtt().is_err() {
-279 return Ok(());
-280 }
-281 conn.inner.recv_stream(self.stream).stop(error_code)?;
-282 conn.wake();
-283 self.all_data_read = true;
-284 Ok(())
-285 }
-286
-287 /// Check if this stream has been opened during 0-RTT.
-288 ///
-289 /// In which case any non-idempotent request should be considered dangerous at the application
-290 /// level. Because read data is subject to replay attacks.
-291 pub fn is_0rtt(&self) -> bool {
-292 self.is_0rtt
-293 }
-294
-295 /// Get the identity of this stream
-296 pub fn id(&self) -> StreamId {
-297 self.stream
-298 }
-299
-300 /// Completes when the stream has been reset by the peer or otherwise closed
-301 ///
-302 /// Yields `Some` with the reset error code when the stream is reset by the peer. Yields `None`
-303 /// when the stream was previously [`stop()`](Self::stop)ed, or when the stream was
-304 /// [`finish()`](crate::SendStream::finish)ed by the peer and all data has been received, after
-305 /// which it is no longer meaningful for the stream to be reset.
-306 ///
-307 /// This operation is cancel-safe.
-308 pub async fn received_reset(&mut self) -> Result<Option<VarInt>, ResetError> {
-309 poll_fn(|cx| {
-310 let mut conn = self.conn.state.lock("RecvStream::reset");
-311 if self.is_0rtt && conn.check_0rtt().is_err() {
-312 return Poll::Ready(Err(ResetError::ZeroRttRejected));
-313 }
-314
-315 if let Some(code) = self.reset {
-316 return Poll::Ready(Ok(Some(code)));
-317 }
-318
-319 match conn.inner.recv_stream(self.stream).received_reset() {
-320 Err(_) => Poll::Ready(Ok(None)),
-321 Ok(Some(error_code)) => {
-322 // Stream state has just now been freed, so the connection may need to issue new
-323 // stream ID flow control credit
-324 conn.wake();
-325 Poll::Ready(Ok(Some(error_code)))
-326 }
-327 Ok(None) => {
-328 if let Some(e) = &conn.error {
-329 return Poll::Ready(Err(e.clone().into()));
-330 }
-331 // Resets always notify readers, since a reset is an immediate read error. We
-332 // could introduce a dedicated channel to reduce the risk of spurious wakeups,
-333 // but that increased complexity is probably not justified, as an application
-334 // that is expecting a reset is not likely to receive large amounts of data.
-335 conn.blocked_readers.insert(self.stream, cx.waker().clone());
-336 Poll::Pending
-337 }
-338 }
-339 })
-340 .await
-341 }
-342
-343 /// Handle common logic related to reading out of a receive stream
-344 ///
-345 /// This takes an `FnMut` closure that takes care of the actual reading process, matching
-346 /// the detailed read semantics for the calling function with a particular return type.
-347 /// The closure can read from the passed `&mut Chunks` and has to return the status after
-348 /// reading: the amount of data read, and the status after the final read call.
-349 fn poll_read_generic<T, U>(
-350 &mut self,
-351 cx: &mut Context,
-352 ordered: bool,
-353 mut read_fn: T,
-354 ) -> Poll<Result<Option<U>, ReadError>>
-355 where
-356 T: FnMut(&mut Chunks) -> ReadStatus<U>,
-357 {
-358 use proto::ReadError::*;
-359 if self.all_data_read {
-360 return Poll::Ready(Ok(None));
-361 }
-362
-363 let mut conn = self.conn.state.lock("RecvStream::poll_read");
-364 if self.is_0rtt {
-365 conn.check_0rtt().map_err(|()| ReadError::ZeroRttRejected)?;
-366 }
-367
-368 // If we stored an error during a previous call, return it now. This can happen if a
-369 // `read_fn` both wants to return data and also returns an error in its final stream status.
-370 let status = match self.reset {
-371 Some(code) => ReadStatus::Failed(None, Reset(code)),
-372 None => {
-373 let mut recv = conn.inner.recv_stream(self.stream);
-374 let mut chunks = recv.read(ordered)?;
-375 let status = read_fn(&mut chunks);
-376 if chunks.finalize().should_transmit() {
-377 conn.wake();
-378 }
-379 status
-380 }
-381 };
-382
-383 match status {
-384 ReadStatus::Readable(read) => Poll::Ready(Ok(Some(read))),
-385 ReadStatus::Finished(read) => {
-386 self.all_data_read = true;
-387 Poll::Ready(Ok(read))
-388 }
-389 ReadStatus::Failed(read, Blocked) => match read {
-390 Some(val) => Poll::Ready(Ok(Some(val))),
-391 None => {
-392 if let Some(ref x) = conn.error {
-393 return Poll::Ready(Err(ReadError::ConnectionLost(x.clone())));
-394 }
-395 conn.blocked_readers.insert(self.stream, cx.waker().clone());
-396 Poll::Pending
-397 }
-398 },
-399 ReadStatus::Failed(read, Reset(error_code)) => match read {
+260 /// Fails with [`ReadToEndError::TooLong`] on reading more than `size_limit` bytes, discarding
+261 /// all data read. Uses unordered reads to be more efficient than using `AsyncRead` would
+262 /// allow. `size_limit` should be set to limit worst-case memory use.
+263 ///
+264 /// If unordered reads have already been made, the resulting buffer may have gaps containing
+265 /// arbitrary data.
+266 ///
+267 /// This operation is *not* cancel-safe.
+268 ///
+269 /// [`ReadToEndError::TooLong`]: crate::ReadToEndError::TooLong
+270 pub async fn read_to_end(&mut self, size_limit: usize) -> Result<Vec<u8>, ReadToEndError> {
+271 ReadToEnd {
+272 stream: self,
+273 size_limit,
+274 read: Vec::new(),
+275 start: u64::MAX,
+276 end: 0,
+277 }
+278 .await
+279 }
+280
+281 /// Stop accepting data
+282 ///
+283 /// Discards unread data and notifies the peer to stop transmitting. Once stopped, further
+284 /// attempts to operate on a stream will yield `ClosedStream` errors.
+285 pub fn stop(&mut self, error_code: VarInt) -> Result<(), ClosedStream> {
+286 let mut conn = self.conn.state.lock("RecvStream::stop");
+287 if self.is_0rtt && conn.check_0rtt().is_err() {
+288 return Ok(());
+289 }
+290 conn.inner.recv_stream(self.stream).stop(error_code)?;
+291 conn.wake();
+292 self.all_data_read = true;
+293 Ok(())
+294 }
+295
+296 /// Check if this stream has been opened during 0-RTT.
+297 ///
+298 /// In which case any non-idempotent request should be considered dangerous at the application
+299 /// level. Because read data is subject to replay attacks.
+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 /// Completes when the stream has been reset by the peer or otherwise closed
+310 ///
+311 /// Yields `Some` with the reset error code when the stream is reset by the peer. Yields `None`
+312 /// when the stream was previously [`stop()`](Self::stop)ed, or when the stream was
+313 /// [`finish()`](crate::SendStream::finish)ed by the peer and all data has been received, after
+314 /// which it is no longer meaningful for the stream to be reset.
+315 ///
+316 /// This operation is cancel-safe.
+317 pub async fn received_reset(&mut self) -> Result<Option<VarInt>, ResetError> {
+318 poll_fn(|cx| {
+319 let mut conn = self.conn.state.lock("RecvStream::reset");
+320 if self.is_0rtt && conn.check_0rtt().is_err() {
+321 return Poll::Ready(Err(ResetError::ZeroRttRejected));
+322 }
+323
+324 if let Some(code) = self.reset {
+325 return Poll::Ready(Ok(Some(code)));
+326 }
+327
+328 match conn.inner.recv_stream(self.stream).received_reset() {
+329 Err(_) => Poll::Ready(Ok(None)),
+330 Ok(Some(error_code)) => {
+331 // Stream state has just now been freed, so the connection may need to issue new
+332 // stream ID flow control credit
+333 conn.wake();
+334 Poll::Ready(Ok(Some(error_code)))
+335 }
+336 Ok(None) => {
+337 if let Some(e) = &conn.error {
+338 return Poll::Ready(Err(e.clone().into()));
+339 }
+340 // Resets always notify readers, since a reset is an immediate read error. We
+341 // could introduce a dedicated channel to reduce the risk of spurious wakeups,
+342 // but that increased complexity is probably not justified, as an application
+343 // that is expecting a reset is not likely to receive large amounts of data.
+344 conn.blocked_readers.insert(self.stream, cx.waker().clone());
+345 Poll::Pending
+346 }
+347 }
+348 })
+349 .await
+350 }
+351
+352 /// Handle common logic related to reading out of a receive stream
+353 ///
+354 /// This takes an `FnMut` closure that takes care of the actual reading process, matching
+355 /// the detailed read semantics for the calling function with a particular return type.
+356 /// The closure can read from the passed `&mut Chunks` and has to return the status after
+357 /// reading: the amount of data read, and the status after the final read call.
+358 fn poll_read_generic<T, U>(
+359 &mut self,
+360 cx: &mut Context,
+361 ordered: bool,
+362 mut read_fn: T,
+363 ) -> Poll<Result<Option<U>, ReadError>>
+364 where
+365 T: FnMut(&mut Chunks) -> ReadStatus<U>,
+366 {
+367 use proto::ReadError::*;
+368 if self.all_data_read {
+369 return Poll::Ready(Ok(None));
+370 }
+371
+372 let mut conn = self.conn.state.lock("RecvStream::poll_read");
+373 if self.is_0rtt {
+374 conn.check_0rtt().map_err(|()| ReadError::ZeroRttRejected)?;
+375 }
+376
+377 // If we stored an error during a previous call, return it now. This can happen if a
+378 // `read_fn` both wants to return data and also returns an error in its final stream status.
+379 let status = match self.reset {
+380 Some(code) => ReadStatus::Failed(None, Reset(code)),
+381 None => {
+382 let mut recv = conn.inner.recv_stream(self.stream);
+383 let mut chunks = recv.read(ordered)?;
+384 let status = read_fn(&mut chunks);
+385 if chunks.finalize().should_transmit() {
+386 conn.wake();
+387 }
+388 status
+389 }
+390 };
+391
+392 match status {
+393 ReadStatus::Readable(read) => Poll::Ready(Ok(Some(read))),
+394 ReadStatus::Finished(read) => {
+395 self.all_data_read = true;
+396 Poll::Ready(Ok(read))
+397 }
+398 ReadStatus::Failed(read, Blocked) => match read {
+399 Some(val) => Poll::Ready(Ok(Some(val))),
400 None => {
-401 self.all_data_read = true;
-402 self.reset = Some(error_code);
-403 Poll::Ready(Err(ReadError::Reset(error_code)))
-404 }
-405 done => {
-406 self.reset = Some(error_code);
-407 Poll::Ready(Ok(done))
-408 }
-409 },
-410 }
-411 }
-412
-413 /// Converts this stream into an unordered stream.
-414 pub fn into_unordered(self) -> UnorderedRecvStream {
-415 UnorderedRecvStream { inner: self }
-416 }
-417}
-418
-419impl UnorderedRecvStream {
-420 /// Reads the next segment of data.
-421 ///
-422 /// Yields `None` if the stream was finished. Otherwise, yields a segment of data and its
-423 /// offset in the stream. Segments may be received in any order, and the `Chunk`'s `offset`
-424 /// field can be used to determine ordering in the caller. Unordered reads are less prone
-425 /// to head-of-line blocking within a stream, but require the application to manage
-426 /// reassembling the original data.
-427 ///
-428 /// This operation is cancel-safe.
-429 pub async fn read_chunk(&mut self, max_length: usize) -> Result<Option<Chunk>, ReadError> {
-430 ReadChunk {
-431 stream: &mut self.inner,
-432 max_length,
-433 ordered: false,
-434 }
-435 .await
-436 }
-437
-438 /// Get the identity of this stream
-439 pub fn id(&self) -> StreamId {
-440 self.inner.id()
-441 }
-442
-443 /// Check if this stream has been opened during 0-RTT.
-444 ///
-445 /// In which case any non-idempotent request should be considered dangerous at the application
-446 /// level. Because read data is subject to replay attacks.
-447 pub fn is_0rtt(&self) -> bool {
-448 self.inner.is_0rtt()
-449 }
-450
-451 /// Stop accepting data
-452 ///
-453 /// Discards unread data and notifies the peer to stop transmitting. Once stopped, further
-454 /// attempts to operate on a stream will yield `ClosedStream` errors.
-455 pub fn stop(&mut self, error_code: VarInt) -> Result<(), ClosedStream> {
-456 self.inner.stop(error_code)
-457 }
-458
-459 /// Completes when the stream has been reset by the peer or otherwise closed
-460 ///
-461 /// Yields `Some` with the reset error code when the stream is reset by the peer. Yields `None`
-462 /// when the stream was previously [`stop()`](Self::stop)ed, or when the stream was
-463 /// [`finish()`](crate::SendStream::finish)ed by the peer and all data has been received, after
-464 /// which it is no longer meaningful for the stream to be reset.
-465 ///
-466 /// This operation is cancel-safe.
-467 pub async fn received_reset(&mut self) -> Result<Option<VarInt>, ResetError> {
-468 self.inner.received_reset().await
-469 }
-470}
-471
-472enum ReadStatus<T> {
-473 Readable(T),
-474 Finished(Option<T>),
-475 Failed(Option<T>, proto::ReadError),
-476}
-477
-478impl<T> From<(Option<T>, Option<proto::ReadError>)> for ReadStatus<T> {
-479 fn from(status: (Option<T>, Option<proto::ReadError>)) -> Self {
-480 match status {
-481 (read, None) => Self::Finished(read),
-482 (read, Some(e)) => Self::Failed(read, e),
-483 }
-484 }
+401 if let Some(ref x) = conn.error {
+402 return Poll::Ready(Err(ReadError::ConnectionLost(x.clone())));
+403 }
+404 conn.blocked_readers.insert(self.stream, cx.waker().clone());
+405 Poll::Pending
+406 }
+407 },
+408 ReadStatus::Failed(read, Reset(error_code)) => match read {
+409 None => {
+410 self.all_data_read = true;
+411 self.reset = Some(error_code);
+412 Poll::Ready(Err(ReadError::Reset(error_code)))
+413 }
+414 done => {
+415 self.reset = Some(error_code);
+416 Poll::Ready(Ok(done))
+417 }
+418 },
+419 }
+420 }
+421
+422 /// Converts this stream into an unordered stream.
+423 pub fn into_unordered(self) -> UnorderedRecvStream {
+424 UnorderedRecvStream { inner: self }
+425 }
+426}
+427
+428impl UnorderedRecvStream {
+429 /// Reads the next segment of data.
+430 ///
+431 /// Yields `None` if the stream was finished. Otherwise, yields a segment of data and its
+432 /// offset in the stream. Segments may be received in any order, and the `Chunk`'s `offset`
+433 /// field can be used to determine ordering in the caller. Unordered reads are less prone
+434 /// to head-of-line blocking within a stream, but require the application to manage
+435 /// reassembling the original data.
+436 ///
+437 /// This operation is cancel-safe.
+438 pub async fn read_chunk(&mut self, max_length: usize) -> Result<Option<Chunk>, ReadError> {
+439 ReadChunk {
+440 stream: &mut self.inner,
+441 max_length,
+442 ordered: false,
+443 }
+444 .await
+445 }
+446
+447 /// Get the identity of this stream
+448 pub fn id(&self) -> StreamId {
+449 self.inner.id()
+450 }
+451
+452 /// Check if this stream has been opened during 0-RTT.
+453 ///
+454 /// In which case any non-idempotent request should be considered dangerous at the application
+455 /// level. Because read data is subject to replay attacks.
+456 pub fn is_0rtt(&self) -> bool {
+457 self.inner.is_0rtt()
+458 }
+459
+460 /// Stop accepting data
+461 ///
+462 /// Discards unread data and notifies the peer to stop transmitting. Once stopped, further
+463 /// attempts to operate on a stream will yield `ClosedStream` errors.
+464 pub fn stop(&mut self, error_code: VarInt) -> Result<(), ClosedStream> {
+465 self.inner.stop(error_code)
+466 }
+467
+468 /// Completes when the stream has been reset by the peer or otherwise closed
+469 ///
+470 /// Yields `Some` with the reset error code when the stream is reset by the peer. Yields `None`
+471 /// when the stream was previously [`stop()`](Self::stop)ed, or when the stream was
+472 /// [`finish()`](crate::SendStream::finish)ed by the peer and all data has been received, after
+473 /// which it is no longer meaningful for the stream to be reset.
+474 ///
+475 /// This operation is cancel-safe.
+476 pub async fn received_reset(&mut self) -> Result<Option<VarInt>, ResetError> {
+477 self.inner.received_reset().await
+478 }
+479}
+480
+481enum ReadStatus<T> {
+482 Readable(T),
+483 Finished(Option<T>),
+484 Failed(Option<T>, proto::ReadError),
485}
486
-487/// Future produced by [`RecvStream::read_to_end()`].
-488///
-489/// [`RecvStream::read_to_end()`]: crate::RecvStream::read_to_end
-490struct ReadToEnd<'a> {
-491 stream: &'a mut RecvStream,
-492 read: Vec<(Bytes, u64)>,
-493 start: u64,
-494 end: u64,
-495 size_limit: usize,
-496}
-497
-498impl Future for ReadToEnd<'_> {
-499 type Output = Result<Vec<u8>, ReadToEndError>;
-500 fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
-501 loop {
-502 match ready!(self.stream.poll_read_chunk(cx, usize::MAX, false))? {
-503 Some(chunk) => {
-504 self.start = self.start.min(chunk.offset);
-505 let end = chunk.bytes.len() as u64 + chunk.offset;
-506 if (end - self.start) > self.size_limit as u64 {
-507 return Poll::Ready(Err(ReadToEndError::TooLong));
-508 }
-509 self.end = self.end.max(end);
-510 self.read.push((chunk.bytes, chunk.offset));
-511 }
-512 None => {
-513 if self.end == 0 {
-514 // Never received anything
-515 return Poll::Ready(Ok(Vec::new()));
-516 }
-517 let start = self.start;
-518 let mut buffer = vec![0; (self.end - start) as usize];
-519 for (data, offset) in self.read.drain(..) {
-520 let offset = (offset - start) as usize;
-521 buffer[offset..offset + data.len()].copy_from_slice(&data);
-522 }
-523 return Poll::Ready(Ok(buffer));
-524 }
-525 }
-526 }
-527 }
-528}
-529
-530/// Errors from [`RecvStream::read_to_end`]
-531#[derive(Debug, Error, Clone, PartialEq, Eq)]
-532pub enum ReadToEndError {
-533 /// An error occurred during reading
-534 #[error("read error: {0}")]
-535 Read(#[from] ReadError),
-536 /// The stream is larger than the user-supplied limit
-537 #[error("stream too long")]
-538 TooLong,
-539}
-540
-541#[cfg(feature = "futures-io")]
-542impl futures_io::AsyncRead for RecvStream {
-543 fn poll_read(
-544 self: Pin<&mut Self>,
-545 cx: &mut Context,
-546 buf: &mut [u8],
-547 ) -> Poll<io::Result<usize>> {
-548 let mut buf = ReadBuf::new(buf);
-549 ready!(Self::poll_read_buf(self.get_mut(), cx, &mut buf))?;
-550 Poll::Ready(Ok(buf.filled().len()))
-551 }
-552}
-553
-554impl tokio::io::AsyncRead for RecvStream {
-555 fn poll_read(
-556 self: Pin<&mut Self>,
-557 cx: &mut Context<'_>,
-558 buf: &mut ReadBuf<'_>,
-559 ) -> Poll<io::Result<()>> {
-560 ready!(Self::poll_read_buf(self.get_mut(), cx, buf))?;
-561 Poll::Ready(Ok(()))
-562 }
-563}
-564
-565impl Drop for RecvStream {
-566 fn drop(&mut self) {
-567 let mut conn = self.conn.state.lock("RecvStream::drop");
-568
-569 // clean up any previously registered wakers
-570 conn.blocked_readers.remove(&self.stream);
-571
-572 if conn.error.is_some() || (self.is_0rtt && conn.check_0rtt().is_err()) {
-573 return;
-574 }
-575 if !self.all_data_read {
-576 // Ignore ClosedStream errors
-577 let _ = conn.inner.recv_stream(self.stream).stop(0u32.into());
-578 conn.wake();
-579 }
-580 }
-581}
-582
-583/// Errors that arise from reading from a stream.
-584#[derive(Debug, Error, Clone, PartialEq, Eq)]
-585pub enum ReadError {
-586 /// The peer abandoned transmitting data on this stream
-587 ///
-588 /// Carries an application-defined error code.
-589 #[error("stream reset by peer: error {0}")]
-590 Reset(VarInt),
-591 /// The connection was lost
-592 #[error("connection lost")]
-593 ConnectionLost(#[from] ConnectionError),
-594 /// The stream has already been stopped, finished, or reset
-595 #[error("closed stream")]
-596 ClosedStream,
-597 /// Attempted an ordered read following an unordered read
-598 ///
-599 /// Performing an unordered read allows discontinuities to arise in the receive buffer of a
-600 /// stream which cannot be recovered, making further ordered reads impossible.
-601 #[error("ordered read after unordered read")]
-602 IllegalOrderedRead,
-603 /// This was a 0-RTT stream and the server rejected it
-604 ///
-605 /// Can only occur on clients for 0-RTT streams, which can be opened using
-606 /// [`Connecting::into_0rtt()`].
+487impl<T> From<(Option<T>, Option<proto::ReadError>)> for ReadStatus<T> {
+488 fn from(status: (Option<T>, Option<proto::ReadError>)) -> Self {
+489 match status {
+490 (read, None) => Self::Finished(read),
+491 (read, Some(e)) => Self::Failed(read, e),
+492 }
+493 }
+494}
+495
+496/// Future produced by [`RecvStream::read_to_end()`].
+497///
+498/// [`RecvStream::read_to_end()`]: crate::RecvStream::read_to_end
+499struct ReadToEnd<'a> {
+500 stream: &'a mut RecvStream,
+501 read: Vec<(Bytes, u64)>,
+502 start: u64,
+503 end: u64,
+504 size_limit: usize,
+505}
+506
+507impl Future for ReadToEnd<'_> {
+508 type Output = Result<Vec<u8>, ReadToEndError>;
+509 fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
+510 loop {
+511 match ready!(self.stream.poll_read_chunk(cx, usize::MAX, false))? {
+512 Some(chunk) => {
+513 self.start = self.start.min(chunk.offset);
+514 let end = chunk.bytes.len() as u64 + chunk.offset;
+515 if (end - self.start) > self.size_limit as u64 {
+516 return Poll::Ready(Err(ReadToEndError::TooLong));
+517 }
+518 self.end = self.end.max(end);
+519 self.read.push((chunk.bytes, chunk.offset));
+520 }
+521 None => {
+522 if self.end == 0 {
+523 // Never received anything
+524 return Poll::Ready(Ok(Vec::new()));
+525 }
+526 let start = self.start;
+527 let mut buffer = vec![0; (self.end - start) as usize];
+528 for (data, offset) in self.read.drain(..) {
+529 let offset = (offset - start) as usize;
+530 buffer[offset..offset + data.len()].copy_from_slice(&data);
+531 }
+532 return Poll::Ready(Ok(buffer));
+533 }
+534 }
+535 }
+536 }
+537}
+538
+539/// Errors from [`RecvStream::read_to_end`]
+540#[derive(Debug, Error, Clone, PartialEq, Eq)]
+541pub enum ReadToEndError {
+542 /// An error occurred during reading
+543 #[error("read error: {0}")]
+544 Read(#[from] ReadError),
+545 /// The stream is larger than the user-supplied limit
+546 #[error("stream too long")]
+547 TooLong,
+548}
+549
+550#[cfg(feature = "futures-io")]
+551impl futures_io::AsyncRead for RecvStream {
+552 fn poll_read(
+553 self: Pin<&mut Self>,
+554 cx: &mut Context,
+555 buf: &mut [u8],
+556 ) -> Poll<io::Result<usize>> {
+557 let mut buf = ReadBuf::new(buf);
+558 ready!(Self::poll_read_buf(self.get_mut(), cx, &mut buf))?;
+559 Poll::Ready(Ok(buf.filled().len()))
+560 }
+561}
+562
+563impl tokio::io::AsyncRead for RecvStream {
+564 fn poll_read(
+565 self: Pin<&mut Self>,
+566 cx: &mut Context<'_>,
+567 buf: &mut ReadBuf<'_>,
+568 ) -> Poll<io::Result<()>> {
+569 ready!(Self::poll_read_buf(self.get_mut(), cx, buf))?;
+570 Poll::Ready(Ok(()))
+571 }
+572}
+573
+574impl Drop for RecvStream {
+575 fn drop(&mut self) {
+576 let mut conn = self.conn.state.lock("RecvStream::drop");
+577
+578 // clean up any previously registered wakers
+579 conn.blocked_readers.remove(&self.stream);
+580
+581 if conn.error.is_some() || (self.is_0rtt && conn.check_0rtt().is_err()) {
+582 return;
+583 }
+584 if !self.all_data_read {
+585 // Ignore ClosedStream errors
+586 let _ = conn.inner.recv_stream(self.stream).stop(0u32.into());
+587 conn.wake();
+588 }
+589 }
+590}
+591
+592/// Errors that arise from reading from a stream.
+593#[derive(Debug, Error, Clone, PartialEq, Eq)]
+594pub enum ReadError {
+595 /// The peer abandoned transmitting data on this stream
+596 ///
+597 /// Carries an application-defined error code.
+598 #[error("stream reset by peer: error {0}")]
+599 Reset(VarInt),
+600 /// The connection was lost
+601 #[error("connection lost")]
+602 ConnectionLost(#[from] ConnectionError),
+603 /// The stream has already been stopped, finished, or reset
+604 #[error("closed stream")]
+605 ClosedStream,
+606 /// Attempted an ordered read following an unordered read
607 ///
-608 /// [`Connecting::into_0rtt()`]: crate::Connecting::into_0rtt()
-609 #[error("0-RTT rejected")]
-610 ZeroRttRejected,
-611}
-612
-613impl From<ReadableError> for ReadError {
-614 fn from(e: ReadableError) -> Self {
-615 match e {
-616 ReadableError::ClosedStream => Self::ClosedStream,
-617 ReadableError::IllegalOrderedRead => Self::IllegalOrderedRead,
-618 }
-619 }
+608 /// Performing an unordered read allows discontinuities to arise in the receive buffer of a
+609 /// stream which cannot be recovered, making further ordered reads impossible.
+610 #[error("ordered read after unordered read")]
+611 IllegalOrderedRead,
+612 /// This was a 0-RTT stream and the server rejected it
+613 ///
+614 /// Can only occur on clients for 0-RTT streams, which can be opened using
+615 /// [`Connecting::into_0rtt()`].
+616 ///
+617 /// [`Connecting::into_0rtt()`]: crate::Connecting::into_0rtt()
+618 #[error("0-RTT rejected")]
+619 ZeroRttRejected,
620}
621
-622impl From<ResetError> for ReadError {
-623 fn from(e: ResetError) -> Self {
+622impl From<ReadableError> for ReadError {
+623 fn from(e: ReadableError) -> Self {
624 match e {
-625 ResetError::ConnectionLost(e) => Self::ConnectionLost(e),
-626 ResetError::ZeroRttRejected => Self::ZeroRttRejected,
+625 ReadableError::ClosedStream => Self::ClosedStream,
+626 ReadableError::IllegalOrderedRead => Self::IllegalOrderedRead,
627 }
628 }
629}
630
-631impl From<ReadError> for io::Error {
-632 fn from(x: ReadError) -> Self {
-633 use ReadError::*;
-634 let kind = match x {
-635 Reset { .. } | ZeroRttRejected => io::ErrorKind::ConnectionReset,
-636 ConnectionLost(_) | ClosedStream => io::ErrorKind::NotConnected,
-637 IllegalOrderedRead => io::ErrorKind::InvalidInput,
-638 };
-639 Self::new(kind, x)
-640 }
-641}
-642
-643/// Errors that arise while waiting for a stream to be reset
-644#[derive(Debug, Error, Clone, PartialEq, Eq)]
-645pub enum ResetError {
-646 /// The connection was lost
-647 #[error("connection lost")]
-648 ConnectionLost(#[from] ConnectionError),
-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 io::Error {
-660 fn from(x: ResetError) -> Self {
-661 use ResetError::*;
-662 let kind = match x {
-663 ZeroRttRejected => io::ErrorKind::ConnectionReset,
-664 ConnectionLost(_) => io::ErrorKind::NotConnected,
-665 };
-666 Self::new(kind, x)
-667 }
-668}
-669
-670/// Future produced by [`RecvStream::read()`].
-671///
-672/// [`RecvStream::read()`]: crate::RecvStream::read
-673struct Read<'a> {
-674 stream: &'a mut RecvStream,
-675 buf: ReadBuf<'a>,
-676}
-677
-678impl Future for Read<'_> {
-679 type Output = Result<Option<usize>, ReadError>;
-680
-681 fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
-682 let this = self.get_mut();
-683 ready!(this.stream.poll_read_buf(cx, &mut this.buf))?;
-684 match this.buf.filled().len() {
-685 0 if this.buf.capacity() != 0 => Poll::Ready(Ok(None)),
-686 n => Poll::Ready(Ok(Some(n))),
-687 }
-688 }
-689}
-690
-691/// Future produced by [`RecvStream::read_exact()`].
-692///
-693/// [`RecvStream::read_exact()`]: crate::RecvStream::read_exact
-694struct ReadExact<'a> {
-695 stream: &'a mut RecvStream,
-696 buf: ReadBuf<'a>,
-697}
-698
-699impl Future for ReadExact<'_> {
-700 type Output = Result<(), ReadExactError>;
-701 fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
-702 let this = self.get_mut();
-703 let mut remaining = this.buf.remaining();
-704 while remaining > 0 {
-705 ready!(this.stream.poll_read_buf(cx, &mut this.buf))?;
-706 let new = this.buf.remaining();
-707 if new == remaining {
-708 return Poll::Ready(Err(ReadExactError::FinishedEarly(this.buf.filled().len())));
-709 }
-710 remaining = new;
-711 }
-712 Poll::Ready(Ok(()))
-713 }
-714}
-715
-716/// Errors that arise from reading from a stream.
-717#[derive(Debug, Error, Clone, PartialEq, Eq)]
-718pub enum ReadExactError {
-719 /// The stream finished before all bytes were read
-720 #[error("stream finished early ({0} bytes read)")]
-721 FinishedEarly(usize),
-722 /// A read error occurred
-723 #[error(transparent)]
-724 ReadError(#[from] ReadError),
-725}
-726
-727/// Future produced by [`RecvStream::read_chunk()`].
-728///
-729/// [`RecvStream::read_chunk()`]: crate::RecvStream::read_chunk
-730struct ReadChunk<'a> {
-731 stream: &'a mut RecvStream,
-732 max_length: usize,
-733 ordered: bool,
+631impl From<ResetError> for ReadError {
+632 fn from(e: ResetError) -> Self {
+633 match e {
+634 ResetError::ConnectionLost(e) => Self::ConnectionLost(e),
+635 ResetError::ZeroRttRejected => Self::ZeroRttRejected,
+636 }
+637 }
+638}
+639
+640impl From<ReadError> for io::Error {
+641 fn from(x: ReadError) -> Self {
+642 use ReadError::*;
+643 let kind = match x {
+644 Reset { .. } | ZeroRttRejected => io::ErrorKind::ConnectionReset,
+645 ConnectionLost(_) | ClosedStream => io::ErrorKind::NotConnected,
+646 IllegalOrderedRead => io::ErrorKind::InvalidInput,
+647 };
+648 Self::new(kind, x)
+649 }
+650}
+651
+652/// Errors that arise while waiting for a stream to be reset
+653#[derive(Debug, Error, Clone, PartialEq, Eq)]
+654pub enum ResetError {
+655 /// The connection was lost
+656 #[error("connection lost")]
+657 ConnectionLost(#[from] ConnectionError),
+658 /// This was a 0-RTT stream and the server rejected it
+659 ///
+660 /// Can only occur on clients for 0-RTT streams, which can be opened using
+661 /// [`Connecting::into_0rtt()`].
+662 ///
+663 /// [`Connecting::into_0rtt()`]: crate::Connecting::into_0rtt()
+664 #[error("0-RTT rejected")]
+665 ZeroRttRejected,
+666}
+667
+668impl From<ResetError> for io::Error {
+669 fn from(x: ResetError) -> Self {
+670 use ResetError::*;
+671 let kind = match x {
+672 ZeroRttRejected => io::ErrorKind::ConnectionReset,
+673 ConnectionLost(_) => io::ErrorKind::NotConnected,
+674 };
+675 Self::new(kind, x)
+676 }
+677}
+678
+679/// Future produced by [`RecvStream::read()`].
+680///
+681/// [`RecvStream::read()`]: crate::RecvStream::read
+682struct Read<'a> {
+683 stream: &'a mut RecvStream,
+684 buf: ReadBuf<'a>,
+685}
+686
+687impl Future for Read<'_> {
+688 type Output = Result<Option<usize>, ReadError>;
+689
+690 fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
+691 let this = self.get_mut();
+692 ready!(this.stream.poll_read_buf(cx, &mut this.buf))?;
+693 match this.buf.filled().len() {
+694 0 if this.buf.capacity() != 0 => Poll::Ready(Ok(None)),
+695 n => Poll::Ready(Ok(Some(n))),
+696 }
+697 }
+698}
+699
+700/// Future produced by [`RecvStream::read_exact()`].
+701///
+702/// [`RecvStream::read_exact()`]: crate::RecvStream::read_exact
+703struct ReadExact<'a> {
+704 stream: &'a mut RecvStream,
+705 buf: ReadBuf<'a>,
+706}
+707
+708impl Future for ReadExact<'_> {
+709 type Output = Result<(), ReadExactError>;
+710 fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
+711 let this = self.get_mut();
+712 let mut remaining = this.buf.remaining();
+713 while remaining > 0 {
+714 ready!(this.stream.poll_read_buf(cx, &mut this.buf))?;
+715 let new = this.buf.remaining();
+716 if new == remaining {
+717 return Poll::Ready(Err(ReadExactError::FinishedEarly(this.buf.filled().len())));
+718 }
+719 remaining = new;
+720 }
+721 Poll::Ready(Ok(()))
+722 }
+723}
+724
+725/// Errors that arise from reading from a stream.
+726#[derive(Debug, Error, Clone, PartialEq, Eq)]
+727pub enum ReadExactError {
+728 /// The stream finished before all bytes were read
+729 #[error("stream finished early ({0} bytes read)")]
+730 FinishedEarly(usize),
+731 /// A read error occurred
+732 #[error(transparent)]
+733 ReadError(#[from] ReadError),
734}
735
-736impl Future for ReadChunk<'_> {
-737 type Output = Result<Option<Chunk>, ReadError>;
-738 fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
-739 let (max_length, ordered) = (self.max_length, self.ordered);
-740 self.stream.poll_read_chunk(cx, max_length, ordered)
-741 }
-742}
-743
-744/// Future produced by [`RecvStream::read_chunks()`].
-745///
-746/// [`RecvStream::read_chunks()`]: crate::RecvStream::read_chunks
-747struct ReadChunks<'a> {
-748 stream: &'a mut RecvStream,
-749 bufs: &'a mut [Bytes],
-750}
-751
-752impl Future for ReadChunks<'_> {
-753 type Output = Result<Option<usize>, ReadError>;
-754 fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
-755 let this = self.get_mut();
-756 this.stream.poll_read_chunks(cx, this.bufs)
-757 }
-758}
\ No newline at end of file
+736/// Future produced by [`RecvStream::read_chunk()`].
+737///
+738/// [`RecvStream::read_chunk()`]: crate::RecvStream::read_chunk
+739struct ReadChunk<'a> {
+740 stream: &'a mut RecvStream,
+741 max_length: usize,
+742 ordered: bool,
+743}
+744
+745impl Future for ReadChunk<'_> {
+746 type Output = Result<Option<Chunk>, ReadError>;
+747 fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
+748 let (max_length, ordered) = (self.max_length, self.ordered);
+749 self.stream.poll_read_chunk(cx, max_length, ordered)
+750 }
+751}
+752
+753/// Future produced by [`RecvStream::read_chunks()`].
+754///
+755/// [`RecvStream::read_chunks()`]: crate::RecvStream::read_chunks
+756struct ReadChunks<'a> {
+757 stream: &'a mut RecvStream,
+758 bufs: &'a mut [Bytes],
+759}
+760
+761impl Future for ReadChunks<'_> {
+762 type Output = Result<Option<usize>, ReadError>;
+763 fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
+764 let this = self.get_mut();
+765 this.stream.poll_read_chunks(cx, this.bufs)
+766 }
+767}
\ No newline at end of file
diff --git a/pr/257/docs/src/iroh_quinn_proto/connection/mod.rs.html b/pr/257/docs/src/iroh_quinn_proto/connection/mod.rs.html
index 0a99b6ffa..8eadae936 100644
--- a/pr/257/docs/src/iroh_quinn_proto/connection/mod.rs.html
+++ b/pr/257/docs/src/iroh_quinn_proto/connection/mod.rs.html
@@ -6329,358 +6329,365 @@
6329 }
6330 }
6331
-6332 self.iroh_hp
-6333 .client_side_mut()
-6334 .expect("connection side validated")
-6335 .set_round_path_ids(path_ids);
-6336
-6337 Ok(probed_addresses)
-6338 }
-6339}
-6340
-6341impl fmt::Debug for Connection {
-6342 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-6343 f.debug_struct("Connection")
-6344 .field("handshake_cid", &self.handshake_cid)
-6345 .finish()
-6346 }
-6347}
-6348
-6349#[derive(Debug, Copy, Clone, PartialEq, Eq)]
-6350enum PathBlocked {
-6351 No,
-6352 AntiAmplification,
-6353 Congestion,
-6354 Pacing,
-6355}
-6356
-6357/// Fields of `Connection` specific to it being client-side or server-side
-6358enum ConnectionSide {
-6359 Client {
-6360 /// Sent in every outgoing Initial packet. Always empty after Initial keys are discarded
-6361 token: Bytes,
-6362 token_store: Arc<dyn TokenStore>,
-6363 server_name: String,
-6364 },
-6365 Server {
-6366 server_config: Arc<ServerConfig>,
-6367 },
-6368}
-6369
-6370impl ConnectionSide {
-6371 fn remote_may_migrate(&self, state: &State) -> bool {
-6372 match self {
-6373 Self::Server { server_config } => server_config.migration,
-6374 Self::Client { .. } => {
-6375 if let Some(hs) = state.as_handshake() {
-6376 hs.allow_server_migration
-6377 } else {
-6378 false
-6379 }
-6380 }
-6381 }
-6382 }
-6383
-6384 fn is_client(&self) -> bool {
-6385 self.side().is_client()
-6386 }
-6387
-6388 fn is_server(&self) -> bool {
-6389 self.side().is_server()
-6390 }
-6391
-6392 fn side(&self) -> Side {
-6393 match *self {
-6394 Self::Client { .. } => Side::Client,
-6395 Self::Server { .. } => Side::Server,
-6396 }
+6332 if let Some(err) = err {
+6333 // We failed to probe any addresses, bail out
+6334 if probed_addresses.is_empty() {
+6335 return Err(iroh_hp::Error::Multipath(err));
+6336 }
+6337 }
+6338
+6339 self.iroh_hp
+6340 .client_side_mut()
+6341 .expect("connection side validated")
+6342 .set_round_path_ids(path_ids);
+6343
+6344 Ok(probed_addresses)
+6345 }
+6346}
+6347
+6348impl fmt::Debug for Connection {
+6349 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+6350 f.debug_struct("Connection")
+6351 .field("handshake_cid", &self.handshake_cid)
+6352 .finish()
+6353 }
+6354}
+6355
+6356#[derive(Debug, Copy, Clone, PartialEq, Eq)]
+6357enum PathBlocked {
+6358 No,
+6359 AntiAmplification,
+6360 Congestion,
+6361 Pacing,
+6362}
+6363
+6364/// Fields of `Connection` specific to it being client-side or server-side
+6365enum ConnectionSide {
+6366 Client {
+6367 /// Sent in every outgoing Initial packet. Always empty after Initial keys are discarded
+6368 token: Bytes,
+6369 token_store: Arc<dyn TokenStore>,
+6370 server_name: String,
+6371 },
+6372 Server {
+6373 server_config: Arc<ServerConfig>,
+6374 },
+6375}
+6376
+6377impl ConnectionSide {
+6378 fn remote_may_migrate(&self, state: &State) -> bool {
+6379 match self {
+6380 Self::Server { server_config } => server_config.migration,
+6381 Self::Client { .. } => {
+6382 if let Some(hs) = state.as_handshake() {
+6383 hs.allow_server_migration
+6384 } else {
+6385 false
+6386 }
+6387 }
+6388 }
+6389 }
+6390
+6391 fn is_client(&self) -> bool {
+6392 self.side().is_client()
+6393 }
+6394
+6395 fn is_server(&self) -> bool {
+6396 self.side().is_server()
6397 }
-6398}
-6399
-6400impl From<SideArgs> for ConnectionSide {
-6401 fn from(side: SideArgs) -> Self {
-6402 match side {
-6403 SideArgs::Client {
-6404 token_store,
-6405 server_name,
-6406 } => Self::Client {
-6407 token: token_store.take(&server_name).unwrap_or_default(),
-6408 token_store,
-6409 server_name,
-6410 },
-6411 SideArgs::Server {
-6412 server_config,
-6413 pref_addr_cid: _,
-6414 path_validated: _,
-6415 } => Self::Server { server_config },
-6416 }
-6417 }
-6418}
-6419
-6420/// Parameters to `Connection::new` specific to it being client-side or server-side
-6421pub(crate) enum SideArgs {
-6422 Client {
-6423 token_store: Arc<dyn TokenStore>,
-6424 server_name: String,
-6425 },
-6426 Server {
-6427 server_config: Arc<ServerConfig>,
-6428 pref_addr_cid: Option<ConnectionId>,
-6429 path_validated: bool,
-6430 },
-6431}
-6432
-6433impl SideArgs {
-6434 pub(crate) fn pref_addr_cid(&self) -> Option<ConnectionId> {
-6435 match *self {
-6436 Self::Client { .. } => None,
-6437 Self::Server { pref_addr_cid, .. } => pref_addr_cid,
-6438 }
-6439 }
-6440
-6441 pub(crate) fn path_validated(&self) -> bool {
+6398
+6399 fn side(&self) -> Side {
+6400 match *self {
+6401 Self::Client { .. } => Side::Client,
+6402 Self::Server { .. } => Side::Server,
+6403 }
+6404 }
+6405}
+6406
+6407impl From<SideArgs> for ConnectionSide {
+6408 fn from(side: SideArgs) -> Self {
+6409 match side {
+6410 SideArgs::Client {
+6411 token_store,
+6412 server_name,
+6413 } => Self::Client {
+6414 token: token_store.take(&server_name).unwrap_or_default(),
+6415 token_store,
+6416 server_name,
+6417 },
+6418 SideArgs::Server {
+6419 server_config,
+6420 pref_addr_cid: _,
+6421 path_validated: _,
+6422 } => Self::Server { server_config },
+6423 }
+6424 }
+6425}
+6426
+6427/// Parameters to `Connection::new` specific to it being client-side or server-side
+6428pub(crate) enum SideArgs {
+6429 Client {
+6430 token_store: Arc<dyn TokenStore>,
+6431 server_name: String,
+6432 },
+6433 Server {
+6434 server_config: Arc<ServerConfig>,
+6435 pref_addr_cid: Option<ConnectionId>,
+6436 path_validated: bool,
+6437 },
+6438}
+6439
+6440impl SideArgs {
+6441 pub(crate) fn pref_addr_cid(&self) -> Option<ConnectionId> {
6442 match *self {
-6443 Self::Client { .. } => true,
-6444 Self::Server { path_validated, .. } => path_validated,
+6443 Self::Client { .. } => None,
+6444 Self::Server { pref_addr_cid, .. } => pref_addr_cid,
6445 }
6446 }
6447
-6448 pub(crate) fn side(&self) -> Side {
+6448 pub(crate) fn path_validated(&self) -> bool {
6449 match *self {
-6450 Self::Client { .. } => Side::Client,
-6451 Self::Server { .. } => Side::Server,
+6450 Self::Client { .. } => true,
+6451 Self::Server { path_validated, .. } => path_validated,
6452 }
6453 }
-6454}
-6455
-6456/// Reasons why a connection might be lost
-6457#[derive(Debug, Error, Clone, PartialEq, Eq)]
-6458pub enum ConnectionError {
-6459 /// The peer doesn't implement any supported version
-6460 #[error("peer doesn't implement any supported version")]
-6461 VersionMismatch,
-6462 /// The peer violated the QUIC specification as understood by this implementation
-6463 #[error(transparent)]
-6464 TransportError(#[from] TransportError),
-6465 /// The peer's QUIC stack aborted the connection automatically
-6466 #[error("aborted by peer: {0}")]
-6467 ConnectionClosed(frame::ConnectionClose),
-6468 /// The peer closed the connection
-6469 #[error("closed by peer: {0}")]
-6470 ApplicationClosed(frame::ApplicationClose),
-6471 /// The peer is unable to continue processing this connection, usually due to having restarted
-6472 #[error("reset by peer")]
-6473 Reset,
-6474 /// Communication with the peer has lapsed for longer than the negotiated idle timeout
-6475 ///
-6476 /// If neither side is sending keep-alives, a connection will time out after a long enough idle
-6477 /// period even if the peer is still reachable. See also [`TransportConfig::max_idle_timeout()`]
-6478 /// and [`TransportConfig::keep_alive_interval()`].
-6479 #[error("timed out")]
-6480 TimedOut,
-6481 /// The local application closed the connection
-6482 #[error("closed")]
-6483 LocallyClosed,
-6484 /// The connection could not be created because not enough of the CID space is available
-6485 ///
-6486 /// Try using longer connection IDs.
-6487 #[error("CIDs exhausted")]
-6488 CidsExhausted,
-6489}
-6490
-6491impl From<Close> for ConnectionError {
-6492 fn from(x: Close) -> Self {
-6493 match x {
-6494 Close::Connection(reason) => Self::ConnectionClosed(reason),
-6495 Close::Application(reason) => Self::ApplicationClosed(reason),
-6496 }
-6497 }
-6498}
-6499
-6500// For compatibility with API consumers
-6501impl From<ConnectionError> for io::Error {
-6502 fn from(x: ConnectionError) -> Self {
-6503 use ConnectionError::*;
-6504 let kind = match x {
-6505 TimedOut => io::ErrorKind::TimedOut,
-6506 Reset => io::ErrorKind::ConnectionReset,
-6507 ApplicationClosed(_) | ConnectionClosed(_) => io::ErrorKind::ConnectionAborted,
-6508 TransportError(_) | VersionMismatch | LocallyClosed | CidsExhausted => {
-6509 io::ErrorKind::Other
-6510 }
-6511 };
-6512 Self::new(kind, x)
-6513 }
-6514}
-6515
-6516/// Errors that might trigger a path being closed
-6517// TODO(@divma): maybe needs to be reworked based on what we want to do with the public API
-6518#[derive(Debug, Error, PartialEq, Eq, Clone, Copy)]
-6519pub enum PathError {
-6520 /// The extension was not negotiated with the peer
-6521 #[error("multipath extension not negotiated")]
-6522 MultipathNotNegotiated,
-6523 /// Paths can only be opened client-side
-6524 #[error("the server side may not open a path")]
-6525 ServerSideNotAllowed,
-6526 /// Current limits do not allow us to open more paths
-6527 #[error("maximum number of concurrent paths reached")]
-6528 MaxPathIdReached,
-6529 /// No remote CIDs available to open a new path
-6530 #[error("remoted CIDs exhausted")]
-6531 RemoteCidsExhausted,
-6532 /// Path could not be validated and will be abandoned
-6533 #[error("path validation failed")]
-6534 ValidationFailed,
-6535 /// The remote address for the path is not supported by the endpoint
-6536 #[error("invalid remote address")]
-6537 InvalidRemoteAddress(SocketAddr),
-6538}
-6539
-6540/// Errors triggered when abandoning a path
-6541#[derive(Debug, Error, Clone, Eq, PartialEq)]
-6542pub enum ClosePathError {
-6543 /// The path is already closed or was never opened
-6544 #[error("closed path")]
-6545 ClosedPath,
-6546 /// This is the last path, which can not be abandoned
-6547 #[error("last open path")]
-6548 LastOpenPath,
-6549}
-6550
-6551#[derive(Debug, Error, Clone, Copy)]
-6552#[error("Multipath extension not negotiated")]
-6553pub struct MultipathNotNegotiated {
-6554 _private: (),
-6555}
-6556
-6557/// Events of interest to the application
-6558#[derive(Debug)]
-6559pub enum Event {
-6560 /// The connection's handshake data is ready
-6561 HandshakeDataReady,
-6562 /// The connection was successfully established
-6563 Connected,
-6564 /// The TLS handshake was confirmed
-6565 HandshakeConfirmed,
-6566 /// The connection was lost
-6567 ///
-6568 /// Emitted if the peer closes the connection or an error is encountered.
-6569 ConnectionLost {
-6570 /// Reason that the connection was closed
-6571 reason: ConnectionError,
-6572 },
-6573 /// Stream events
-6574 Stream(StreamEvent),
-6575 /// One or more application datagrams have been received
-6576 DatagramReceived,
-6577 /// One or more application datagrams have been sent after blocking
-6578 DatagramsUnblocked,
-6579 /// (Multi)Path events
-6580 Path(PathEvent),
-6581 /// Iroh's nat traversal events
-6582 NatTraversal(iroh_hp::Event),
-6583}
-6584
-6585impl From<PathEvent> for Event {
-6586 fn from(source: PathEvent) -> Self {
-6587 Self::Path(source)
-6588 }
-6589}
-6590
-6591fn get_max_ack_delay(params: &TransportParameters) -> Duration {
-6592 Duration::from_micros(params.max_ack_delay.0 * 1000)
-6593}
-6594
-6595// Prevents overflow and improves behavior in extreme circumstances
-6596const MAX_BACKOFF_EXPONENT: u32 = 16;
+6454
+6455 pub(crate) fn side(&self) -> Side {
+6456 match *self {
+6457 Self::Client { .. } => Side::Client,
+6458 Self::Server { .. } => Side::Server,
+6459 }
+6460 }
+6461}
+6462
+6463/// Reasons why a connection might be lost
+6464#[derive(Debug, Error, Clone, PartialEq, Eq)]
+6465pub enum ConnectionError {
+6466 /// The peer doesn't implement any supported version
+6467 #[error("peer doesn't implement any supported version")]
+6468 VersionMismatch,
+6469 /// The peer violated the QUIC specification as understood by this implementation
+6470 #[error(transparent)]
+6471 TransportError(#[from] TransportError),
+6472 /// The peer's QUIC stack aborted the connection automatically
+6473 #[error("aborted by peer: {0}")]
+6474 ConnectionClosed(frame::ConnectionClose),
+6475 /// The peer closed the connection
+6476 #[error("closed by peer: {0}")]
+6477 ApplicationClosed(frame::ApplicationClose),
+6478 /// The peer is unable to continue processing this connection, usually due to having restarted
+6479 #[error("reset by peer")]
+6480 Reset,
+6481 /// Communication with the peer has lapsed for longer than the negotiated idle timeout
+6482 ///
+6483 /// If neither side is sending keep-alives, a connection will time out after a long enough idle
+6484 /// period even if the peer is still reachable. See also [`TransportConfig::max_idle_timeout()`]
+6485 /// and [`TransportConfig::keep_alive_interval()`].
+6486 #[error("timed out")]
+6487 TimedOut,
+6488 /// The local application closed the connection
+6489 #[error("closed")]
+6490 LocallyClosed,
+6491 /// The connection could not be created because not enough of the CID space is available
+6492 ///
+6493 /// Try using longer connection IDs.
+6494 #[error("CIDs exhausted")]
+6495 CidsExhausted,
+6496}
+6497
+6498impl From<Close> for ConnectionError {
+6499 fn from(x: Close) -> Self {
+6500 match x {
+6501 Close::Connection(reason) => Self::ConnectionClosed(reason),
+6502 Close::Application(reason) => Self::ApplicationClosed(reason),
+6503 }
+6504 }
+6505}
+6506
+6507// For compatibility with API consumers
+6508impl From<ConnectionError> for io::Error {
+6509 fn from(x: ConnectionError) -> Self {
+6510 use ConnectionError::*;
+6511 let kind = match x {
+6512 TimedOut => io::ErrorKind::TimedOut,
+6513 Reset => io::ErrorKind::ConnectionReset,
+6514 ApplicationClosed(_) | ConnectionClosed(_) => io::ErrorKind::ConnectionAborted,
+6515 TransportError(_) | VersionMismatch | LocallyClosed | CidsExhausted => {
+6516 io::ErrorKind::Other
+6517 }
+6518 };
+6519 Self::new(kind, x)
+6520 }
+6521}
+6522
+6523/// Errors that might trigger a path being closed
+6524// TODO(@divma): maybe needs to be reworked based on what we want to do with the public API
+6525#[derive(Debug, Error, PartialEq, Eq, Clone, Copy)]
+6526pub enum PathError {
+6527 /// The extension was not negotiated with the peer
+6528 #[error("multipath extension not negotiated")]
+6529 MultipathNotNegotiated,
+6530 /// Paths can only be opened client-side
+6531 #[error("the server side may not open a path")]
+6532 ServerSideNotAllowed,
+6533 /// Current limits do not allow us to open more paths
+6534 #[error("maximum number of concurrent paths reached")]
+6535 MaxPathIdReached,
+6536 /// No remote CIDs available to open a new path
+6537 #[error("remoted CIDs exhausted")]
+6538 RemoteCidsExhausted,
+6539 /// Path could not be validated and will be abandoned
+6540 #[error("path validation failed")]
+6541 ValidationFailed,
+6542 /// The remote address for the path is not supported by the endpoint
+6543 #[error("invalid remote address")]
+6544 InvalidRemoteAddress(SocketAddr),
+6545}
+6546
+6547/// Errors triggered when abandoning a path
+6548#[derive(Debug, Error, Clone, Eq, PartialEq)]
+6549pub enum ClosePathError {
+6550 /// The path is already closed or was never opened
+6551 #[error("closed path")]
+6552 ClosedPath,
+6553 /// This is the last path, which can not be abandoned
+6554 #[error("last open path")]
+6555 LastOpenPath,
+6556}
+6557
+6558#[derive(Debug, Error, Clone, Copy)]
+6559#[error("Multipath extension not negotiated")]
+6560pub struct MultipathNotNegotiated {
+6561 _private: (),
+6562}
+6563
+6564/// Events of interest to the application
+6565#[derive(Debug)]
+6566pub enum Event {
+6567 /// The connection's handshake data is ready
+6568 HandshakeDataReady,
+6569 /// The connection was successfully established
+6570 Connected,
+6571 /// The TLS handshake was confirmed
+6572 HandshakeConfirmed,
+6573 /// The connection was lost
+6574 ///
+6575 /// Emitted if the peer closes the connection or an error is encountered.
+6576 ConnectionLost {
+6577 /// Reason that the connection was closed
+6578 reason: ConnectionError,
+6579 },
+6580 /// Stream events
+6581 Stream(StreamEvent),
+6582 /// One or more application datagrams have been received
+6583 DatagramReceived,
+6584 /// One or more application datagrams have been sent after blocking
+6585 DatagramsUnblocked,
+6586 /// (Multi)Path events
+6587 Path(PathEvent),
+6588 /// Iroh's nat traversal events
+6589 NatTraversal(iroh_hp::Event),
+6590}
+6591
+6592impl From<PathEvent> for Event {
+6593 fn from(source: PathEvent) -> Self {
+6594 Self::Path(source)
+6595 }
+6596}
6597
-6598/// Minimal remaining size to allow packet coalescing, excluding cryptographic tag
-6599///
-6600/// This must be at least as large as the header for a well-formed empty packet to be coalesced,
-6601/// plus some space for frames. We only care about handshake headers because short header packets
-6602/// necessarily have smaller headers, and initial packets are only ever the first packet in a
-6603/// datagram (because we coalesce in ascending packet space order and the only reason to split a
-6604/// packet is when packet space changes).
-6605const MIN_PACKET_SPACE: usize = MAX_HANDSHAKE_OR_0RTT_HEADER_SIZE + 32;
-6606
-6607/// Largest amount of space that could be occupied by a Handshake or 0-RTT packet's header
-6608///
-6609/// Excludes packet-type-specific fields such as packet number or Initial token
-6610// https://www.rfc-editor.org/rfc/rfc9000.html#name-0-rtt: flags + version + dcid len + dcid +
-6611// scid len + scid + length + pn
-6612const MAX_HANDSHAKE_OR_0RTT_HEADER_SIZE: usize =
-6613 1 + 4 + 1 + MAX_CID_SIZE + 1 + MAX_CID_SIZE + VarInt::from_u32(u16::MAX as u32).size() + 4;
-6614
-6615/// Perform key updates this many packets before the AEAD confidentiality limit.
-6616///
-6617/// Chosen arbitrarily, intended to be large enough to prevent spurious connection loss.
-6618const KEY_UPDATE_MARGIN: u64 = 10_000;
-6619
-6620#[derive(Default)]
-6621struct SentFrames {
-6622 retransmits: ThinRetransmits,
-6623 /// The packet number of the largest acknowledged packet for each path
-6624 largest_acked: FxHashMap<PathId, u64>,
-6625 stream_frames: StreamMetaVec,
-6626 /// Whether the packet contains non-retransmittable frames (like datagrams)
-6627 non_retransmits: bool,
-6628 /// If the datagram containing these frames should be padded to the min MTU
-6629 requires_padding: bool,
-6630}
-6631
-6632impl SentFrames {
-6633 /// Returns whether the packet contains only ACKs
-6634 fn is_ack_only(&self, streams: &StreamsState) -> bool {
-6635 !self.largest_acked.is_empty()
-6636 && !self.non_retransmits
-6637 && self.stream_frames.is_empty()
-6638 && self.retransmits.is_empty(streams)
-6639 }
-6640}
-6641
-6642/// Compute the negotiated idle timeout based on local and remote max_idle_timeout transport parameters.
-6643///
-6644/// According to the definition of max_idle_timeout, a value of `0` means the timeout is disabled; see <https://www.rfc-editor.org/rfc/rfc9000#section-18.2-4.4.1.>
-6645///
-6646/// According to the negotiation procedure, either the minimum of the timeouts or one specified is used as the negotiated value; see <https://www.rfc-editor.org/rfc/rfc9000#section-10.1-2.>
-6647///
-6648/// Returns the negotiated idle timeout as a `Duration`, or `None` when both endpoints have opted out of idle timeout.
-6649fn negotiate_max_idle_timeout(x: Option<VarInt>, y: Option<VarInt>) -> Option<Duration> {
-6650 match (x, y) {
-6651 (Some(VarInt(0)) | None, Some(VarInt(0)) | None) => None,
-6652 (Some(VarInt(0)) | None, Some(y)) => Some(Duration::from_millis(y.0)),
-6653 (Some(x), Some(VarInt(0)) | None) => Some(Duration::from_millis(x.0)),
-6654 (Some(x), Some(y)) => Some(Duration::from_millis(cmp::min(x, y).0)),
-6655 }
-6656}
-6657
-6658#[cfg(test)]
-6659mod tests {
-6660 use super::*;
-6661
-6662 #[test]
-6663 fn negotiate_max_idle_timeout_commutative() {
-6664 let test_params = [
-6665 (None, None, None),
-6666 (None, Some(VarInt(0)), None),
-6667 (None, Some(VarInt(2)), Some(Duration::from_millis(2))),
-6668 (Some(VarInt(0)), Some(VarInt(0)), None),
-6669 (
-6670 Some(VarInt(2)),
-6671 Some(VarInt(0)),
-6672 Some(Duration::from_millis(2)),
-6673 ),
-6674 (
-6675 Some(VarInt(1)),
-6676 Some(VarInt(4)),
-6677 Some(Duration::from_millis(1)),
-6678 ),
-6679 ];
-6680
-6681 for (left, right, result) in test_params {
-6682 assert_eq!(negotiate_max_idle_timeout(left, right), result);
-6683 assert_eq!(negotiate_max_idle_timeout(right, left), result);
-6684 }
-6685 }
-6686}
\ No newline at end of file
+6598fn get_max_ack_delay(params: &TransportParameters) -> Duration {
+6599 Duration::from_micros(params.max_ack_delay.0 * 1000)
+6600}
+6601
+6602// Prevents overflow and improves behavior in extreme circumstances
+6603const MAX_BACKOFF_EXPONENT: u32 = 16;
+6604
+6605/// Minimal remaining size to allow packet coalescing, excluding cryptographic tag
+6606///
+6607/// This must be at least as large as the header for a well-formed empty packet to be coalesced,
+6608/// plus some space for frames. We only care about handshake headers because short header packets
+6609/// necessarily have smaller headers, and initial packets are only ever the first packet in a
+6610/// datagram (because we coalesce in ascending packet space order and the only reason to split a
+6611/// packet is when packet space changes).
+6612const MIN_PACKET_SPACE: usize = MAX_HANDSHAKE_OR_0RTT_HEADER_SIZE + 32;
+6613
+6614/// Largest amount of space that could be occupied by a Handshake or 0-RTT packet's header
+6615///
+6616/// Excludes packet-type-specific fields such as packet number or Initial token
+6617// https://www.rfc-editor.org/rfc/rfc9000.html#name-0-rtt: flags + version + dcid len + dcid +
+6618// scid len + scid + length + pn
+6619const MAX_HANDSHAKE_OR_0RTT_HEADER_SIZE: usize =
+6620 1 + 4 + 1 + MAX_CID_SIZE + 1 + MAX_CID_SIZE + VarInt::from_u32(u16::MAX as u32).size() + 4;
+6621
+6622/// Perform key updates this many packets before the AEAD confidentiality limit.
+6623///
+6624/// Chosen arbitrarily, intended to be large enough to prevent spurious connection loss.
+6625const KEY_UPDATE_MARGIN: u64 = 10_000;
+6626
+6627#[derive(Default)]
+6628struct SentFrames {
+6629 retransmits: ThinRetransmits,
+6630 /// The packet number of the largest acknowledged packet for each path
+6631 largest_acked: FxHashMap<PathId, u64>,
+6632 stream_frames: StreamMetaVec,
+6633 /// Whether the packet contains non-retransmittable frames (like datagrams)
+6634 non_retransmits: bool,
+6635 /// If the datagram containing these frames should be padded to the min MTU
+6636 requires_padding: bool,
+6637}
+6638
+6639impl SentFrames {
+6640 /// Returns whether the packet contains only ACKs
+6641 fn is_ack_only(&self, streams: &StreamsState) -> bool {
+6642 !self.largest_acked.is_empty()
+6643 && !self.non_retransmits
+6644 && self.stream_frames.is_empty()
+6645 && self.retransmits.is_empty(streams)
+6646 }
+6647}
+6648
+6649/// Compute the negotiated idle timeout based on local and remote max_idle_timeout transport parameters.
+6650///
+6651/// According to the definition of max_idle_timeout, a value of `0` means the timeout is disabled; see <https://www.rfc-editor.org/rfc/rfc9000#section-18.2-4.4.1.>
+6652///
+6653/// According to the negotiation procedure, either the minimum of the timeouts or one specified is used as the negotiated value; see <https://www.rfc-editor.org/rfc/rfc9000#section-10.1-2.>
+6654///
+6655/// Returns the negotiated idle timeout as a `Duration`, or `None` when both endpoints have opted out of idle timeout.
+6656fn negotiate_max_idle_timeout(x: Option<VarInt>, y: Option<VarInt>) -> Option<Duration> {
+6657 match (x, y) {
+6658 (Some(VarInt(0)) | None, Some(VarInt(0)) | None) => None,
+6659 (Some(VarInt(0)) | None, Some(y)) => Some(Duration::from_millis(y.0)),
+6660 (Some(x), Some(VarInt(0)) | None) => Some(Duration::from_millis(x.0)),
+6661 (Some(x), Some(y)) => Some(Duration::from_millis(cmp::min(x, y).0)),
+6662 }
+6663}
+6664
+6665#[cfg(test)]
+6666mod tests {
+6667 use super::*;
+6668
+6669 #[test]
+6670 fn negotiate_max_idle_timeout_commutative() {
+6671 let test_params = [
+6672 (None, None, None),
+6673 (None, Some(VarInt(0)), None),
+6674 (None, Some(VarInt(2)), Some(Duration::from_millis(2))),
+6675 (Some(VarInt(0)), Some(VarInt(0)), None),
+6676 (
+6677 Some(VarInt(2)),
+6678 Some(VarInt(0)),
+6679 Some(Duration::from_millis(2)),
+6680 ),
+6681 (
+6682 Some(VarInt(1)),
+6683 Some(VarInt(4)),
+6684 Some(Duration::from_millis(1)),
+6685 ),
+6686 ];
+6687
+6688 for (left, right, result) in test_params {
+6689 assert_eq!(negotiate_max_idle_timeout(left, right), result);
+6690 assert_eq!(negotiate_max_idle_timeout(right, left), result);
+6691 }
+6692 }
+6693}
\ No newline at end of file