diff --git a/pr/255/docs/iroh_quinn/all.html b/pr/255/docs/iroh_quinn/all.html index f28f87dc5..9efe65aca 100644 --- a/pr/255/docs/iroh_quinn/all.html +++ b/pr/255/docs/iroh_quinn/all.html @@ -1 +1 @@ -List of all items in this crate

All

List of all items

Structs

Enums

Traits

Functions

\ No newline at end of file +List of all items in this crate

All

List of all items

Structs

Enums

Traits

Functions

\ No newline at end of file diff --git a/pr/255/docs/iroh_quinn/congestion/index.html b/pr/255/docs/iroh_quinn/congestion/index.html index 38ff69dad..2216af227 100644 --- a/pr/255/docs/iroh_quinn/congestion/index.html +++ b/pr/255/docs/iroh_quinn/congestion/index.html @@ -1,2 +1,2 @@ -iroh_quinn::congestion - Rust

Module congestion

Module congestion 

Source
Expand description

Logic for controlling the rate at which data is sent

+iroh_quinn::congestion - Rust

Module congestion

Module congestion 

Source
Expand description

Logic for controlling the rate at which data is sent

Structs§

Bbr
Experimental! Use at your own risk.
BbrConfig
Configuration for the Bbr congestion controller
ControllerMetrics
Common congestion controller metrics
Cubic
The RFC8312 congestion controller, as widely used for TCP
CubicConfig
Configuration for the Cubic congestion controller
NewReno
A simple, standard congestion controller
NewRenoConfig
Configuration for the NewReno congestion controller

Traits§

Controller
Common interface for different congestion controllers
ControllerFactory
Constructs controllers on demand
\ No newline at end of file diff --git a/pr/255/docs/iroh_quinn/congestion/struct.Bbr.html b/pr/255/docs/iroh_quinn/congestion/struct.Bbr.html index 990c58c07..630fc0fa4 100644 --- a/pr/255/docs/iroh_quinn/congestion/struct.Bbr.html +++ b/pr/255/docs/iroh_quinn/congestion/struct.Bbr.html @@ -1,4 +1,4 @@ -Bbr in iroh_quinn::congestion - Rust

Bbr

Struct Bbr 

Source
pub struct Bbr { /* private fields */ }
Expand description

Experimental! Use at your own risk.

+Bbr in iroh_quinn::congestion - Rust

Bbr

Struct Bbr 

Source
pub struct Bbr { /* private fields */ }
Expand description

Experimental! Use at your own risk.

Aims for reduced buffer bloat and improved performance over high bandwidth-delay product networks. Based on google’s quiche implementation https://source.chromium.org/chromium/chromium/src/+/master:net/third_party/quiche/src/quic/core/congestion_control/bbr_sender.cc of BBR https://datatracker.ietf.org/doc/html/draft-cardwell-iccrg-bbr-congestion-control. diff --git a/pr/255/docs/iroh_quinn/congestion/struct.BbrConfig.html b/pr/255/docs/iroh_quinn/congestion/struct.BbrConfig.html index 3b267cdc4..f340fb3e2 100644 --- a/pr/255/docs/iroh_quinn/congestion/struct.BbrConfig.html +++ b/pr/255/docs/iroh_quinn/congestion/struct.BbrConfig.html @@ -1,4 +1,4 @@ -BbrConfig in iroh_quinn::congestion - Rust

BbrConfig

Struct BbrConfig 

Source
pub struct BbrConfig { /* private fields */ }
Expand description

Configuration for the Bbr congestion controller

+BbrConfig in iroh_quinn::congestion - Rust

BbrConfig

Struct BbrConfig 

Source
pub struct BbrConfig { /* private fields */ }
Expand description

Configuration for the Bbr congestion controller

Implementations§

Source§

impl BbrConfig

Source

pub fn initial_window(&mut self, value: u64) -> &mut BbrConfig

Default limit on the amount of outstanding data in bytes.

Recommended value: min(10 * max_datagram_size, max(2 * max_datagram_size, 14720))

Trait Implementations§

Source§

impl Clone for BbrConfig

Source§

fn clone(&self) -> BbrConfig

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl ControllerFactory for BbrConfig

Source§

fn build( diff --git a/pr/255/docs/iroh_quinn/congestion/struct.ControllerMetrics.html b/pr/255/docs/iroh_quinn/congestion/struct.ControllerMetrics.html index 09244b55e..b06811749 100644 --- a/pr/255/docs/iroh_quinn/congestion/struct.ControllerMetrics.html +++ b/pr/255/docs/iroh_quinn/congestion/struct.ControllerMetrics.html @@ -1,4 +1,4 @@ -ControllerMetrics in iroh_quinn::congestion - Rust

ControllerMetrics

Struct ControllerMetrics 

Source
#[non_exhaustive]
pub struct ControllerMetrics { +ControllerMetrics in iroh_quinn::congestion - Rust

ControllerMetrics

Struct ControllerMetrics 

Source
#[non_exhaustive]
pub struct ControllerMetrics { pub congestion_window: u64, pub ssthresh: Option<u64>, pub pacing_rate: Option<u64>, diff --git a/pr/255/docs/iroh_quinn/congestion/struct.Cubic.html b/pr/255/docs/iroh_quinn/congestion/struct.Cubic.html index b39ee37ea..822e5f78f 100644 --- a/pr/255/docs/iroh_quinn/congestion/struct.Cubic.html +++ b/pr/255/docs/iroh_quinn/congestion/struct.Cubic.html @@ -1,4 +1,4 @@ -Cubic in iroh_quinn::congestion - Rust

Cubic

Struct Cubic 

Source
pub struct Cubic { /* private fields */ }
Expand description

The RFC8312 congestion controller, as widely used for TCP

+Cubic in iroh_quinn::congestion - Rust

Cubic

Struct Cubic 

Source
pub struct Cubic { /* private fields */ }
Expand description

The RFC8312 congestion controller, as widely used for TCP

Implementations§

Source§

impl Cubic

Source

pub fn new(config: Arc<CubicConfig>, _now: Instant, current_mtu: u16) -> Cubic

Construct a state using the given config and current time now

Trait Implementations§

Source§

impl Clone for Cubic

Source§

fn clone(&self) -> Cubic

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Controller for Cubic

Source§

fn on_ack( &mut self, diff --git a/pr/255/docs/iroh_quinn/congestion/struct.CubicConfig.html b/pr/255/docs/iroh_quinn/congestion/struct.CubicConfig.html index 19a3bcba7..0b4a10fdc 100644 --- a/pr/255/docs/iroh_quinn/congestion/struct.CubicConfig.html +++ b/pr/255/docs/iroh_quinn/congestion/struct.CubicConfig.html @@ -1,4 +1,4 @@ -CubicConfig in iroh_quinn::congestion - Rust

CubicConfig

Struct CubicConfig 

Source
pub struct CubicConfig { /* private fields */ }
Expand description

Configuration for the Cubic congestion controller

+CubicConfig in iroh_quinn::congestion - Rust

CubicConfig

Struct CubicConfig 

Source
pub struct CubicConfig { /* private fields */ }
Expand description

Configuration for the Cubic congestion controller

Implementations§

Source§

impl CubicConfig

Source

pub fn initial_window(&mut self, value: u64) -> &mut CubicConfig

Default limit on the amount of outstanding data in bytes.

Recommended value: min(10 * max_datagram_size, max(2 * max_datagram_size, 14720))

Trait Implementations§

Source§

impl Clone for CubicConfig

Source§

fn clone(&self) -> CubicConfig

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl ControllerFactory for CubicConfig

Source§

fn build( diff --git a/pr/255/docs/iroh_quinn/congestion/struct.NewReno.html b/pr/255/docs/iroh_quinn/congestion/struct.NewReno.html index a29a548f7..4656699b6 100644 --- a/pr/255/docs/iroh_quinn/congestion/struct.NewReno.html +++ b/pr/255/docs/iroh_quinn/congestion/struct.NewReno.html @@ -1,4 +1,4 @@ -NewReno in iroh_quinn::congestion - Rust

NewReno

Struct NewReno 

Source
pub struct NewReno { /* private fields */ }
Expand description

A simple, standard congestion controller

+NewReno in iroh_quinn::congestion - Rust

NewReno

Struct NewReno 

Source
pub struct NewReno { /* private fields */ }
Expand description

A simple, standard congestion controller

Implementations§

Source§

impl NewReno

Source

pub fn new( config: Arc<NewRenoConfig>, now: Instant, diff --git a/pr/255/docs/iroh_quinn/congestion/struct.NewRenoConfig.html b/pr/255/docs/iroh_quinn/congestion/struct.NewRenoConfig.html index 7333c4b5d..5fe3a7f56 100644 --- a/pr/255/docs/iroh_quinn/congestion/struct.NewRenoConfig.html +++ b/pr/255/docs/iroh_quinn/congestion/struct.NewRenoConfig.html @@ -1,4 +1,4 @@ -NewRenoConfig in iroh_quinn::congestion - Rust

NewRenoConfig

Struct NewRenoConfig 

Source
pub struct NewRenoConfig { /* private fields */ }
Expand description

Configuration for the NewReno congestion controller

+NewRenoConfig in iroh_quinn::congestion - Rust

NewRenoConfig

Struct NewRenoConfig 

Source
pub struct NewRenoConfig { /* private fields */ }
Expand description

Configuration for the NewReno congestion controller

Implementations§

Source§

impl NewRenoConfig

Source

pub fn initial_window(&mut self, value: u64) -> &mut NewRenoConfig

Default limit on the amount of outstanding data in bytes.

Recommended value: min(10 * max_datagram_size, max(2 * max_datagram_size, 14720))

Source

pub fn loss_reduction_factor(&mut self, value: f32) -> &mut NewRenoConfig

Reduction in congestion window when a new loss event is detected.

diff --git a/pr/255/docs/iroh_quinn/congestion/trait.Controller.html b/pr/255/docs/iroh_quinn/congestion/trait.Controller.html index 4d9a8a8e9..6fd6a4943 100644 --- a/pr/255/docs/iroh_quinn/congestion/trait.Controller.html +++ b/pr/255/docs/iroh_quinn/congestion/trait.Controller.html @@ -1,4 +1,4 @@ -Controller in iroh_quinn::congestion - Rust

Controller

Trait Controller 

Source
pub trait Controller:
+Controller in iroh_quinn::congestion - Rust

Controller

Trait Controller 

Source
pub trait Controller:
     Send
     + Sync
     + Debug {
diff --git a/pr/255/docs/iroh_quinn/congestion/trait.ControllerFactory.html b/pr/255/docs/iroh_quinn/congestion/trait.ControllerFactory.html
index 6707640ab..056571893 100644
--- a/pr/255/docs/iroh_quinn/congestion/trait.ControllerFactory.html
+++ b/pr/255/docs/iroh_quinn/congestion/trait.ControllerFactory.html
@@ -1,4 +1,4 @@
-ControllerFactory in iroh_quinn::congestion - Rust

ControllerFactory

Trait ControllerFactory 

Source
pub trait ControllerFactory {
+ControllerFactory in iroh_quinn::congestion - Rust

ControllerFactory

Trait ControllerFactory 

Source
pub trait ControllerFactory {
     // Required method
     fn build(
         self: Arc<Self>,
diff --git a/pr/255/docs/iroh_quinn/crypto/index.html b/pr/255/docs/iroh_quinn/crypto/index.html
index 22dee581f..c3f1c74ee 100644
--- a/pr/255/docs/iroh_quinn/crypto/index.html
+++ b/pr/255/docs/iroh_quinn/crypto/index.html
@@ -1,4 +1,4 @@
-iroh_quinn::crypto - Rust

Module crypto

Module crypto 

Source
Expand description

Traits and implementations for the QUIC cryptography protocol

+iroh_quinn::crypto - Rust

Module crypto

Module crypto 

Source
Expand description

Traits and implementations for the QUIC cryptography protocol

The protocol logic in Quinn is contained in types that abstract over the actual cryptographic protocol used. This module contains the traits used for this abstraction layer as well as a single implementation of these traits that uses diff --git a/pr/255/docs/iroh_quinn/crypto/rustls/enum.Error.html b/pr/255/docs/iroh_quinn/crypto/rustls/enum.Error.html index 59ce9ffff..49cd9d5d4 100644 --- a/pr/255/docs/iroh_quinn/crypto/rustls/enum.Error.html +++ b/pr/255/docs/iroh_quinn/crypto/rustls/enum.Error.html @@ -1,4 +1,4 @@ -Error in iroh_quinn::crypto::rustls - Rust

Error

Enum Error 

#[non_exhaustive]
pub enum Error { +Error in iroh_quinn::crypto::rustls - Rust

Error

Enum Error 

#[non_exhaustive]
pub enum Error {
Show 22 variants InappropriateMessage { expect_types: Vec<ContentType>, got_type: ContentType, diff --git a/pr/255/docs/iroh_quinn/crypto/rustls/index.html b/pr/255/docs/iroh_quinn/crypto/rustls/index.html index 35a3c6577..ba8a16afa 100644 --- a/pr/255/docs/iroh_quinn/crypto/rustls/index.html +++ b/pr/255/docs/iroh_quinn/crypto/rustls/index.html @@ -1,2 +1,2 @@ -iroh_quinn::crypto::rustls - Rust

Module rustls

Module rustls 

Source
Expand description

TLS interface based on rustls

+iroh_quinn::crypto::rustls - Rust

Module rustls

Module rustls 

Source
Expand description

TLS interface based on rustls

Structs§

HandshakeData
Authentication data for (rustls) TLS session
NoInitialCipherSuite
The initial cipher suite (AES-128-GCM-SHA256) is not available
QuicClientConfig
A QUIC-compatible TLS client configuration
QuicServerConfig
A QUIC-compatible TLS server configuration
TlsSession
A rustls TLS session

Enums§

Error
rustls reports protocol errors using this type.
\ No newline at end of file diff --git a/pr/255/docs/iroh_quinn/crypto/rustls/struct.HandshakeData.html b/pr/255/docs/iroh_quinn/crypto/rustls/struct.HandshakeData.html index cdb7c70fc..47dd6568f 100644 --- a/pr/255/docs/iroh_quinn/crypto/rustls/struct.HandshakeData.html +++ b/pr/255/docs/iroh_quinn/crypto/rustls/struct.HandshakeData.html @@ -1,4 +1,4 @@ -HandshakeData in iroh_quinn::crypto::rustls - Rust

HandshakeData

Struct HandshakeData 

Source
pub struct HandshakeData {
+HandshakeData in iroh_quinn::crypto::rustls - Rust

HandshakeData

Struct HandshakeData 

Source
pub struct HandshakeData {
     pub protocol: Option<Vec<u8>>,
     pub server_name: Option<String>,
     pub negotiated_key_exchange_group: NamedGroup,
diff --git a/pr/255/docs/iroh_quinn/crypto/rustls/struct.NoInitialCipherSuite.html b/pr/255/docs/iroh_quinn/crypto/rustls/struct.NoInitialCipherSuite.html
index ee260d560..b5d8d04a6 100644
--- a/pr/255/docs/iroh_quinn/crypto/rustls/struct.NoInitialCipherSuite.html
+++ b/pr/255/docs/iroh_quinn/crypto/rustls/struct.NoInitialCipherSuite.html
@@ -1,4 +1,4 @@
-NoInitialCipherSuite in iroh_quinn::crypto::rustls - Rust

NoInitialCipherSuite

Struct NoInitialCipherSuite 

Source
pub struct NoInitialCipherSuite { /* private fields */ }
Expand description

The initial cipher suite (AES-128-GCM-SHA256) is not available

+NoInitialCipherSuite in iroh_quinn::crypto::rustls - Rust

NoInitialCipherSuite

Struct NoInitialCipherSuite 

Source
pub struct NoInitialCipherSuite { /* private fields */ }
Expand description

The initial cipher suite (AES-128-GCM-SHA256) is not available

When the cipher suite is supplied with_initial(), it must be [CipherSuite::TLS13_AES_128_GCM_SHA256]. When the cipher suite is derived from a config’s CryptoProvider, that provider must reference a cipher suite with the same ID.

diff --git a/pr/255/docs/iroh_quinn/crypto/rustls/struct.QuicClientConfig.html b/pr/255/docs/iroh_quinn/crypto/rustls/struct.QuicClientConfig.html index 01245bde8..00fbff019 100644 --- a/pr/255/docs/iroh_quinn/crypto/rustls/struct.QuicClientConfig.html +++ b/pr/255/docs/iroh_quinn/crypto/rustls/struct.QuicClientConfig.html @@ -1,4 +1,4 @@ -QuicClientConfig in iroh_quinn::crypto::rustls - Rust

QuicClientConfig

Struct QuicClientConfig 

Source
pub struct QuicClientConfig { /* private fields */ }
Expand description

A QUIC-compatible TLS client configuration

+QuicClientConfig in iroh_quinn::crypto::rustls - Rust

QuicClientConfig

Struct QuicClientConfig 

Source
pub struct QuicClientConfig { /* private fields */ }
Expand description

A QUIC-compatible TLS client configuration

Quinn implicitly constructs a QuicClientConfig with reasonable defaults within ClientConfig::with_root_certificates() and ClientConfig::with_platform_verifier(). Alternatively, QuicClientConfig’s TryFrom implementation can be used to wrap around a diff --git a/pr/255/docs/iroh_quinn/crypto/rustls/struct.QuicServerConfig.html b/pr/255/docs/iroh_quinn/crypto/rustls/struct.QuicServerConfig.html index 3a89edfc5..cd5aca2da 100644 --- a/pr/255/docs/iroh_quinn/crypto/rustls/struct.QuicServerConfig.html +++ b/pr/255/docs/iroh_quinn/crypto/rustls/struct.QuicServerConfig.html @@ -1,4 +1,4 @@ -QuicServerConfig in iroh_quinn::crypto::rustls - Rust

QuicServerConfig

Struct QuicServerConfig 

Source
pub struct QuicServerConfig { /* private fields */ }
Expand description

A QUIC-compatible TLS server configuration

+QuicServerConfig in iroh_quinn::crypto::rustls - Rust

QuicServerConfig

Struct QuicServerConfig 

Source
pub struct QuicServerConfig { /* private fields */ }
Expand description

A QUIC-compatible TLS server configuration

Quinn implicitly constructs a QuicServerConfig with reasonable defaults within ServerConfig::with_single_cert(). Alternatively, QuicServerConfig’s TryFrom implementation or with_initial method can be used to wrap around a custom diff --git a/pr/255/docs/iroh_quinn/crypto/rustls/struct.TlsSession.html b/pr/255/docs/iroh_quinn/crypto/rustls/struct.TlsSession.html index 3e69b9872..0168dd5fb 100644 --- a/pr/255/docs/iroh_quinn/crypto/rustls/struct.TlsSession.html +++ b/pr/255/docs/iroh_quinn/crypto/rustls/struct.TlsSession.html @@ -1,4 +1,4 @@ -TlsSession in iroh_quinn::crypto::rustls - Rust

TlsSession

Struct TlsSession 

Source
pub struct TlsSession { /* private fields */ }
Expand description

A rustls TLS session

+TlsSession in iroh_quinn::crypto::rustls - Rust

TlsSession

Struct TlsSession 

Source
pub struct TlsSession { /* private fields */ }
Expand description

A rustls TLS session

Trait Implementations§

Source§

impl Session for TlsSession

Source§

fn peer_identity(&self) -> Option<Box<dyn Any>>

For the rustls TlsSession, the Any type is Vec<rustls::pki_types::CertificateDer>

Source§

fn initial_keys(&self, dst_cid: ConnectionId, side: Side) -> Keys

Create the initial set of keys given the client’s initial destination ConnectionId
Source§

fn handshake_data(&self) -> Option<Box<dyn Any>>

Get data negotiated during the handshake, if available Read more
Source§

fn early_crypto(&self) -> Option<(Box<dyn HeaderKey>, Box<dyn PacketKey>)>

Get the 0-RTT keys if available (clients only) Read more
Source§

fn early_data_accepted(&self) -> Option<bool>

If the 0-RTT-encrypted data has been accepted by the peer
Source§

fn is_handshaking(&self) -> bool

Returns true until the connection is fully established.
Source§

fn read_handshake(&mut self, buf: &[u8]) -> Result<bool, Error>

Read bytes of handshake data Read more
Source§

fn transport_parameters(&self) -> Result<Option<TransportParameters>, Error>

The peer’s QUIC transport parameters Read more
Source§

fn write_handshake(&mut self, buf: &mut Vec<u8>) -> Option<Keys>

Writes handshake bytes into the given buffer and optionally returns the negotiated keys Read more
Source§

fn next_1rtt_keys(&mut self) -> Option<KeyPair<Box<dyn PacketKey>>>

Compute keys for the next key update
Source§

fn is_valid_retry( &self, diff --git a/pr/255/docs/iroh_quinn/crypto/struct.CryptoError.html b/pr/255/docs/iroh_quinn/crypto/struct.CryptoError.html index b60f9c45c..eec18a5af 100644 --- a/pr/255/docs/iroh_quinn/crypto/struct.CryptoError.html +++ b/pr/255/docs/iroh_quinn/crypto/struct.CryptoError.html @@ -1,4 +1,4 @@ -CryptoError in iroh_quinn::crypto - Rust

CryptoError

Struct CryptoError 

Source
pub struct CryptoError;
Expand description

Generic crypto errors

+CryptoError in iroh_quinn::crypto - Rust

CryptoError

Struct CryptoError 

Source
pub struct CryptoError;
Expand description

Generic crypto errors

Trait Implementations§

Source§

impl Debug for CryptoError

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl From<Unspecified> for CryptoError

Source§

fn from(_: Unspecified) -> CryptoError

Converts to this type from the input type.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where diff --git a/pr/255/docs/iroh_quinn/crypto/struct.ExportKeyingMaterialError.html b/pr/255/docs/iroh_quinn/crypto/struct.ExportKeyingMaterialError.html index e24d2196e..c6f81f007 100644 --- a/pr/255/docs/iroh_quinn/crypto/struct.ExportKeyingMaterialError.html +++ b/pr/255/docs/iroh_quinn/crypto/struct.ExportKeyingMaterialError.html @@ -1,4 +1,4 @@ -ExportKeyingMaterialError in iroh_quinn::crypto - Rust

ExportKeyingMaterialError

Struct ExportKeyingMaterialError 

Source
pub struct ExportKeyingMaterialError;
Expand description

Error returned by Session::export_keying_material.

+ExportKeyingMaterialError in iroh_quinn::crypto - Rust

ExportKeyingMaterialError

Struct ExportKeyingMaterialError 

Source
pub struct ExportKeyingMaterialError;
Expand description

Error returned by Session::export_keying_material.

This error occurs if the requested output length is too large.

Trait Implementations§

Source§

impl Debug for ExportKeyingMaterialError

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl PartialEq for ExportKeyingMaterialError

Source§

fn eq(&self, other: &ExportKeyingMaterialError) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl Eq for ExportKeyingMaterialError

Source§

impl StructuralPartialEq for ExportKeyingMaterialError

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where diff --git a/pr/255/docs/iroh_quinn/crypto/struct.KeyPair.html b/pr/255/docs/iroh_quinn/crypto/struct.KeyPair.html index c4dc97199..639077cb6 100644 --- a/pr/255/docs/iroh_quinn/crypto/struct.KeyPair.html +++ b/pr/255/docs/iroh_quinn/crypto/struct.KeyPair.html @@ -1,4 +1,4 @@ -KeyPair in iroh_quinn::crypto - Rust

KeyPair

Struct KeyPair 

Source
pub struct KeyPair<T> {
+KeyPair in iroh_quinn::crypto - Rust

KeyPair

Struct KeyPair 

Source
pub struct KeyPair<T> {
     pub local: T,
     pub remote: T,
 }
Expand description

A pair of keys for bidirectional communication

diff --git a/pr/255/docs/iroh_quinn/crypto/struct.Keys.html b/pr/255/docs/iroh_quinn/crypto/struct.Keys.html index 232814912..24a88b01b 100644 --- a/pr/255/docs/iroh_quinn/crypto/struct.Keys.html +++ b/pr/255/docs/iroh_quinn/crypto/struct.Keys.html @@ -1,4 +1,4 @@ -Keys in iroh_quinn::crypto - Rust

Keys

Struct Keys 

Source
pub struct Keys {
+Keys in iroh_quinn::crypto - Rust

Keys

Struct Keys 

Source
pub struct Keys {
     pub header: KeyPair<Box<dyn HeaderKey>>,
     pub packet: KeyPair<Box<dyn PacketKey>>,
 }
Expand description

A complete set of keys for a certain packet space

diff --git a/pr/255/docs/iroh_quinn/crypto/struct.UnsupportedVersion.html b/pr/255/docs/iroh_quinn/crypto/struct.UnsupportedVersion.html index 709220217..4fe4bcf1f 100644 --- a/pr/255/docs/iroh_quinn/crypto/struct.UnsupportedVersion.html +++ b/pr/255/docs/iroh_quinn/crypto/struct.UnsupportedVersion.html @@ -1,4 +1,4 @@ -UnsupportedVersion in iroh_quinn::crypto - Rust

UnsupportedVersion

Struct UnsupportedVersion 

Source
pub struct UnsupportedVersion;
Expand description

Error indicating that the specified QUIC version is not supported

+UnsupportedVersion in iroh_quinn::crypto - Rust

UnsupportedVersion

Struct UnsupportedVersion 

Source
pub struct UnsupportedVersion;
Expand description

Error indicating that the specified QUIC version is not supported

Trait Implementations§

Source§

impl Debug for UnsupportedVersion

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl From<UnsupportedVersion> for ConnectError

Source§

fn from(_: UnsupportedVersion) -> ConnectError

Converts to this type from the input type.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where diff --git a/pr/255/docs/iroh_quinn/crypto/trait.AeadKey.html b/pr/255/docs/iroh_quinn/crypto/trait.AeadKey.html index 51ac071fe..4cdb6d379 100644 --- a/pr/255/docs/iroh_quinn/crypto/trait.AeadKey.html +++ b/pr/255/docs/iroh_quinn/crypto/trait.AeadKey.html @@ -1,4 +1,4 @@ -AeadKey in iroh_quinn::crypto - Rust

AeadKey

Trait AeadKey 

Source
pub trait AeadKey {
+AeadKey in iroh_quinn::crypto - Rust

AeadKey

Trait AeadKey 

Source
pub trait AeadKey {
     // Required methods
     fn seal(
         &self,
diff --git a/pr/255/docs/iroh_quinn/crypto/trait.ClientConfig.html b/pr/255/docs/iroh_quinn/crypto/trait.ClientConfig.html
index 46555b5ff..1daa840d1 100644
--- a/pr/255/docs/iroh_quinn/crypto/trait.ClientConfig.html
+++ b/pr/255/docs/iroh_quinn/crypto/trait.ClientConfig.html
@@ -1,4 +1,4 @@
-ClientConfig in iroh_quinn::crypto - Rust

ClientConfig

Trait ClientConfig 

Source
pub trait ClientConfig: Send + Sync {
+ClientConfig in iroh_quinn::crypto - Rust

ClientConfig

Trait ClientConfig 

Source
pub trait ClientConfig: Send + Sync {
     // Required method
     fn start_session(
         self: Arc<Self>,
diff --git a/pr/255/docs/iroh_quinn/crypto/trait.HandshakeTokenKey.html b/pr/255/docs/iroh_quinn/crypto/trait.HandshakeTokenKey.html
index 85576ce8e..7ad34a69c 100644
--- a/pr/255/docs/iroh_quinn/crypto/trait.HandshakeTokenKey.html
+++ b/pr/255/docs/iroh_quinn/crypto/trait.HandshakeTokenKey.html
@@ -1,4 +1,4 @@
-HandshakeTokenKey in iroh_quinn::crypto - Rust

HandshakeTokenKey

Trait HandshakeTokenKey 

Source
pub trait HandshakeTokenKey: Send + Sync {
+HandshakeTokenKey in iroh_quinn::crypto - Rust

HandshakeTokenKey

Trait HandshakeTokenKey 

Source
pub trait HandshakeTokenKey: Send + Sync {
     // Required method
     fn aead_from_hkdf(&self, random_bytes: &[u8]) -> Box<dyn AeadKey>;
 }
Expand description

A pseudo random key for HKDF

diff --git a/pr/255/docs/iroh_quinn/crypto/trait.HeaderKey.html b/pr/255/docs/iroh_quinn/crypto/trait.HeaderKey.html index bc22e9b18..355b73848 100644 --- a/pr/255/docs/iroh_quinn/crypto/trait.HeaderKey.html +++ b/pr/255/docs/iroh_quinn/crypto/trait.HeaderKey.html @@ -1,4 +1,4 @@ -HeaderKey in iroh_quinn::crypto - Rust

HeaderKey

Trait HeaderKey 

Source
pub trait HeaderKey: Send + Sync {
+HeaderKey in iroh_quinn::crypto - Rust

HeaderKey

Trait HeaderKey 

Source
pub trait HeaderKey: Send + Sync {
     // Required methods
     fn decrypt(&self, pn_offset: usize, packet: &mut [u8]);
     fn encrypt(&self, pn_offset: usize, packet: &mut [u8]);
diff --git a/pr/255/docs/iroh_quinn/crypto/trait.HmacKey.html b/pr/255/docs/iroh_quinn/crypto/trait.HmacKey.html
index 684cfc6a1..541975bd6 100644
--- a/pr/255/docs/iroh_quinn/crypto/trait.HmacKey.html
+++ b/pr/255/docs/iroh_quinn/crypto/trait.HmacKey.html
@@ -1,4 +1,4 @@
-HmacKey in iroh_quinn::crypto - Rust

HmacKey

Trait HmacKey 

Source
pub trait HmacKey: Send + Sync {
+HmacKey in iroh_quinn::crypto - Rust

HmacKey

Trait HmacKey 

Source
pub trait HmacKey: Send + Sync {
     // Required methods
     fn sign(&self, data: &[u8], signature_out: &mut [u8]);
     fn signature_len(&self) -> usize;
diff --git a/pr/255/docs/iroh_quinn/crypto/trait.PacketKey.html b/pr/255/docs/iroh_quinn/crypto/trait.PacketKey.html
index b4580faf0..f129bbda6 100644
--- a/pr/255/docs/iroh_quinn/crypto/trait.PacketKey.html
+++ b/pr/255/docs/iroh_quinn/crypto/trait.PacketKey.html
@@ -1,4 +1,4 @@
-PacketKey in iroh_quinn::crypto - Rust

PacketKey

Trait PacketKey 

Source
pub trait PacketKey: Send + Sync {
+PacketKey in iroh_quinn::crypto - Rust

PacketKey

Trait PacketKey 

Source
pub trait PacketKey: Send + Sync {
     // Required methods
     fn encrypt(
         &self,
diff --git a/pr/255/docs/iroh_quinn/crypto/trait.ServerConfig.html b/pr/255/docs/iroh_quinn/crypto/trait.ServerConfig.html
index 45f057eae..c25b21b5a 100644
--- a/pr/255/docs/iroh_quinn/crypto/trait.ServerConfig.html
+++ b/pr/255/docs/iroh_quinn/crypto/trait.ServerConfig.html
@@ -1,4 +1,4 @@
-ServerConfig in iroh_quinn::crypto - Rust

ServerConfig

Trait ServerConfig 

Source
pub trait ServerConfig: Send + Sync {
+ServerConfig in iroh_quinn::crypto - Rust

ServerConfig

Trait ServerConfig 

Source
pub trait ServerConfig: Send + Sync {
     // Required methods
     fn initial_keys(
         &self,
diff --git a/pr/255/docs/iroh_quinn/crypto/trait.Session.html b/pr/255/docs/iroh_quinn/crypto/trait.Session.html
index 490c06363..2654dc8a2 100644
--- a/pr/255/docs/iroh_quinn/crypto/trait.Session.html
+++ b/pr/255/docs/iroh_quinn/crypto/trait.Session.html
@@ -1,4 +1,4 @@
-Session in iroh_quinn::crypto - Rust

Session

Trait Session 

Source
pub trait Session:
+Session in iroh_quinn::crypto - Rust

Session

Trait Session 

Source
pub trait Session:
     Send
     + Sync
     + 'static {
diff --git a/pr/255/docs/iroh_quinn/enum.ConfigError.html b/pr/255/docs/iroh_quinn/enum.ConfigError.html
index 659f797b9..f0a6f72ec 100644
--- a/pr/255/docs/iroh_quinn/enum.ConfigError.html
+++ b/pr/255/docs/iroh_quinn/enum.ConfigError.html
@@ -1,4 +1,4 @@
-ConfigError in iroh_quinn - Rust

ConfigError

Enum ConfigError 

Source
#[non_exhaustive]
pub enum ConfigError { +ConfigError in iroh_quinn - Rust

ConfigError

Enum ConfigError 

Source
#[non_exhaustive]
pub enum ConfigError { OutOfBounds, }
Expand description

Errors in the configuration of an endpoint

Variants (Non-exhaustive)§

This enum is marked as non-exhaustive
Non-exhaustive enums could have additional variants added in future. Therefore, when matching against variants of non-exhaustive enums, an extra wildcard arm must be added to account for any future variants.
§

OutOfBounds

Value exceeds supported bounds

diff --git a/pr/255/docs/iroh_quinn/enum.ConnectError.html b/pr/255/docs/iroh_quinn/enum.ConnectError.html index d0f8ace66..cbdd09bd8 100644 --- a/pr/255/docs/iroh_quinn/enum.ConnectError.html +++ b/pr/255/docs/iroh_quinn/enum.ConnectError.html @@ -1,4 +1,4 @@ -ConnectError in iroh_quinn - Rust

ConnectError

Enum ConnectError 

Source
pub enum ConnectError {
+ConnectError in iroh_quinn - Rust

ConnectError

Enum ConnectError 

Source
pub enum ConnectError {
     EndpointStopping,
     CidsExhausted,
     InvalidServerName(String),
diff --git a/pr/255/docs/iroh_quinn/enum.ConnectionError.html b/pr/255/docs/iroh_quinn/enum.ConnectionError.html
index af340953e..088a81850 100644
--- a/pr/255/docs/iroh_quinn/enum.ConnectionError.html
+++ b/pr/255/docs/iroh_quinn/enum.ConnectionError.html
@@ -1,4 +1,4 @@
-ConnectionError in iroh_quinn - Rust

ConnectionError

Enum ConnectionError 

Source
pub enum ConnectionError {
+ConnectionError in iroh_quinn - Rust

ConnectionError

Enum ConnectionError 

Source
pub enum ConnectionError {
     VersionMismatch,
     TransportError(Error),
     ConnectionClosed(ConnectionClose),
@@ -20,7 +20,7 @@ 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 more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for ConnectionError

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl Display for ConnectionError

Source§

fn fmt(&self, __formatter: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl Error for ConnectionError

Source§

fn source(&self) -> Option<&(dyn Error + 'static)>

Returns the lower-level source of this error, if any. Read more
1.0.0 · Source§

fn description(&self) -> &str

👎Deprecated since 1.42.0: use the Display impl or to_string()
1.0.0 · Source§

fn cause(&self) -> Option<&dyn Error>

👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
Source§

fn provide<'a>(&'a self, request: &mut Request<'a>)

🔬This is a nightly-only experimental API. (error_generic_member_access)
Provides type-based access to context intended for error reports. Read more
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§

fn eq(&self, other: &ConnectionError) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, +

Trait Implementations§

Source§

impl Clone for ConnectionError

Source§

fn clone(&self) -> ConnectionError

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for ConnectionError

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl Display for ConnectionError

Source§

fn fmt(&self, __formatter: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl Error for ConnectionError

Source§

fn source(&self) -> Option<&(dyn Error + 'static)>

Returns the lower-level source of this error, if any. Read more
1.0.0 · Source§

fn description(&self) -> &str

👎Deprecated since 1.42.0: use the Display impl or to_string()
1.0.0 · Source§

fn cause(&self) -> Option<&dyn Error>

👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
Source§

fn provide<'a>(&'a self, request: &mut Request<'a>)

🔬This is a nightly-only experimental API. (error_generic_member_access)
Provides type-based access to context intended for error reports. Read more
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§

fn eq(&self, other: &ConnectionError) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl Eq for ConnectionError

Source§

impl StructuralPartialEq for ConnectionError

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where diff --git a/pr/255/docs/iroh_quinn/enum.Dir.html b/pr/255/docs/iroh_quinn/enum.Dir.html index f7e187e1f..efbb040b3 100644 --- a/pr/255/docs/iroh_quinn/enum.Dir.html +++ b/pr/255/docs/iroh_quinn/enum.Dir.html @@ -1,4 +1,4 @@ -Dir in iroh_quinn - Rust

Dir

Enum Dir 

Source
pub enum Dir {
+Dir in iroh_quinn - Rust

Dir

Enum Dir 

Source
pub enum Dir {
     Bi = 0,
     Uni = 1,
 }
Expand description

Whether a stream communicates data in both directions or only from the initiator

diff --git a/pr/255/docs/iroh_quinn/enum.EcnCodepoint.html b/pr/255/docs/iroh_quinn/enum.EcnCodepoint.html index 9dc3f3563..0571db855 100644 --- a/pr/255/docs/iroh_quinn/enum.EcnCodepoint.html +++ b/pr/255/docs/iroh_quinn/enum.EcnCodepoint.html @@ -1,4 +1,4 @@ -EcnCodepoint in iroh_quinn - Rust

EcnCodepoint

Enum EcnCodepoint 

Source
#[repr(u8)]
pub enum EcnCodepoint { +EcnCodepoint in iroh_quinn - Rust

EcnCodepoint

Enum EcnCodepoint 

Source
#[repr(u8)]
pub enum EcnCodepoint { Ect0 = 2, Ect1 = 1, Ce = 3, diff --git a/pr/255/docs/iroh_quinn/enum.FrameType.html b/pr/255/docs/iroh_quinn/enum.FrameType.html index fe640829e..a35f3f031 100644 --- a/pr/255/docs/iroh_quinn/enum.FrameType.html +++ b/pr/255/docs/iroh_quinn/enum.FrameType.html @@ -1,4 +1,4 @@ -FrameType in iroh_quinn - Rust

FrameType

Enum FrameType 

Source
pub enum FrameType {
+FrameType in iroh_quinn - Rust

FrameType

Enum FrameType 

Source
pub enum FrameType {
 
Show 44 variants Padding, Ping, Ack, @@ -43,11 +43,10 @@ ReachOutAtIpv4, ReachOutAtIpv6, RemoveAddress, -
}
Expand description

A QUIC frame type

-

Variants§

§

Padding

§

Ping

§

Ack

§

AckEcn

§

ResetStream

§

StopSending

§

Crypto

§

NewToken

§

Stream(StreamInfo)

§

MaxData

§

MaxStreamData

§

MaxStreamsBidi

§

MaxStreamsUni

§

DataBlocked

§

StreamDataBlocked

§

StreamsBlockedBidi

§

StreamsBlockedUni

§

NewConnectionId

§

RetireConnectionId

§

PathChallenge

§

PathResponse

§

ConnectionClose

§

ApplicationClose

§

HandshakeDone

§

AckFrequency

§

ImmediateAck

§

Datagram(DatagramInfo)

§

ObservedIpv4Addr

§

ObservedIpv6Addr

§

PathAck

§

PathAckEcn

§

PathAbandon

§

PathStatusBackup

§

PathStatusAvailable

§

PathNewConnectionId

§

PathRetireConnectionId

§

MaxPathId

§

PathsBlocked

§

PathCidsBlocked

§

AddIpv4Address

§

AddIpv6Address

§

ReachOutAtIpv4

§

ReachOutAtIpv6

§

RemoveAddress

Trait Implementations§

Source§

impl Clone for FrameType

Source§

fn clone(&self) -> FrameType

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for FrameType

Source§

fn fmt(&self, __derive_more_f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl Decodable for FrameType

Source§

fn decode<B>(buf: &mut B) -> Result<FrameType, UnexpectedEnd>
where - B: Buf,

Decode a Self from the provided buffer, if the buffer is large enough
Source§

impl Display for FrameType

Source§

fn fmt(&self, __derive_more_f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl Encodable for FrameType

Source§

fn encode<B>(&self, buf: &mut B)
where - B: BufMut,

Append the encoding of self to the provided buffer.
Source§

impl PartialEq for FrameType

Source§

fn eq(&self, other: &FrameType) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, -and should not be overridden without very good reason.
Source§

impl TryFrom<u64> for FrameType

Source§

type Error = InvalidFrameId

The type returned in the event of a conversion error.
Source§

fn try_from(value: u64) -> Result<FrameType, <FrameType as TryFrom<u64>>::Error>

Performs the conversion.
Source§

impl Copy for FrameType

Source§

impl Eq for FrameType

Source§

impl StructuralPartialEq for FrameType

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where +

}

Variants§

§

Padding

§

Ping

§

Ack

§

AckEcn

§

ResetStream

§

StopSending

§

Crypto

§

NewToken

§

Stream(StreamInfo)

§

MaxData

§

MaxStreamData

§

MaxStreamsBidi

§

MaxStreamsUni

§

DataBlocked

§

StreamDataBlocked

§

StreamsBlockedBidi

§

StreamsBlockedUni

§

NewConnectionId

§

RetireConnectionId

§

PathChallenge

§

PathResponse

§

ConnectionClose

§

ApplicationClose

§

HandshakeDone

§

AckFrequency

§

ImmediateAck

§

Datagram(DatagramInfo)

§

ObservedIpv4Addr

§

ObservedIpv6Addr

§

PathAck

§

PathAckEcn

§

PathAbandon

§

PathStatusBackup

§

PathStatusAvailable

§

PathNewConnectionId

§

PathRetireConnectionId

§

MaxPathId

§

PathsBlocked

§

PathCidsBlocked

§

AddIpv4Address

§

AddIpv6Address

§

ReachOutAtIpv4

§

ReachOutAtIpv6

§

RemoveAddress

Trait Implementations§

Source§

impl Clone for FrameType

Source§

fn clone(&self) -> FrameType

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for FrameType

Source§

fn fmt(&self, __derive_more_f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl Decodable for FrameType

Source§

fn decode<B>(buf: &mut B) -> Result<FrameType, UnexpectedEnd>
where + B: Buf,

Decode a Self from the provided buffer, if the buffer is large enough
Source§

impl Display for FrameType

Source§

fn fmt(&self, __derive_more_f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl Encodable for FrameType

Source§

fn encode<B>(&self, buf: &mut B)
where + B: BufMut,

Append the encoding of self to the provided buffer.
Source§

impl PartialEq for FrameType

Source§

fn eq(&self, other: &FrameType) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, +and should not be overridden without very good reason.
Source§

impl TryFrom<u64> for FrameType

Source§

type Error = InvalidFrameId

The type returned in the event of a conversion error.
Source§

fn try_from(value: u64) -> Result<FrameType, <FrameType as TryFrom<u64>>::Error>

Performs the conversion.
Source§

impl Copy for FrameType

Source§

impl Eq for FrameType

Source§

impl StructuralPartialEq for FrameType

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where diff --git a/pr/255/docs/iroh_quinn/enum.ReadError.html b/pr/255/docs/iroh_quinn/enum.ReadError.html index f07ed9270..d20463df7 100644 --- a/pr/255/docs/iroh_quinn/enum.ReadError.html +++ b/pr/255/docs/iroh_quinn/enum.ReadError.html @@ -1,4 +1,4 @@ -ReadError in iroh_quinn - Rust

ReadError

Enum ReadError 

Source
pub enum ReadError {
+ReadError in iroh_quinn - Rust

ReadError

Enum ReadError 

Source
pub enum ReadError {
     Reset(VarInt),
     ConnectionLost(ConnectionError),
     ClosedStream,
diff --git a/pr/255/docs/iroh_quinn/enum.ReadExactError.html b/pr/255/docs/iroh_quinn/enum.ReadExactError.html
index cfa14f40f..9092da520 100644
--- a/pr/255/docs/iroh_quinn/enum.ReadExactError.html
+++ b/pr/255/docs/iroh_quinn/enum.ReadExactError.html
@@ -1,4 +1,4 @@
-ReadExactError in iroh_quinn - Rust

ReadExactError

Enum ReadExactError 

Source
pub enum ReadExactError {
+ReadExactError in iroh_quinn - Rust

ReadExactError

Enum ReadExactError 

Source
pub enum ReadExactError {
     FinishedEarly(usize),
     ReadError(ReadError),
 }
Expand description

Errors that arise from reading from a stream.

diff --git a/pr/255/docs/iroh_quinn/enum.ReadToEndError.html b/pr/255/docs/iroh_quinn/enum.ReadToEndError.html index 82b309e87..ff17280a4 100644 --- a/pr/255/docs/iroh_quinn/enum.ReadToEndError.html +++ b/pr/255/docs/iroh_quinn/enum.ReadToEndError.html @@ -1,4 +1,4 @@ -ReadToEndError in iroh_quinn - Rust

ReadToEndError

Enum ReadToEndError 

Source
pub enum ReadToEndError {
+ReadToEndError in iroh_quinn - Rust

ReadToEndError

Enum ReadToEndError 

Source
pub enum ReadToEndError {
     Read(ReadError),
     TooLong,
 }
Expand description

Errors from RecvStream::read_to_end

diff --git a/pr/255/docs/iroh_quinn/enum.ResetError.html b/pr/255/docs/iroh_quinn/enum.ResetError.html index 8702e7efd..ae6ceb2e5 100644 --- a/pr/255/docs/iroh_quinn/enum.ResetError.html +++ b/pr/255/docs/iroh_quinn/enum.ResetError.html @@ -1,4 +1,4 @@ -ResetError in iroh_quinn - Rust

ResetError

Enum ResetError 

Source
pub enum ResetError {
+ResetError in iroh_quinn - Rust

ResetError

Enum ResetError 

Source
pub enum ResetError {
     ConnectionLost(ConnectionError),
     ZeroRttRejected,
 }
Expand description

Errors that arise while waiting for a stream to be reset

diff --git a/pr/255/docs/iroh_quinn/enum.SendDatagramError.html b/pr/255/docs/iroh_quinn/enum.SendDatagramError.html index bd22b081c..23fd1cb34 100644 --- a/pr/255/docs/iroh_quinn/enum.SendDatagramError.html +++ b/pr/255/docs/iroh_quinn/enum.SendDatagramError.html @@ -1,4 +1,4 @@ -SendDatagramError in iroh_quinn - Rust

SendDatagramError

Enum SendDatagramError 

Source
pub enum SendDatagramError {
+SendDatagramError in iroh_quinn - Rust

SendDatagramError

Enum SendDatagramError 

Source
pub enum SendDatagramError {
     UnsupportedByPeer,
     Disabled,
     TooLarge,
@@ -10,8 +10,8 @@
 

Indicates that the path MTU minus overhead or the limit advertised by the peer has been exceeded.

§

ConnectionLost(ConnectionError)

The connection was lost

-

Trait Implementations§

Source§

impl Clone for SendDatagramError

Source§

fn clone(&self) -> SendDatagramError

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for SendDatagramError

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Display for SendDatagramError

Source§

fn fmt(&self, __formatter: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Error for SendDatagramError

Source§

fn source(&self) -> Option<&(dyn Error + 'static)>

Returns the lower-level source of this error, if any. Read more
1.0.0 · Source§

fn description(&self) -> &str

👎Deprecated since 1.42.0: use the Display impl or to_string()
1.0.0 · Source§

fn cause(&self) -> Option<&dyn Error>

👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
Source§

fn provide<'a>(&'a self, request: &mut Request<'a>)

🔬This is a nightly-only experimental API. (error_generic_member_access)
Provides type-based access to context intended for error reports. Read more
Source§

impl From<ConnectionError> for SendDatagramError

Source§

fn from(source: ConnectionError) -> Self

Converts to this type from the input type.
Source§

impl PartialEq for SendDatagramError

Source§

fn eq(&self, other: &SendDatagramError) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, -and should not be overridden without very good reason.
Source§

impl Eq for SendDatagramError

Source§

impl StructuralPartialEq for SendDatagramError

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where +

Trait Implementations§

Source§

impl Clone for SendDatagramError

Source§

fn clone(&self) -> SendDatagramError

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for SendDatagramError

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Display for SendDatagramError

Source§

fn fmt(&self, __formatter: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Error for SendDatagramError

Source§

fn source(&self) -> Option<&(dyn Error + 'static)>

Returns the lower-level source of this error, if any. Read more
1.0.0 · Source§

fn description(&self) -> &str

👎Deprecated since 1.42.0: use the Display impl or to_string()
1.0.0 · Source§

fn cause(&self) -> Option<&dyn Error>

👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
Source§

fn provide<'a>(&'a self, request: &mut Request<'a>)

🔬This is a nightly-only experimental API. (error_generic_member_access)
Provides type-based access to context intended for error reports. Read more
Source§

impl From<ConnectionError> for SendDatagramError

Source§

fn from(source: ConnectionError) -> Self

Converts to this type from the input type.
Source§

impl PartialEq for SendDatagramError

Source§

fn eq(&self, other: &SendDatagramError) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, +and should not be overridden without very good reason.
Source§

impl Eq for SendDatagramError

Source§

impl StructuralPartialEq for SendDatagramError

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where diff --git a/pr/255/docs/iroh_quinn/enum.Side.html b/pr/255/docs/iroh_quinn/enum.Side.html index e2c824d18..2bcf64c9b 100644 --- a/pr/255/docs/iroh_quinn/enum.Side.html +++ b/pr/255/docs/iroh_quinn/enum.Side.html @@ -1,4 +1,4 @@ -Side in iroh_quinn - Rust

Side

Enum Side 

Source
pub enum Side {
+Side in iroh_quinn - Rust

Side

Enum Side 

Source
pub enum Side {
     Client = 0,
     Server = 1,
 }
Expand description

Whether an endpoint was the initiator of a connection

diff --git a/pr/255/docs/iroh_quinn/enum.StoppedError.html b/pr/255/docs/iroh_quinn/enum.StoppedError.html index cf9fcd7f7..42ac78ed6 100644 --- a/pr/255/docs/iroh_quinn/enum.StoppedError.html +++ b/pr/255/docs/iroh_quinn/enum.StoppedError.html @@ -1,4 +1,4 @@ -StoppedError in iroh_quinn - Rust

StoppedError

Enum StoppedError 

Source
pub enum StoppedError {
+StoppedError in iroh_quinn - Rust

StoppedError

Enum StoppedError 

Source
pub enum StoppedError {
     ConnectionLost(ConnectionError),
     ZeroRttRejected,
 }
Expand description

Errors that arise while monitoring for a send stream stop from the peer

diff --git a/pr/255/docs/iroh_quinn/enum.WriteError.html b/pr/255/docs/iroh_quinn/enum.WriteError.html index fd9bfb6a1..48fd44e36 100644 --- a/pr/255/docs/iroh_quinn/enum.WriteError.html +++ b/pr/255/docs/iroh_quinn/enum.WriteError.html @@ -1,4 +1,4 @@ -WriteError in iroh_quinn - Rust

WriteError

Enum WriteError 

Source
pub enum WriteError {
+WriteError in iroh_quinn - Rust

WriteError

Enum WriteError 

Source
pub enum WriteError {
     Stopped(VarInt),
     ConnectionLost(ConnectionError),
     ClosedStream,
diff --git a/pr/255/docs/iroh_quinn/fn.default_runtime.html b/pr/255/docs/iroh_quinn/fn.default_runtime.html
index d741ac157..f7c0e26f8 100644
--- a/pr/255/docs/iroh_quinn/fn.default_runtime.html
+++ b/pr/255/docs/iroh_quinn/fn.default_runtime.html
@@ -1,4 +1,4 @@
-default_runtime in iroh_quinn - Rust

default_runtime

Function default_runtime 

Source
pub fn default_runtime() -> Option<Arc<dyn Runtime>>
Expand description

Automatically select an appropriate runtime from those enabled at compile time

+default_runtime in iroh_quinn - Rust

default_runtime

Function default_runtime 

Source
pub fn default_runtime() -> Option<Arc<dyn Runtime>>
Expand description

Automatically select an appropriate runtime from those enabled at compile time

If runtime-tokio is enabled and this function is called from within a Tokio runtime context, then TokioRuntime is returned. Otherwise, if runtime-smol is enabled, SmolRuntime is returned. Otherwise, None is returned.

diff --git a/pr/255/docs/iroh_quinn/index.html b/pr/255/docs/iroh_quinn/index.html index 322e4f8fe..281df6ef6 100644 --- a/pr/255/docs/iroh_quinn/index.html +++ b/pr/255/docs/iroh_quinn/index.html @@ -1,4 +1,4 @@ -iroh_quinn - Rust

Crate iroh_quinn

Crate iroh_quinn 

Source
Expand description

QUIC transport protocol implementation

+iroh_quinn - Rust

Crate iroh_quinn

Crate iroh_quinn 

Source
Expand description

QUIC transport protocol implementation

QUIC is a modern transport protocol addressing shortcomings of TCP, such as head-of-line blocking, poor security, slow handshakes, and inefficient congestion control. This crate provides a portable userspace implementation. It @@ -30,5 +30,5 @@ authority. If this is infeasible–for example, if servers are short-lived or no with a domain name–then as with TLS, self-signed certificates can be used to provide encryption alone.

Re-exports§

pub use rustls;
pub use udp;

Modules§

congestion
Logic for controlling the rate at which data is sent
crypto
Traits and implementations for the QUIC cryptography protocol

Structs§

Accept
Future produced by Endpoint::accept
AcceptBi
Future produced by Connection::accept_bi
AcceptUni
Future produced by Connection::accept_uni
AckFrequencyConfig
Parameters for controlling the peer’s acknowledgement frequency
ApplicationClose
Reason given by an application for closing the connection
BloomTokenLog
Bloom filter-based TokenLog
Chunk
A chunk of data from the receive stream
ClientConfig
Configuration for outgoing connections
ClosedStream
Error indicating that a stream has not been opened or has already been finished or reset
Connecting
In-progress connection attempt future
Connection
A QUIC connection.
ConnectionClose
Reason given by the transport for closing the connection
ConnectionId
Protocol-level identifier for a connection.
ConnectionStats
Connection statistics
Endpoint
A QUIC endpoint.
EndpointConfig
Global configuration for the endpoint, affecting all connections
EndpointStats
Statistics on Endpoint activity
FrameStats
Number of frames transmitted or received of each frame type
IdleTimeout
Maximum duration of inactivity to accept before timing out the connection
Incoming
An incoming connection for which the server has not yet begun its part of the handshake
IncomingFuture
Basic adapter to let Incoming be await-ed like a Connecting
MtuDiscoveryConfig
Parameters governing MTU discovery.
NoneTokenLog
Null implementation of TokenLog, which never accepts tokens
NoneTokenStore
Null implementation of TokenStore, which does not store any tokens
OnClosed
Future returned by Connection::on_closed
OpenBi
Future produced by Connection::open_bi
OpenPath
Future produced by crate::Connection::open_path
OpenUni
Future produced by Connection::open_uni
Path
An open (Multi)Path
PathId
Id representing different paths when using multipath extension
PathStats
Statistics related to a transmission path
QlogConfig
Configuration for qlog trace logging.
QlogFileFactory
Enables writing qlog traces to a directory.
ReadDatagram
Future produced by Connection::read_datagram
RecvStream
A stream that can only be used to receive data
RetryError
Error for attempting to retry an Incoming which already bears a token from a previous retry
SendDatagram
Future produced by Connection::send_datagram_wait
SendStream
A stream that can only be used to send data
ServerConfig
Parameters governing incoming connections
SmolRuntime
A Quinn runtime for smol
StdSystemTime
Default implementation of TimeSource
StreamId
Identifier for a stream within a particular connection
TokenMemoryCache
TokenStore implementation that stores up to N tokens per server name for up to a -limited number of server names, in-memory
TokenReuseError
Error for when a validation token may have been reused
TokioRuntime
A Quinn runtime for Tokio
Transmit
An outgoing packet
TransportConfig
Parameters governing the core QUIC state machine
TransportErrorCode
Transport-level error code
UdpStats
Statistics about UDP datagrams transmitted or received on a connection
UnorderedRecvStream
A stream that can be used to receive data out-of-order.
ValidationTokenConfig
Configuration for sending and handling validation tokens in incoming connections
VarInt
An integer less than 2^62
VarIntBoundsExceeded
Error returned when constructing a VarInt from a value >= 2^62
WeakConnectionHandle
A handle to some connection internals, use with care.
Written
Indicates how many bytes and chunks had been transferred in a write operation
ZeroRttAccepted
Future that completes when a connection is fully established

Enums§

ConfigError
Errors in the configuration of an endpoint
ConnectError
Errors in the parameters being used to create a new connection
ConnectionError
Reasons why a connection might be lost
Dir
Whether a stream communicates data in both directions or only from the initiator
EcnCodepoint
Explicit congestion notification codepoint
FrameType
A QUIC frame type
ReadError
Errors that arise from reading from a stream.
ReadExactError
Errors that arise from reading from a stream.
ReadToEndError
Errors from RecvStream::read_to_end
ResetError
Errors that arise while waiting for a stream to be reset
SendDatagramError
Errors that can arise when sending a datagram
Side
Whether an endpoint was the initiator of a connection
StoppedError
Errors that arise while monitoring for a send stream stop from the peer
WriteError
Errors that arise from writing to a stream

Traits§

AsyncTimer
Abstract implementation of an async timer for runtime independence
AsyncUdpSocket
Abstract implementation of a UDP socket for runtime independence
ConnectionIdGenerator
Generates connection IDs for incoming connections
QlogFactory
Constructs a QlogConfig for individual connections.
Runtime
Abstracts I/O and timer operations for runtime independence
TimeSource
Object to get current SystemTime
TokenLog
Responsible for limiting clients’ ability to reuse validation tokens
TokenStore
Responsible for storing validation tokens received from servers and retrieving them for use in +limited number of server names, in-memory
TokenReuseError
Error for when a validation token may have been reused
TokioRuntime
A Quinn runtime for Tokio
Transmit
An outgoing packet
TransportConfig
Parameters governing the core QUIC state machine
TransportErrorCode
Transport-level error code
UdpStats
Statistics about UDP datagrams transmitted or received on a connection
UnorderedRecvStream
A stream that can be used to receive data out-of-order.
ValidationTokenConfig
Configuration for sending and handling validation tokens in incoming connections
VarInt
An integer less than 2^62
VarIntBoundsExceeded
Error returned when constructing a VarInt from a value >= 2^62
WeakConnectionHandle
A handle to some connection internals, use with care.
Written
Indicates how many bytes and chunks had been transferred in a write operation
ZeroRttAccepted
Future that completes when a connection is fully established

Enums§

ConfigError
Errors in the configuration of an endpoint
ConnectError
Errors in the parameters being used to create a new connection
ConnectionError
Reasons why a connection might be lost
Dir
Whether a stream communicates data in both directions or only from the initiator
EcnCodepoint
Explicit congestion notification codepoint
FrameType
ReadError
Errors that arise from reading from a stream.
ReadExactError
Errors that arise from reading from a stream.
ReadToEndError
Errors from RecvStream::read_to_end
ResetError
Errors that arise while waiting for a stream to be reset
SendDatagramError
Errors that can arise when sending a datagram
Side
Whether an endpoint was the initiator of a connection
StoppedError
Errors that arise while monitoring for a send stream stop from the peer
WriteError
Errors that arise from writing to a stream

Traits§

AsyncTimer
Abstract implementation of an async timer for runtime independence
AsyncUdpSocket
Abstract implementation of a UDP socket for runtime independence
ConnectionIdGenerator
Generates connection IDs for incoming connections
QlogFactory
Constructs a QlogConfig for individual connections.
Runtime
Abstracts I/O and timer operations for runtime independence
TimeSource
Object to get current SystemTime
TokenLog
Responsible for limiting clients’ ability to reuse validation tokens
TokenStore
Responsible for storing validation tokens received from servers and retrieving them for use in subsequent connections
UdpSender
An object for asynchronously writing to an associated AsyncUdpSocket.

Functions§

default_runtime
Automatically select an appropriate runtime from those enabled at compile time
\ No newline at end of file diff --git a/pr/255/docs/iroh_quinn/struct.Accept.html b/pr/255/docs/iroh_quinn/struct.Accept.html index 65581f2d2..6e17e11a0 100644 --- a/pr/255/docs/iroh_quinn/struct.Accept.html +++ b/pr/255/docs/iroh_quinn/struct.Accept.html @@ -1,4 +1,4 @@ -Accept in iroh_quinn - Rust

Accept

Struct Accept 

Source
pub struct Accept<'a> { /* private fields */ }
Expand description

Future produced by Endpoint::accept

+Accept in iroh_quinn - Rust

Accept

Struct Accept 

Source
pub struct Accept<'a> { /* private fields */ }
Expand description

Future produced by Endpoint::accept

Trait Implementations§

Source§

impl Future for Accept<'_>

Source§

type Output = Option<Incoming>

The type of value produced on completion.
Source§

fn poll(self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Self::Output>

Attempts to resolve the future to a final value, registering the current task for wakeup if the value is not yet available. Read more
Source§

impl<'__pin, 'a> Unpin for Accept<'a>
where PinnedFieldsOf<__Origin<'__pin, 'a>>: Unpin,

Auto Trait Implementations§

§

impl<'a> !Freeze for Accept<'a>

§

impl<'a> !RefUnwindSafe for Accept<'a>

§

impl<'a> Send for Accept<'a>

§

impl<'a> Sync for Accept<'a>

§

impl<'a> !UnwindSafe for Accept<'a>

Blanket Implementations§

Source§

impl<T> Any for T
where diff --git a/pr/255/docs/iroh_quinn/struct.AcceptBi.html b/pr/255/docs/iroh_quinn/struct.AcceptBi.html index c8b3e6379..164203db4 100644 --- a/pr/255/docs/iroh_quinn/struct.AcceptBi.html +++ b/pr/255/docs/iroh_quinn/struct.AcceptBi.html @@ -1,4 +1,4 @@ -AcceptBi in iroh_quinn - Rust

AcceptBi

Struct AcceptBi 

Source
pub struct AcceptBi<'a> { /* private fields */ }
Expand description

Future produced by Connection::accept_bi

+AcceptBi in iroh_quinn - Rust

AcceptBi

Struct AcceptBi 

Source
pub struct AcceptBi<'a> { /* private fields */ }
Expand description

Future produced by Connection::accept_bi

Trait Implementations§

Source§

impl Future for AcceptBi<'_>

Source§

type Output = Result<(SendStream, RecvStream), ConnectionError>

The type of value produced on completion.
Source§

fn poll(self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Self::Output>

Attempts to resolve the future to a final value, registering the current task for wakeup if the value is not yet available. Read more
Source§

impl<'__pin, 'a> Unpin for AcceptBi<'a>
where PinnedFieldsOf<__Origin<'__pin, 'a>>: Unpin,

Auto Trait Implementations§

§

impl<'a> !Freeze for AcceptBi<'a>

§

impl<'a> !RefUnwindSafe for AcceptBi<'a>

§

impl<'a> Send for AcceptBi<'a>

§

impl<'a> Sync for AcceptBi<'a>

§

impl<'a> !UnwindSafe for AcceptBi<'a>

Blanket Implementations§

Source§

impl<T> Any for T
where diff --git a/pr/255/docs/iroh_quinn/struct.AcceptUni.html b/pr/255/docs/iroh_quinn/struct.AcceptUni.html index f072fa9f0..f4132294f 100644 --- a/pr/255/docs/iroh_quinn/struct.AcceptUni.html +++ b/pr/255/docs/iroh_quinn/struct.AcceptUni.html @@ -1,4 +1,4 @@ -AcceptUni in iroh_quinn - Rust

AcceptUni

Struct AcceptUni 

Source
pub struct AcceptUni<'a> { /* private fields */ }
Expand description

Future produced by Connection::accept_uni

+AcceptUni in iroh_quinn - Rust

AcceptUni

Struct AcceptUni 

Source
pub struct AcceptUni<'a> { /* private fields */ }
Expand description

Future produced by Connection::accept_uni

Trait Implementations§

Source§

impl Future for AcceptUni<'_>

Source§

type Output = Result<RecvStream, ConnectionError>

The type of value produced on completion.
Source§

fn poll(self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Self::Output>

Attempts to resolve the future to a final value, registering the current task for wakeup if the value is not yet available. Read more
Source§

impl<'__pin, 'a> Unpin for AcceptUni<'a>
where PinnedFieldsOf<__Origin<'__pin, 'a>>: Unpin,

Auto Trait Implementations§

§

impl<'a> !Freeze for AcceptUni<'a>

§

impl<'a> !RefUnwindSafe for AcceptUni<'a>

§

impl<'a> Send for AcceptUni<'a>

§

impl<'a> Sync for AcceptUni<'a>

§

impl<'a> !UnwindSafe for AcceptUni<'a>

Blanket Implementations§

Source§

impl<T> Any for T
where diff --git a/pr/255/docs/iroh_quinn/struct.AckFrequencyConfig.html b/pr/255/docs/iroh_quinn/struct.AckFrequencyConfig.html index 39aea5364..a096d544b 100644 --- a/pr/255/docs/iroh_quinn/struct.AckFrequencyConfig.html +++ b/pr/255/docs/iroh_quinn/struct.AckFrequencyConfig.html @@ -1,4 +1,4 @@ -AckFrequencyConfig in iroh_quinn - Rust

AckFrequencyConfig

Struct AckFrequencyConfig 

Source
pub struct AckFrequencyConfig { /* private fields */ }
Expand description

Parameters for controlling the peer’s acknowledgement frequency

+AckFrequencyConfig in iroh_quinn - Rust

AckFrequencyConfig

Struct AckFrequencyConfig 

Source
pub struct AckFrequencyConfig { /* private fields */ }
Expand description

Parameters for controlling the peer’s acknowledgement frequency

The parameters provided in this config will be sent to the peer at the beginning of the connection, so it can take them into account when sending acknowledgements (see each parameter’s description for details on how it influences acknowledgement frequency).

diff --git a/pr/255/docs/iroh_quinn/struct.ApplicationClose.html b/pr/255/docs/iroh_quinn/struct.ApplicationClose.html index 659a173e2..c6ccb9e8e 100644 --- a/pr/255/docs/iroh_quinn/struct.ApplicationClose.html +++ b/pr/255/docs/iroh_quinn/struct.ApplicationClose.html @@ -1,11 +1,11 @@ -ApplicationClose in iroh_quinn - Rust

ApplicationClose

Struct ApplicationClose 

Source
pub struct ApplicationClose {
+ApplicationClose in iroh_quinn - Rust

ApplicationClose

Struct ApplicationClose 

Source
pub struct ApplicationClose {
     pub error_code: VarInt,
     pub reason: Bytes,
 }
Expand description

Reason given by an application for closing the connection

Fields§

§error_code: VarInt

Application-specific reason code

§reason: Bytes

Human-readable reason for the close

-

Trait Implementations§

Source§

impl Clone for ApplicationClose

Source§

fn clone(&self) -> ApplicationClose

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for ApplicationClose

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl Display for ApplicationClose

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl PartialEq for ApplicationClose

Source§

fn eq(&self, other: &ApplicationClose) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, -and should not be overridden without very good reason.
Source§

impl Eq for ApplicationClose

Source§

impl StructuralPartialEq for ApplicationClose

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where +

Trait Implementations§

Source§

impl Clone for ApplicationClose

Source§

fn clone(&self) -> ApplicationClose

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for ApplicationClose

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl Display for ApplicationClose

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl PartialEq for ApplicationClose

Source§

fn eq(&self, other: &ApplicationClose) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, +and should not be overridden without very good reason.
Source§

impl Eq for ApplicationClose

Source§

impl StructuralPartialEq for ApplicationClose

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where diff --git a/pr/255/docs/iroh_quinn/struct.BloomTokenLog.html b/pr/255/docs/iroh_quinn/struct.BloomTokenLog.html index 2d461c3a0..4a09daee7 100644 --- a/pr/255/docs/iroh_quinn/struct.BloomTokenLog.html +++ b/pr/255/docs/iroh_quinn/struct.BloomTokenLog.html @@ -1,4 +1,4 @@ -BloomTokenLog in iroh_quinn - Rust

BloomTokenLog

Struct BloomTokenLog 

Source
pub struct BloomTokenLog(/* private fields */);
Expand description

Bloom filter-based TokenLog

+BloomTokenLog in iroh_quinn - Rust

BloomTokenLog

Struct BloomTokenLog 

Source
pub struct BloomTokenLog(/* private fields */);
Expand description

Bloom filter-based TokenLog

Parameterizable over an approximate maximum number of bytes to allocate. Starts out by storing used tokens in a hash set. Once the hash set becomes too large, converts it to a bloom filter. This achieves a memory profile of linear growth with an upper bound.

diff --git a/pr/255/docs/iroh_quinn/struct.Chunk.html b/pr/255/docs/iroh_quinn/struct.Chunk.html index f06dfdff1..1c76cc6f1 100644 --- a/pr/255/docs/iroh_quinn/struct.Chunk.html +++ b/pr/255/docs/iroh_quinn/struct.Chunk.html @@ -1,4 +1,4 @@ -Chunk in iroh_quinn - Rust

Chunk

Struct Chunk 

Source
pub struct Chunk {
+Chunk in iroh_quinn - Rust

Chunk

Struct Chunk 

Source
pub struct Chunk {
     pub offset: u64,
     pub bytes: Bytes,
 }
Expand description

A chunk of data from the receive stream

diff --git a/pr/255/docs/iroh_quinn/struct.ClientConfig.html b/pr/255/docs/iroh_quinn/struct.ClientConfig.html index 8d2af413a..990a35909 100644 --- a/pr/255/docs/iroh_quinn/struct.ClientConfig.html +++ b/pr/255/docs/iroh_quinn/struct.ClientConfig.html @@ -1,4 +1,4 @@ -ClientConfig in iroh_quinn - Rust

ClientConfig

Struct ClientConfig 

Source
#[non_exhaustive]
pub struct ClientConfig { /* private fields */ }
Expand description

Configuration for outgoing connections

+ClientConfig in iroh_quinn - Rust

ClientConfig

Struct ClientConfig 

Source
#[non_exhaustive]
pub struct ClientConfig { /* private fields */ }
Expand description

Configuration for outgoing connections

Default values should be suitable for most internet applications.

Implementations§

Source§

impl ClientConfig

Source

pub fn new(crypto: Arc<dyn ClientConfig>) -> ClientConfig

Create a default config with a particular cryptographic config

Source

pub fn initial_dst_cid_provider( diff --git a/pr/255/docs/iroh_quinn/struct.ClosedStream.html b/pr/255/docs/iroh_quinn/struct.ClosedStream.html index a447d24e2..c9021984a 100644 --- a/pr/255/docs/iroh_quinn/struct.ClosedStream.html +++ b/pr/255/docs/iroh_quinn/struct.ClosedStream.html @@ -1,6 +1,6 @@ -ClosedStream in iroh_quinn - Rust

ClosedStream

Struct ClosedStream 

Source
pub struct ClosedStream { /* private fields */ }
Expand description

Error indicating that a stream has not been opened or has already been finished or reset

-

Trait Implementations§

Source§

impl Clone for ClosedStream

Source§

fn clone(&self) -> ClosedStream

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for ClosedStream

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl Default for ClosedStream

Source§

fn default() -> ClosedStream

Returns the “default value” for a type. Read more
Source§

impl Display for ClosedStream

Source§

fn fmt(&self, __formatter: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl Error for ClosedStream

1.30.0 · Source§

fn source(&self) -> Option<&(dyn Error + 'static)>

Returns the lower-level source of this error, if any. Read more
1.0.0 · Source§

fn description(&self) -> &str

👎Deprecated since 1.42.0: use the Display impl or to_string()
1.0.0 · Source§

fn cause(&self) -> Option<&dyn Error>

👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
Source§

fn provide<'a>(&'a self, request: &mut Request<'a>)

🔬This is a nightly-only experimental API. (error_generic_member_access)
Provides type-based access to context intended for error reports. Read more
Source§

impl From<ClosedStream> for WriteError

Source§

fn from(_: ClosedStream) -> Self

Converts to this type from the input type.
Source§

impl PartialEq for ClosedStream

Source§

fn eq(&self, other: &ClosedStream) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, -and should not be overridden without very good reason.
Source§

impl Eq for ClosedStream

Source§

impl StructuralPartialEq for ClosedStream

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where +ClosedStream in iroh_quinn - Rust

ClosedStream

Struct ClosedStream 

Source
pub struct ClosedStream { /* private fields */ }
Expand description

Error indicating that a stream has not been opened or has already been finished or reset

+

Trait Implementations§

Source§

impl Clone for ClosedStream

Source§

fn clone(&self) -> ClosedStream

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for ClosedStream

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl Default for ClosedStream

Source§

fn default() -> ClosedStream

Returns the “default value” for a type. Read more
Source§

impl Display for ClosedStream

Source§

fn fmt(&self, __formatter: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl Error for ClosedStream

1.30.0 · Source§

fn source(&self) -> Option<&(dyn Error + 'static)>

Returns the lower-level source of this error, if any. Read more
1.0.0 · Source§

fn description(&self) -> &str

👎Deprecated since 1.42.0: use the Display impl or to_string()
1.0.0 · Source§

fn cause(&self) -> Option<&dyn Error>

👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
Source§

fn provide<'a>(&'a self, request: &mut Request<'a>)

🔬This is a nightly-only experimental API. (error_generic_member_access)
Provides type-based access to context intended for error reports. Read more
Source§

impl From<ClosedStream> for WriteError

Source§

fn from(_: ClosedStream) -> Self

Converts to this type from the input type.
Source§

impl PartialEq for ClosedStream

Source§

fn eq(&self, other: &ClosedStream) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, +and should not be overridden without very good reason.
Source§

impl Eq for ClosedStream

Source§

impl StructuralPartialEq for ClosedStream

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where diff --git a/pr/255/docs/iroh_quinn/struct.Connecting.html b/pr/255/docs/iroh_quinn/struct.Connecting.html index 781fb0b2f..22768cf5c 100644 --- a/pr/255/docs/iroh_quinn/struct.Connecting.html +++ b/pr/255/docs/iroh_quinn/struct.Connecting.html @@ -1,4 +1,4 @@ -Connecting in iroh_quinn - Rust

Connecting

Struct Connecting 

Source
pub struct Connecting { /* private fields */ }
Expand description

In-progress connection attempt future

+Connecting in iroh_quinn - Rust

Connecting

Struct Connecting 

Source
pub struct Connecting { /* private fields */ }
Expand description

In-progress connection attempt future

Implementations§

Source§

impl Connecting

Source

pub fn into_0rtt(self) -> Result<(Connection, ZeroRttAccepted), Self>

Convert into a 0-RTT or 0.5-RTT connection at the cost of weakened security

Returns Ok immediately if the local endpoint is able to attempt sending 0/0.5-RTT data. If so, the returned Connection can be used to send application data without waiting for diff --git a/pr/255/docs/iroh_quinn/struct.Connection.html b/pr/255/docs/iroh_quinn/struct.Connection.html index d485e59b1..a6a37f960 100644 --- a/pr/255/docs/iroh_quinn/struct.Connection.html +++ b/pr/255/docs/iroh_quinn/struct.Connection.html @@ -1,4 +1,4 @@ -Connection in iroh_quinn - Rust

Connection

Struct Connection 

Source
pub struct Connection(/* private fields */);
Expand description

A QUIC connection.

+Connection in iroh_quinn - Rust

Connection

Struct Connection 

Source
pub struct Connection(/* private fields */);
Expand description

A QUIC connection.

If all references to a connection (including every clone of the Connection handle, streams of incoming streams, and the various stream types) have been dropped, then the connection will be automatically closed with an error_code of 0 and an empty reason. You can also close the diff --git a/pr/255/docs/iroh_quinn/struct.ConnectionClose.html b/pr/255/docs/iroh_quinn/struct.ConnectionClose.html index a71a99f42..babfc951e 100644 --- a/pr/255/docs/iroh_quinn/struct.ConnectionClose.html +++ b/pr/255/docs/iroh_quinn/struct.ConnectionClose.html @@ -1,4 +1,4 @@ -ConnectionClose in iroh_quinn - Rust

ConnectionClose

Struct ConnectionClose 

Source
pub struct ConnectionClose {
+ConnectionClose in iroh_quinn - Rust

ConnectionClose

Struct ConnectionClose 

Source
pub struct ConnectionClose {
     pub error_code: Code,
     pub frame_type: MaybeFrame,
     pub reason: Bytes,
@@ -6,8 +6,8 @@
 

Fields§

§error_code: Code

Class of error as encoded in the specification

§frame_type: MaybeFrame

Type of frame that caused the close

§reason: Bytes

Human-readable reason for the close

-

Trait Implementations§

Source§

impl Clone for ConnectionClose

Source§

fn clone(&self) -> ConnectionClose

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for ConnectionClose

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl Display for ConnectionClose

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl From<Error> for ConnectionClose

Source§

fn from(x: Error) -> ConnectionClose

Converts to this type from the input type.
Source§

impl PartialEq for ConnectionClose

Source§

fn eq(&self, other: &ConnectionClose) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, -and should not be overridden without very good reason.
Source§

impl Eq for ConnectionClose

Source§

impl StructuralPartialEq for ConnectionClose

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where +

Trait Implementations§

Source§

impl Clone for ConnectionClose

Source§

fn clone(&self) -> ConnectionClose

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for ConnectionClose

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl Display for ConnectionClose

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl From<Error> for ConnectionClose

Source§

fn from(x: Error) -> ConnectionClose

Converts to this type from the input type.
Source§

impl PartialEq for ConnectionClose

Source§

fn eq(&self, other: &ConnectionClose) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, +and should not be overridden without very good reason.
Source§

impl Eq for ConnectionClose

Source§

impl StructuralPartialEq for ConnectionClose

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where diff --git a/pr/255/docs/iroh_quinn/struct.ConnectionId.html b/pr/255/docs/iroh_quinn/struct.ConnectionId.html index 75d6fba72..d2cf719fe 100644 --- a/pr/255/docs/iroh_quinn/struct.ConnectionId.html +++ b/pr/255/docs/iroh_quinn/struct.ConnectionId.html @@ -1,4 +1,4 @@ -ConnectionId in iroh_quinn - Rust

ConnectionId

Struct ConnectionId 

Source
pub struct ConnectionId { /* private fields */ }
Expand description

Protocol-level identifier for a connection.

+ConnectionId in iroh_quinn - Rust

ConnectionId

Struct ConnectionId 

Source
pub struct ConnectionId { /* private fields */ }
Expand description

Protocol-level identifier for a connection.

Mainly useful for identifying this connection’s packets on the wire with tools like Wireshark.

Implementations§

Source§

impl ConnectionId

Source

pub fn new(bytes: &[u8]) -> ConnectionId

Construct cid from byte array

Source

pub fn from_buf(buf: &mut (impl Buf + ?Sized), len: usize) -> ConnectionId

Constructs cid by reading len bytes from a Buf

diff --git a/pr/255/docs/iroh_quinn/struct.ConnectionStats.html b/pr/255/docs/iroh_quinn/struct.ConnectionStats.html index 6088bddd3..fc80eb173 100644 --- a/pr/255/docs/iroh_quinn/struct.ConnectionStats.html +++ b/pr/255/docs/iroh_quinn/struct.ConnectionStats.html @@ -1,4 +1,4 @@ -ConnectionStats in iroh_quinn - Rust

ConnectionStats

Struct ConnectionStats 

Source
#[non_exhaustive]
pub struct ConnectionStats { +ConnectionStats in iroh_quinn - Rust

ConnectionStats

Struct ConnectionStats 

Source
#[non_exhaustive]
pub struct ConnectionStats { pub udp_tx: UdpStats, pub udp_rx: UdpStats, pub frame_tx: FrameStats, diff --git a/pr/255/docs/iroh_quinn/struct.Endpoint.html b/pr/255/docs/iroh_quinn/struct.Endpoint.html index 3f81be0ef..df16aa143 100644 --- a/pr/255/docs/iroh_quinn/struct.Endpoint.html +++ b/pr/255/docs/iroh_quinn/struct.Endpoint.html @@ -1,4 +1,4 @@ -Endpoint in iroh_quinn - Rust

Endpoint

Struct Endpoint 

Source
pub struct Endpoint { /* private fields */ }
Expand description

A QUIC endpoint.

+Endpoint in iroh_quinn - Rust

Endpoint

Struct Endpoint 

Source
pub struct Endpoint { /* private fields */ }
Expand description

A QUIC endpoint.

An endpoint corresponds to a single UDP socket, may host many connections, and may act as both client and server for different connections.

May be cloned to obtain another handle to the same endpoint.

diff --git a/pr/255/docs/iroh_quinn/struct.EndpointConfig.html b/pr/255/docs/iroh_quinn/struct.EndpointConfig.html index 8264b2983..81565c343 100644 --- a/pr/255/docs/iroh_quinn/struct.EndpointConfig.html +++ b/pr/255/docs/iroh_quinn/struct.EndpointConfig.html @@ -1,4 +1,4 @@ -EndpointConfig in iroh_quinn - Rust

EndpointConfig

Struct EndpointConfig 

Source
pub struct EndpointConfig { /* private fields */ }
Expand description

Global configuration for the endpoint, affecting all connections

+EndpointConfig in iroh_quinn - Rust

EndpointConfig

Struct EndpointConfig 

Source
pub struct EndpointConfig { /* private fields */ }
Expand description

Global configuration for the endpoint, affecting all connections

Default values should be suitable for most internet applications.

Implementations§

Source§

impl EndpointConfig

Source

pub fn new(reset_key: Arc<dyn HmacKey>) -> EndpointConfig

Create a default config with a particular reset_key

Source

pub fn cid_generator<F>(&mut self, factory: F) -> &mut EndpointConfig
where diff --git a/pr/255/docs/iroh_quinn/struct.EndpointStats.html b/pr/255/docs/iroh_quinn/struct.EndpointStats.html index f5c80c9c9..4500b994a 100644 --- a/pr/255/docs/iroh_quinn/struct.EndpointStats.html +++ b/pr/255/docs/iroh_quinn/struct.EndpointStats.html @@ -1,4 +1,4 @@ -EndpointStats in iroh_quinn - Rust

EndpointStats

Struct EndpointStats 

Source
#[non_exhaustive]
pub struct EndpointStats { +EndpointStats in iroh_quinn - Rust

EndpointStats

Struct EndpointStats 

Source
#[non_exhaustive]
pub struct EndpointStats { pub accepted_handshakes: u64, pub outgoing_handshakes: u64, pub refused_handshakes: u64, diff --git a/pr/255/docs/iroh_quinn/struct.FrameStats.html b/pr/255/docs/iroh_quinn/struct.FrameStats.html index b6fb3da55..a3dea813e 100644 --- a/pr/255/docs/iroh_quinn/struct.FrameStats.html +++ b/pr/255/docs/iroh_quinn/struct.FrameStats.html @@ -1,4 +1,4 @@ -FrameStats in iroh_quinn - Rust

FrameStats

Struct FrameStats 

Source
#[non_exhaustive]
pub struct FrameStats {
Show 37 fields +FrameStats in iroh_quinn - Rust

FrameStats

Struct FrameStats 

Source
#[non_exhaustive]
pub struct FrameStats {
Show 37 fields pub acks: u64, pub path_acks: u64, pub ack_frequency: u64, diff --git a/pr/255/docs/iroh_quinn/struct.IdleTimeout.html b/pr/255/docs/iroh_quinn/struct.IdleTimeout.html index cb731c528..f756e0670 100644 --- a/pr/255/docs/iroh_quinn/struct.IdleTimeout.html +++ b/pr/255/docs/iroh_quinn/struct.IdleTimeout.html @@ -1,4 +1,4 @@ -IdleTimeout in iroh_quinn - Rust

IdleTimeout

Struct IdleTimeout 

Source
pub struct IdleTimeout(/* private fields */);
Expand description

Maximum duration of inactivity to accept before timing out the connection

+IdleTimeout in iroh_quinn - Rust

IdleTimeout

Struct IdleTimeout 

Source
pub struct IdleTimeout(/* private fields */);
Expand description

Maximum duration of inactivity to accept before timing out the connection

This wraps an underlying VarInt, representing the duration in milliseconds. Values can be constructed by converting directly from VarInt, or using TryFrom<Duration>.

diff --git a/pr/255/docs/iroh_quinn/struct.Incoming.html b/pr/255/docs/iroh_quinn/struct.Incoming.html index 107f18bf7..88309d428 100644 --- a/pr/255/docs/iroh_quinn/struct.Incoming.html +++ b/pr/255/docs/iroh_quinn/struct.Incoming.html @@ -1,4 +1,4 @@ -Incoming in iroh_quinn - Rust

Incoming

Struct Incoming 

Source
pub struct Incoming(/* private fields */);
Expand description

An incoming connection for which the server has not yet begun its part of the handshake

+Incoming in iroh_quinn - Rust

Incoming

Struct Incoming 

Source
pub struct Incoming(/* private fields */);
Expand description

An incoming connection for which the server has not yet begun its part of the handshake

Implementations§

Source§

impl Incoming

Source

pub fn accept(self) -> Result<Connecting, ConnectionError>

Attempt to accept this incoming connection (an error may still occur)

Source

pub fn accept_with( self, diff --git a/pr/255/docs/iroh_quinn/struct.IncomingFuture.html b/pr/255/docs/iroh_quinn/struct.IncomingFuture.html index 2a9b89fab..ee5297e45 100644 --- a/pr/255/docs/iroh_quinn/struct.IncomingFuture.html +++ b/pr/255/docs/iroh_quinn/struct.IncomingFuture.html @@ -1,4 +1,4 @@ -IncomingFuture in iroh_quinn - Rust

IncomingFuture

Struct IncomingFuture 

Source
pub struct IncomingFuture(/* private fields */);
Expand description

Basic adapter to let Incoming be await-ed like a Connecting

+IncomingFuture in iroh_quinn - Rust

IncomingFuture

Struct IncomingFuture 

Source
pub struct IncomingFuture(/* private fields */);
Expand description

Basic adapter to let Incoming be await-ed like a Connecting

Trait Implementations§

Source§

impl Debug for IncomingFuture

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Future for IncomingFuture

Source§

type Output = Result<Connection, ConnectionError>

The type of value produced on completion.
Source§

fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>

Attempts to resolve the future to a final value, registering the current task for wakeup if the value is not yet available. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where diff --git a/pr/255/docs/iroh_quinn/struct.MtuDiscoveryConfig.html b/pr/255/docs/iroh_quinn/struct.MtuDiscoveryConfig.html index a4ab595b0..5d953b6cb 100644 --- a/pr/255/docs/iroh_quinn/struct.MtuDiscoveryConfig.html +++ b/pr/255/docs/iroh_quinn/struct.MtuDiscoveryConfig.html @@ -1,4 +1,4 @@ -MtuDiscoveryConfig in iroh_quinn - Rust

MtuDiscoveryConfig

Struct MtuDiscoveryConfig 

Source
pub struct MtuDiscoveryConfig { /* private fields */ }
Expand description

Parameters governing MTU discovery.

+MtuDiscoveryConfig in iroh_quinn - Rust

MtuDiscoveryConfig

Struct MtuDiscoveryConfig 

Source
pub struct MtuDiscoveryConfig { /* private fields */ }
Expand description

Parameters governing MTU discovery.

§The why of MTU discovery

By design, QUIC ensures during the handshake that the network path between the client and the server is able to transmit unfragmented UDP packets with a body of 1200 bytes. In other words, diff --git a/pr/255/docs/iroh_quinn/struct.NoneTokenLog.html b/pr/255/docs/iroh_quinn/struct.NoneTokenLog.html index 9d0e0a661..8ba483763 100644 --- a/pr/255/docs/iroh_quinn/struct.NoneTokenLog.html +++ b/pr/255/docs/iroh_quinn/struct.NoneTokenLog.html @@ -1,4 +1,4 @@ -NoneTokenLog in iroh_quinn - Rust

NoneTokenLog

Struct NoneTokenLog 

Source
pub struct NoneTokenLog;
Expand description

Null implementation of TokenLog, which never accepts tokens

+NoneTokenLog in iroh_quinn - Rust

NoneTokenLog

Struct NoneTokenLog 

Source
pub struct NoneTokenLog;
Expand description

Null implementation of TokenLog, which never accepts tokens

Trait Implementations§

Source§

impl TokenLog for NoneTokenLog

Source§

fn check_and_insert( &self, _: u128, diff --git a/pr/255/docs/iroh_quinn/struct.NoneTokenStore.html b/pr/255/docs/iroh_quinn/struct.NoneTokenStore.html index 2fd9c75f9..4f62b95bd 100644 --- a/pr/255/docs/iroh_quinn/struct.NoneTokenStore.html +++ b/pr/255/docs/iroh_quinn/struct.NoneTokenStore.html @@ -1,4 +1,4 @@ -NoneTokenStore in iroh_quinn - Rust

NoneTokenStore

Struct NoneTokenStore 

Source
pub struct NoneTokenStore;
Expand description

Null implementation of TokenStore, which does not store any tokens

+NoneTokenStore in iroh_quinn - Rust

NoneTokenStore

Struct NoneTokenStore 

Source
pub struct NoneTokenStore;
Expand description

Null implementation of TokenStore, which does not store any tokens

Trait Implementations§

Source§

impl TokenStore for NoneTokenStore

Source§

fn insert(&self, _: &str, _: Bytes)

Potentially store a token for later one-time use Read more
Source§

fn take(&self, _: &str) -> Option<Bytes>

Try to find and take a token that was stored with the given server name Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where diff --git a/pr/255/docs/iroh_quinn/struct.OnClosed.html b/pr/255/docs/iroh_quinn/struct.OnClosed.html index b59cb94ea..e1f68219e 100644 --- a/pr/255/docs/iroh_quinn/struct.OnClosed.html +++ b/pr/255/docs/iroh_quinn/struct.OnClosed.html @@ -1,4 +1,4 @@ -OnClosed in iroh_quinn - Rust

OnClosed

Struct OnClosed 

Source
pub struct OnClosed { /* private fields */ }
Expand description

Future returned by Connection::on_closed

+OnClosed in iroh_quinn - Rust

OnClosed

Struct OnClosed 

Source
pub struct OnClosed { /* private fields */ }
Expand description

Future returned by Connection::on_closed

Resolves to a tuple of (ConnectionError, ConnectionStats).

Trait Implementations§

Source§

impl Drop for OnClosed

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more
Source§

impl Future for OnClosed

Source§

type Output = (ConnectionError, ConnectionStats)

The type of value produced on completion.
Source§

fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>

Attempts to resolve the future to a final value, registering the current task for wakeup if the value is not yet available. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where diff --git a/pr/255/docs/iroh_quinn/struct.OpenBi.html b/pr/255/docs/iroh_quinn/struct.OpenBi.html index 5f5d6ad41..ae4e56427 100644 --- a/pr/255/docs/iroh_quinn/struct.OpenBi.html +++ b/pr/255/docs/iroh_quinn/struct.OpenBi.html @@ -1,4 +1,4 @@ -OpenBi in iroh_quinn - Rust

OpenBi

Struct OpenBi 

Source
pub struct OpenBi<'a> { /* private fields */ }
Expand description

Future produced by Connection::open_bi

+OpenBi in iroh_quinn - Rust

OpenBi

Struct OpenBi 

Source
pub struct OpenBi<'a> { /* private fields */ }
Expand description

Future produced by Connection::open_bi

Trait Implementations§

Source§

impl Future for OpenBi<'_>

Source§

type Output = Result<(SendStream, RecvStream), ConnectionError>

The type of value produced on completion.
Source§

fn poll(self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Self::Output>

Attempts to resolve the future to a final value, registering the current task for wakeup if the value is not yet available. Read more
Source§

impl<'__pin, 'a> Unpin for OpenBi<'a>
where PinnedFieldsOf<__Origin<'__pin, 'a>>: Unpin,

Auto Trait Implementations§

§

impl<'a> !Freeze for OpenBi<'a>

§

impl<'a> !RefUnwindSafe for OpenBi<'a>

§

impl<'a> Send for OpenBi<'a>

§

impl<'a> Sync for OpenBi<'a>

§

impl<'a> !UnwindSafe for OpenBi<'a>

Blanket Implementations§

Source§

impl<T> Any for T
where diff --git a/pr/255/docs/iroh_quinn/struct.OpenPath.html b/pr/255/docs/iroh_quinn/struct.OpenPath.html index d78f1a3b4..8240f8a46 100644 --- a/pr/255/docs/iroh_quinn/struct.OpenPath.html +++ b/pr/255/docs/iroh_quinn/struct.OpenPath.html @@ -1,4 +1,4 @@ -OpenPath in iroh_quinn - Rust

OpenPath

Struct OpenPath 

Source
pub struct OpenPath(/* private fields */);
Expand description

Future produced by crate::Connection::open_path

+OpenPath in iroh_quinn - Rust

OpenPath

Struct OpenPath 

Source
pub struct OpenPath(/* private fields */);
Expand description

Future produced by crate::Connection::open_path

Implementations§

Source§

impl OpenPath

Source

pub fn path_id(&self) -> Option<PathId>

Returns the path ID of the new path being opened.

If an error occurred before a path ID was allocated, None is returned. In this case the future is ready and polling it will immediately yield the error.

diff --git a/pr/255/docs/iroh_quinn/struct.OpenUni.html b/pr/255/docs/iroh_quinn/struct.OpenUni.html index af61824b4..4b9cff2d9 100644 --- a/pr/255/docs/iroh_quinn/struct.OpenUni.html +++ b/pr/255/docs/iroh_quinn/struct.OpenUni.html @@ -1,4 +1,4 @@ -OpenUni in iroh_quinn - Rust

OpenUni

Struct OpenUni 

Source
pub struct OpenUni<'a> { /* private fields */ }
Expand description

Future produced by Connection::open_uni

+OpenUni in iroh_quinn - Rust

OpenUni

Struct OpenUni 

Source
pub struct OpenUni<'a> { /* private fields */ }
Expand description

Future produced by Connection::open_uni

Trait Implementations§

Source§

impl Future for OpenUni<'_>

Source§

type Output = Result<SendStream, ConnectionError>

The type of value produced on completion.
Source§

fn poll(self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Self::Output>

Attempts to resolve the future to a final value, registering the current task for wakeup if the value is not yet available. Read more
Source§

impl<'__pin, 'a> Unpin for OpenUni<'a>
where PinnedFieldsOf<__Origin<'__pin, 'a>>: Unpin,

Auto Trait Implementations§

§

impl<'a> !Freeze for OpenUni<'a>

§

impl<'a> !RefUnwindSafe for OpenUni<'a>

§

impl<'a> Send for OpenUni<'a>

§

impl<'a> Sync for OpenUni<'a>

§

impl<'a> !UnwindSafe for OpenUni<'a>

Blanket Implementations§

Source§

impl<T> Any for T
where diff --git a/pr/255/docs/iroh_quinn/struct.Path.html b/pr/255/docs/iroh_quinn/struct.Path.html index 7e9a721c2..5602610f3 100644 --- a/pr/255/docs/iroh_quinn/struct.Path.html +++ b/pr/255/docs/iroh_quinn/struct.Path.html @@ -1,4 +1,4 @@ -Path in iroh_quinn - Rust

Path

Struct Path 

Source
pub struct Path { /* private fields */ }
Expand description

An open (Multi)Path

+Path in iroh_quinn - Rust

Path

Struct Path 

Source
pub struct Path { /* private fields */ }
Expand description

An open (Multi)Path

Implementations§

Source§

impl Path

Source

pub fn id(&self) -> PathId

The PathId of this path.

Source

pub fn status(&self) -> Result<PathStatus, ClosedPath>

The current local PathStatus of this path.

Source

pub fn set_status(&self, status: PathStatus) -> Result<(), SetPathStatusError>

Sets the PathStatus of this path.

diff --git a/pr/255/docs/iroh_quinn/struct.PathId.html b/pr/255/docs/iroh_quinn/struct.PathId.html index 3a2767ea9..9c99d610e 100644 --- a/pr/255/docs/iroh_quinn/struct.PathId.html +++ b/pr/255/docs/iroh_quinn/struct.PathId.html @@ -1,4 +1,4 @@ -PathId in iroh_quinn - Rust

PathId

Struct PathId 

Source
pub struct PathId(/* private fields */);
Expand description

Id representing different paths when using multipath extension

+PathId in iroh_quinn - Rust

PathId

Struct PathId 

Source
pub struct PathId(/* private fields */);
Expand description

Id representing different paths when using multipath extension

Implementations§

Source§

impl PathId

Source

pub const MAX: PathId

The maximum path ID allowed.

Source

pub const ZERO: PathId

The 0 path id.

Source

pub fn saturating_add(self, rhs: impl Into<PathId>) -> PathId

Saturating integer addition. Computes self + rhs, saturating at the numeric bounds instead diff --git a/pr/255/docs/iroh_quinn/struct.PathStats.html b/pr/255/docs/iroh_quinn/struct.PathStats.html index 0726d2d4a..3a25ec205 100644 --- a/pr/255/docs/iroh_quinn/struct.PathStats.html +++ b/pr/255/docs/iroh_quinn/struct.PathStats.html @@ -1,4 +1,4 @@ -PathStats in iroh_quinn - Rust

PathStats

Struct PathStats 

Source
#[non_exhaustive]
pub struct PathStats { +PathStats in iroh_quinn - Rust

PathStats

Struct PathStats 

Source
#[non_exhaustive]
pub struct PathStats { pub rtt: Duration, pub cwnd: u64, pub congestion_events: u64, diff --git a/pr/255/docs/iroh_quinn/struct.QlogConfig.html b/pr/255/docs/iroh_quinn/struct.QlogConfig.html index 8c37642c3..025c5ad65 100644 --- a/pr/255/docs/iroh_quinn/struct.QlogConfig.html +++ b/pr/255/docs/iroh_quinn/struct.QlogConfig.html @@ -1,4 +1,4 @@ -QlogConfig in iroh_quinn - Rust

QlogConfig

Struct QlogConfig 

Source
pub struct QlogConfig { /* private fields */ }
Expand description

Configuration for qlog trace logging.

+QlogConfig in iroh_quinn - Rust

QlogConfig

Struct QlogConfig 

Source
pub struct QlogConfig { /* private fields */ }
Expand description

Configuration for qlog trace logging.

This struct is returned from QlogFactory::for_connection if qlog logging should be enabled for a connection. It allows to set metadata for the qlog trace.

The trace will be written to the provided writer in the [JSON-SEQ format] defined in the qlog spec.

diff --git a/pr/255/docs/iroh_quinn/struct.QlogFileFactory.html b/pr/255/docs/iroh_quinn/struct.QlogFileFactory.html index df1cdfe3c..607949e07 100644 --- a/pr/255/docs/iroh_quinn/struct.QlogFileFactory.html +++ b/pr/255/docs/iroh_quinn/struct.QlogFileFactory.html @@ -1,4 +1,4 @@ -QlogFileFactory in iroh_quinn - Rust

QlogFileFactory

Struct QlogFileFactory 

Source
pub struct QlogFileFactory { /* private fields */ }
Expand description

Enables writing qlog traces to a directory.

+QlogFileFactory in iroh_quinn - Rust

QlogFileFactory

Struct QlogFileFactory 

Source
pub struct QlogFileFactory { /* private fields */ }
Expand description

Enables writing qlog traces to a directory.

Implementations§

Source§

impl QlogFileFactory

Source

pub fn new(dir: PathBuf) -> QlogFileFactory

Creates a new qlog factory that writes files into the specified directory.

Source

pub fn from_env() -> QlogFileFactory

Creates a new qlog factory that writes files into QLOGDIR, if set.

If the environment variable QLOGDIR is set, qlog traces for all connections handled diff --git a/pr/255/docs/iroh_quinn/struct.ReadDatagram.html b/pr/255/docs/iroh_quinn/struct.ReadDatagram.html index 68960c5e7..f3500aab9 100644 --- a/pr/255/docs/iroh_quinn/struct.ReadDatagram.html +++ b/pr/255/docs/iroh_quinn/struct.ReadDatagram.html @@ -1,4 +1,4 @@ -ReadDatagram in iroh_quinn - Rust

ReadDatagram

Struct ReadDatagram 

Source
pub struct ReadDatagram<'a> { /* private fields */ }
Expand description

Future produced by Connection::read_datagram

+ReadDatagram in iroh_quinn - Rust

ReadDatagram

Struct ReadDatagram 

Source
pub struct ReadDatagram<'a> { /* private fields */ }
Expand description

Future produced by Connection::read_datagram

Trait Implementations§

Source§

impl Future for ReadDatagram<'_>

Source§

type Output = Result<Bytes, ConnectionError>

The type of value produced on completion.
Source§

fn poll(self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Self::Output>

Attempts to resolve the future to a final value, registering the current task for wakeup if the value is not yet available. Read more
Source§

impl<'__pin, 'a> Unpin for ReadDatagram<'a>
where PinnedFieldsOf<__Origin<'__pin, 'a>>: Unpin,

Auto Trait Implementations§

§

impl<'a> !Freeze for ReadDatagram<'a>

§

impl<'a> !RefUnwindSafe for ReadDatagram<'a>

§

impl<'a> Send for ReadDatagram<'a>

§

impl<'a> Sync for ReadDatagram<'a>

§

impl<'a> !UnwindSafe for ReadDatagram<'a>

Blanket Implementations§

Source§

impl<T> Any for T
where diff --git a/pr/255/docs/iroh_quinn/struct.RecvStream.html b/pr/255/docs/iroh_quinn/struct.RecvStream.html index 1476aa787..d6efb0816 100644 --- a/pr/255/docs/iroh_quinn/struct.RecvStream.html +++ b/pr/255/docs/iroh_quinn/struct.RecvStream.html @@ -1,4 +1,4 @@ -RecvStream in iroh_quinn - Rust

RecvStream

Struct RecvStream 

Source
pub struct RecvStream { /* private fields */ }
Expand description

A stream that can only be used to receive data

+RecvStream in iroh_quinn - Rust

RecvStream

Struct RecvStream 

Source
pub struct RecvStream { /* private fields */ }
Expand description

A stream that can only be used to receive data

stop(0) is implicitly called on drop unless:

  • A variant of ReadError has been yielded by a read call
  • diff --git a/pr/255/docs/iroh_quinn/struct.RetryError.html b/pr/255/docs/iroh_quinn/struct.RetryError.html index 1395a99c2..5e64e8828 100644 --- a/pr/255/docs/iroh_quinn/struct.RetryError.html +++ b/pr/255/docs/iroh_quinn/struct.RetryError.html @@ -1,4 +1,4 @@ -RetryError in iroh_quinn - Rust

    RetryError

    Struct RetryError 

    Source
    pub struct RetryError(/* private fields */);
    Expand description

    Error for attempting to retry an Incoming which already bears a token from a previous retry

    +RetryError in iroh_quinn - Rust

    RetryError

    Struct RetryError 

    Source
    pub struct RetryError(/* private fields */);
    Expand description

    Error for attempting to retry an Incoming which already bears a token from a previous retry

    Implementations§

    Trait Implementations§

    Source§

    impl Debug for RetryError

    Source§

    fn fmt(&self, f: &mut Formatter<'_>) -> Result

    Formats the value using the given formatter. Read more
    Source§

    impl Display for RetryError

    Source§

    fn fmt(&self, __formatter: &mut Formatter<'_>) -> Result

    Formats the value using the given formatter. Read more
    Source§

    impl Error for RetryError

    1.30.0 · Source§

    fn source(&self) -> Option<&(dyn Error + 'static)>

    Returns the lower-level source of this error, if any. Read more
    1.0.0 · Source§

    fn description(&self) -> &str

    👎Deprecated since 1.42.0: use the Display impl or to_string()
    1.0.0 · Source§

    fn cause(&self) -> Option<&dyn Error>

    👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
    Source§

    fn provide<'a>(&'a self, request: &mut Request<'a>)

    🔬This is a nightly-only experimental API. (error_generic_member_access)
    Provides type-based access to context intended for error reports. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Source§

    impl<T> Any for T
    where T: 'static + ?Sized,

    Source§

    fn type_id(&self) -> TypeId

    Gets the TypeId of self. Read more
    Source§

    impl<T> Borrow<T> for T
    where diff --git a/pr/255/docs/iroh_quinn/struct.SendDatagram.html b/pr/255/docs/iroh_quinn/struct.SendDatagram.html index 8addb6100..abc045cd9 100644 --- a/pr/255/docs/iroh_quinn/struct.SendDatagram.html +++ b/pr/255/docs/iroh_quinn/struct.SendDatagram.html @@ -1,4 +1,4 @@ -SendDatagram in iroh_quinn - Rust

    SendDatagram

    Struct SendDatagram 

    Source
    pub struct SendDatagram<'a> { /* private fields */ }
    Expand description

    Future produced by Connection::send_datagram_wait

    +SendDatagram in iroh_quinn - Rust

    SendDatagram

    Struct SendDatagram 

    Source
    pub struct SendDatagram<'a> { /* private fields */ }
    Expand description

    Future produced by Connection::send_datagram_wait

    Trait Implementations§

    Source§

    impl Future for SendDatagram<'_>

    Source§

    type Output = Result<(), SendDatagramError>

    The type of value produced on completion.
    Source§

    fn poll(self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Self::Output>

    Attempts to resolve the future to a final value, registering the current task for wakeup if the value is not yet available. Read more
    Source§

    impl<'__pin, 'a> Unpin for SendDatagram<'a>
    where PinnedFieldsOf<__Origin<'__pin, 'a>>: Unpin,

    Auto Trait Implementations§

    §

    impl<'a> !Freeze for SendDatagram<'a>

    §

    impl<'a> !RefUnwindSafe for SendDatagram<'a>

    §

    impl<'a> Send for SendDatagram<'a>

    §

    impl<'a> Sync for SendDatagram<'a>

    §

    impl<'a> !UnwindSafe for SendDatagram<'a>

    Blanket Implementations§

    Source§

    impl<T> Any for T
    where diff --git a/pr/255/docs/iroh_quinn/struct.SendStream.html b/pr/255/docs/iroh_quinn/struct.SendStream.html index 5baebf4ad..069c8def7 100644 --- a/pr/255/docs/iroh_quinn/struct.SendStream.html +++ b/pr/255/docs/iroh_quinn/struct.SendStream.html @@ -1,4 +1,4 @@ -SendStream in iroh_quinn - Rust

    SendStream

    Struct SendStream 

    Source
    pub struct SendStream { /* private fields */ }
    Expand description

    A stream that can only be used to send data

    +SendStream in iroh_quinn - Rust

    SendStream

    Struct SendStream 

    Source
    pub struct SendStream { /* private fields */ }
    Expand description

    A stream that can only be used to send data

    If dropped, streams that haven’t been explicitly reset() will be implicitly finish()ed, continuing to (re)transmit previously written data until it has been fully acknowledged or the connection is closed.

    diff --git a/pr/255/docs/iroh_quinn/struct.ServerConfig.html b/pr/255/docs/iroh_quinn/struct.ServerConfig.html index 502399a23..8a8e0c25c 100644 --- a/pr/255/docs/iroh_quinn/struct.ServerConfig.html +++ b/pr/255/docs/iroh_quinn/struct.ServerConfig.html @@ -1,4 +1,4 @@ -ServerConfig in iroh_quinn - Rust

    ServerConfig

    Struct ServerConfig 

    Source
    pub struct ServerConfig {
    +ServerConfig in iroh_quinn - Rust

    ServerConfig

    Struct ServerConfig 

    Source
    pub struct ServerConfig {
         pub transport: Arc<TransportConfig>,
         pub crypto: Arc<dyn ServerConfig>,
         pub validation_token: ValidationTokenConfig,
    diff --git a/pr/255/docs/iroh_quinn/struct.SmolRuntime.html b/pr/255/docs/iroh_quinn/struct.SmolRuntime.html
    index bd63cabd8..c4ba7ceee 100644
    --- a/pr/255/docs/iroh_quinn/struct.SmolRuntime.html
    +++ b/pr/255/docs/iroh_quinn/struct.SmolRuntime.html
    @@ -1,4 +1,4 @@
    -SmolRuntime in iroh_quinn - Rust

    SmolRuntime

    Struct SmolRuntime 

    Source
    pub struct SmolRuntime;
    Expand description

    A Quinn runtime for smol

    +SmolRuntime in iroh_quinn - Rust

    SmolRuntime

    Struct SmolRuntime 

    Source
    pub struct SmolRuntime;
    Expand description

    A Quinn runtime for smol

    Trait Implementations§

    Source§

    impl Debug for SmolRuntime

    Source§

    fn fmt(&self, f: &mut Formatter<'_>) -> Result

    Formats the value using the given formatter. Read more
    Source§

    impl Runtime for SmolRuntime

    Source§

    fn new_timer(&self, t: Instant) -> Pin<Box<dyn AsyncTimer>>

    Construct a timer that will expire at i
    Source§

    fn spawn(&self, future: Pin<Box<dyn Future<Output = ()> + Send>>)

    Drive future to completion in the background
    Source§

    fn wrap_udp_socket(&self, sock: UdpSocket) -> Result<Box<dyn AsyncUdpSocket>>

    Convert t into the socket type used by this runtime
    Source§

    fn now(&self) -> Instant

    Look up the current time Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Source§

    impl<T> Any for T
    where T: 'static + ?Sized,

    Source§

    fn type_id(&self) -> TypeId

    Gets the TypeId of self. Read more
    Source§

    impl<T> Borrow<T> for T
    where T: ?Sized,

    Source§

    fn borrow(&self) -> &T

    Immutably borrows from an owned value. Read more
    Source§

    impl<T> BorrowMut<T> for T
    where diff --git a/pr/255/docs/iroh_quinn/struct.StdSystemTime.html b/pr/255/docs/iroh_quinn/struct.StdSystemTime.html index b9fa366ad..601433e0b 100644 --- a/pr/255/docs/iroh_quinn/struct.StdSystemTime.html +++ b/pr/255/docs/iroh_quinn/struct.StdSystemTime.html @@ -1,4 +1,4 @@ -StdSystemTime in iroh_quinn - Rust

    StdSystemTime

    Struct StdSystemTime 

    Source
    pub struct StdSystemTime;
    Expand description

    Default implementation of TimeSource

    +StdSystemTime in iroh_quinn - Rust

    StdSystemTime

    Struct StdSystemTime 

    Source
    pub struct StdSystemTime;
    Expand description

    Default implementation of TimeSource

    Implements now by calling SystemTime::now().

    Trait Implementations§

    Source§

    impl TimeSource for StdSystemTime

    Source§

    fn now(&self) -> SystemTime

    Get SystemTime::now() or the mocked equivalent

    Auto Trait Implementations§

    Blanket Implementations§

    Source§

    impl<T> Any for T
    where T: 'static + ?Sized,

    Source§

    fn type_id(&self) -> TypeId

    Gets the TypeId of self. Read more
    Source§

    impl<T> Borrow<T> for T
    where diff --git a/pr/255/docs/iroh_quinn/struct.StreamId.html b/pr/255/docs/iroh_quinn/struct.StreamId.html index 3400cb891..7d288c046 100644 --- a/pr/255/docs/iroh_quinn/struct.StreamId.html +++ b/pr/255/docs/iroh_quinn/struct.StreamId.html @@ -1,4 +1,4 @@ -StreamId in iroh_quinn - Rust

    StreamId

    Struct StreamId 

    Source
    pub struct StreamId(/* private fields */);
    Expand description

    Identifier for a stream within a particular connection

    +StreamId in iroh_quinn - Rust

    StreamId

    Struct StreamId 

    Source
    pub struct StreamId(/* private fields */);
    Expand description

    Identifier for a stream within a particular connection

    Implementations§

    Source§

    impl StreamId

    Source

    pub fn new(initiator: Side, dir: Dir, index: u64) -> StreamId

    Create a new StreamId

    Source

    pub fn initiator(self) -> Side

    Which side of a connection initiated the stream

    Source

    pub fn dir(self) -> Dir

    Which directions data flows in

    diff --git a/pr/255/docs/iroh_quinn/struct.TokenMemoryCache.html b/pr/255/docs/iroh_quinn/struct.TokenMemoryCache.html index 1762bb976..2f9228fa9 100644 --- a/pr/255/docs/iroh_quinn/struct.TokenMemoryCache.html +++ b/pr/255/docs/iroh_quinn/struct.TokenMemoryCache.html @@ -1,4 +1,4 @@ -TokenMemoryCache in iroh_quinn - Rust

    TokenMemoryCache

    Struct TokenMemoryCache 

    Source
    pub struct TokenMemoryCache(/* private fields */);
    Expand description

    TokenStore implementation that stores up to N tokens per server name for up to a +TokenMemoryCache in iroh_quinn - Rust

    TokenMemoryCache

    Struct TokenMemoryCache 

    Source
    pub struct TokenMemoryCache(/* private fields */);
    Expand description

    TokenStore implementation that stores up to N tokens per server name for up to a limited number of server names, in-memory

    Implementations§

    Source§

    impl TokenMemoryCache

    Source

    pub fn new( max_server_names: u32, diff --git a/pr/255/docs/iroh_quinn/struct.TokenReuseError.html b/pr/255/docs/iroh_quinn/struct.TokenReuseError.html index c5aad2809..b2fb89c81 100644 --- a/pr/255/docs/iroh_quinn/struct.TokenReuseError.html +++ b/pr/255/docs/iroh_quinn/struct.TokenReuseError.html @@ -1,4 +1,4 @@ -TokenReuseError in iroh_quinn - Rust

    TokenReuseError

    Struct TokenReuseError 

    Source
    pub struct TokenReuseError;
    Expand description

    Error for when a validation token may have been reused

    +TokenReuseError in iroh_quinn - Rust

    TokenReuseError

    Struct TokenReuseError 

    Source
    pub struct TokenReuseError;
    Expand description

    Error for when a validation token may have been reused

    Auto Trait Implementations§

    Blanket Implementations§

    Source§

    impl<T> Any for T
    where T: 'static + ?Sized,

    Source§

    fn type_id(&self) -> TypeId

    Gets the TypeId of self. Read more
    Source§

    impl<T> Borrow<T> for T
    where T: ?Sized,

    Source§

    fn borrow(&self) -> &T

    Immutably borrows from an owned value. Read more
    Source§

    impl<T> BorrowMut<T> for T
    where diff --git a/pr/255/docs/iroh_quinn/struct.TokioRuntime.html b/pr/255/docs/iroh_quinn/struct.TokioRuntime.html index a82d38979..b651f8f86 100644 --- a/pr/255/docs/iroh_quinn/struct.TokioRuntime.html +++ b/pr/255/docs/iroh_quinn/struct.TokioRuntime.html @@ -1,4 +1,4 @@ -TokioRuntime in iroh_quinn - Rust

    TokioRuntime

    Struct TokioRuntime 

    Source
    pub struct TokioRuntime;
    Expand description

    A Quinn runtime for Tokio

    +TokioRuntime in iroh_quinn - Rust

    TokioRuntime

    Struct TokioRuntime 

    Source
    pub struct TokioRuntime;
    Expand description

    A Quinn runtime for Tokio

    Trait Implementations§

    Source§

    impl Debug for TokioRuntime

    Source§

    fn fmt(&self, f: &mut Formatter<'_>) -> Result

    Formats the value using the given formatter. Read more
    Source§

    impl Runtime for TokioRuntime

    Source§

    fn new_timer(&self, t: Instant) -> Pin<Box<dyn AsyncTimer>>

    Construct a timer that will expire at i
    Source§

    fn spawn(&self, future: Pin<Box<dyn Future<Output = ()> + Send>>)

    Drive future to completion in the background
    Source§

    fn wrap_udp_socket(&self, sock: UdpSocket) -> Result<Box<dyn AsyncUdpSocket>>

    Convert t into the socket type used by this runtime
    Source§

    fn now(&self) -> Instant

    Look up the current time Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Source§

    impl<T> Any for T
    where T: 'static + ?Sized,

    Source§

    fn type_id(&self) -> TypeId

    Gets the TypeId of self. Read more
    Source§

    impl<T> Borrow<T> for T
    where T: ?Sized,

    Source§

    fn borrow(&self) -> &T

    Immutably borrows from an owned value. Read more
    Source§

    impl<T> BorrowMut<T> for T
    where diff --git a/pr/255/docs/iroh_quinn/struct.Transmit.html b/pr/255/docs/iroh_quinn/struct.Transmit.html index 02c38b955..c36db78b0 100644 --- a/pr/255/docs/iroh_quinn/struct.Transmit.html +++ b/pr/255/docs/iroh_quinn/struct.Transmit.html @@ -1,4 +1,4 @@ -Transmit in iroh_quinn - Rust

    Transmit

    Struct Transmit 

    Source
    pub struct Transmit {
    +Transmit in iroh_quinn - Rust

    Transmit

    Struct Transmit 

    Source
    pub struct Transmit {
         pub destination: SocketAddr,
         pub ecn: Option<EcnCodepoint>,
         pub size: usize,
    diff --git a/pr/255/docs/iroh_quinn/struct.TransportConfig.html b/pr/255/docs/iroh_quinn/struct.TransportConfig.html
    index b62a74604..e312bb680 100644
    --- a/pr/255/docs/iroh_quinn/struct.TransportConfig.html
    +++ b/pr/255/docs/iroh_quinn/struct.TransportConfig.html
    @@ -1,4 +1,4 @@
    -TransportConfig in iroh_quinn - Rust

    TransportConfig

    Struct TransportConfig 

    Source
    pub struct TransportConfig { /* private fields */ }
    Expand description

    Parameters governing the core QUIC state machine

    +TransportConfig in iroh_quinn - Rust

    TransportConfig

    Struct TransportConfig 

    Source
    pub struct TransportConfig { /* private fields */ }
    Expand description

    Parameters governing the core QUIC state machine

    Default values should be suitable for most internet applications. Applications protocols which forbid remotely-initiated streams should set max_concurrent_bidi_streams and max_concurrent_uni_streams to zero.

    diff --git a/pr/255/docs/iroh_quinn/struct.TransportErrorCode.html b/pr/255/docs/iroh_quinn/struct.TransportErrorCode.html index c3a461bc6..e2880abec 100644 --- a/pr/255/docs/iroh_quinn/struct.TransportErrorCode.html +++ b/pr/255/docs/iroh_quinn/struct.TransportErrorCode.html @@ -1,4 +1,4 @@ -TransportErrorCode in iroh_quinn - Rust

    TransportErrorCode

    Struct TransportErrorCode 

    Source
    pub struct TransportErrorCode(/* private fields */);
    Expand description

    Transport-level error code

    +TransportErrorCode in iroh_quinn - Rust

    TransportErrorCode

    Struct TransportErrorCode 

    Source
    pub struct TransportErrorCode(/* private fields */);
    Expand description

    Transport-level error code

    Implementations§

    Source§

    impl Code

    Source

    pub fn crypto(code: u8) -> Code

    Create QUIC error code from TLS alert code

    Source§

    impl Code

    Source

    pub const NO_ERROR: Code

    the connection is being closed abruptly in the absence of any error

    Source

    pub const INTERNAL_ERROR: Code

    the endpoint encountered an internal error and cannot continue with the connection

    diff --git a/pr/255/docs/iroh_quinn/struct.UdpStats.html b/pr/255/docs/iroh_quinn/struct.UdpStats.html index 9bd2b974b..f89423f38 100644 --- a/pr/255/docs/iroh_quinn/struct.UdpStats.html +++ b/pr/255/docs/iroh_quinn/struct.UdpStats.html @@ -1,4 +1,4 @@ -UdpStats in iroh_quinn - Rust

    UdpStats

    Struct UdpStats 

    Source
    #[non_exhaustive]
    pub struct UdpStats { +UdpStats in iroh_quinn - Rust

    UdpStats

    Struct UdpStats 

    Source
    #[non_exhaustive]
    pub struct UdpStats { pub datagrams: u64, pub bytes: u64, pub ios: u64, diff --git a/pr/255/docs/iroh_quinn/struct.UnorderedRecvStream.html b/pr/255/docs/iroh_quinn/struct.UnorderedRecvStream.html index ab3bb3189..80927e34a 100644 --- a/pr/255/docs/iroh_quinn/struct.UnorderedRecvStream.html +++ b/pr/255/docs/iroh_quinn/struct.UnorderedRecvStream.html @@ -1,4 +1,4 @@ -UnorderedRecvStream in iroh_quinn - Rust

    UnorderedRecvStream

    Struct UnorderedRecvStream 

    Source
    pub struct UnorderedRecvStream { /* private fields */ }
    Expand description

    A stream that can be used to receive data out-of-order.

    +UnorderedRecvStream in iroh_quinn - Rust

    UnorderedRecvStream

    Struct UnorderedRecvStream 

    Source
    pub struct UnorderedRecvStream { /* private fields */ }
    Expand description

    A stream that can be used to receive data out-of-order.

    Obtained by converting a RecvStream via RecvStream::into_unordered.

    This variant of RecvStream allows reading chunks of data exclusively out of order. Once you have done an unordered read, ordered reads are no diff --git a/pr/255/docs/iroh_quinn/struct.ValidationTokenConfig.html b/pr/255/docs/iroh_quinn/struct.ValidationTokenConfig.html index d112e449f..1af51d760 100644 --- a/pr/255/docs/iroh_quinn/struct.ValidationTokenConfig.html +++ b/pr/255/docs/iroh_quinn/struct.ValidationTokenConfig.html @@ -1,4 +1,4 @@ -ValidationTokenConfig in iroh_quinn - Rust

    ValidationTokenConfig

    Struct ValidationTokenConfig 

    Source
    pub struct ValidationTokenConfig { /* private fields */ }
    Expand description

    Configuration for sending and handling validation tokens in incoming connections

    +ValidationTokenConfig in iroh_quinn - Rust

    ValidationTokenConfig

    Struct ValidationTokenConfig 

    Source
    pub struct ValidationTokenConfig { /* private fields */ }
    Expand description

    Configuration for sending and handling validation tokens in incoming connections

    Default values should be suitable for most internet applications.

    §QUIC Tokens

    The QUIC protocol defines a concept of “address validation”. Essentially, one side of a diff --git a/pr/255/docs/iroh_quinn/struct.VarInt.html b/pr/255/docs/iroh_quinn/struct.VarInt.html index 3765cbde0..d70a9303d 100644 --- a/pr/255/docs/iroh_quinn/struct.VarInt.html +++ b/pr/255/docs/iroh_quinn/struct.VarInt.html @@ -1,4 +1,4 @@ -VarInt in iroh_quinn - Rust

    VarInt

    Struct VarInt 

    Source
    pub struct VarInt(/* private fields */);
    Expand description

    An integer less than 2^62

    +VarInt in iroh_quinn - Rust

    VarInt

    Struct VarInt 

    Source
    pub struct VarInt(/* private fields */);
    Expand description

    An integer less than 2^62

    Values of this type are suitable for encoding as QUIC variable-length integer.

    Implementations§

    Source§

    impl VarInt

    Source

    pub const MAX: VarInt

    The largest representable value

    Source

    pub const MAX_SIZE: usize = 8usize

    The largest encoded value length

    diff --git a/pr/255/docs/iroh_quinn/struct.VarIntBoundsExceeded.html b/pr/255/docs/iroh_quinn/struct.VarIntBoundsExceeded.html index bbd712096..85bde9bc7 100644 --- a/pr/255/docs/iroh_quinn/struct.VarIntBoundsExceeded.html +++ b/pr/255/docs/iroh_quinn/struct.VarIntBoundsExceeded.html @@ -1,4 +1,4 @@ -VarIntBoundsExceeded in iroh_quinn - Rust

    VarIntBoundsExceeded

    Struct VarIntBoundsExceeded 

    Source
    pub struct VarIntBoundsExceeded;
    Expand description

    Error returned when constructing a VarInt from a value >= 2^62

    +VarIntBoundsExceeded in iroh_quinn - Rust

    VarIntBoundsExceeded

    Struct VarIntBoundsExceeded 

    Source
    pub struct VarIntBoundsExceeded;
    Expand description

    Error returned when constructing a VarInt from a value >= 2^62

    Trait Implementations§

    Source§

    impl Clone for VarIntBoundsExceeded

    Source§

    fn clone(&self) -> VarIntBoundsExceeded

    Returns a duplicate of the value. Read more
    1.0.0 · Source§

    fn clone_from(&mut self, source: &Self)

    Performs copy-assignment from source. Read more
    Source§

    impl Debug for VarIntBoundsExceeded

    Source§

    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

    Formats the value using the given formatter. Read more
    Source§

    impl Display for VarIntBoundsExceeded

    Source§

    fn fmt(&self, __formatter: &mut Formatter<'_>) -> Result<(), Error>

    Formats the value using the given formatter. Read more
    Source§

    impl Error for VarIntBoundsExceeded

    1.30.0 · Source§

    fn source(&self) -> Option<&(dyn Error + 'static)>

    Returns the lower-level source of this error, if any. Read more
    1.0.0 · Source§

    fn description(&self) -> &str

    👎Deprecated since 1.42.0: use the Display impl or to_string()
    1.0.0 · Source§

    fn cause(&self) -> Option<&dyn Error>

    👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
    Source§

    fn provide<'a>(&'a self, request: &mut Request<'a>)

    🔬This is a nightly-only experimental API. (error_generic_member_access)
    Provides type-based access to context intended for error reports. Read more
    Source§

    impl From<VarIntBoundsExceeded> for ConfigError

    Source§

    fn from(_: VarIntBoundsExceeded) -> ConfigError

    Converts to this type from the input type.
    Source§

    impl PartialEq for VarIntBoundsExceeded

    Source§

    fn eq(&self, other: &VarIntBoundsExceeded) -> bool

    Tests for self and other values to be equal, and is used by ==.
    1.0.0 · Source§

    fn ne(&self, other: &Rhs) -> bool

    Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
    Source§

    impl Copy for VarIntBoundsExceeded

    Source§

    impl Eq for VarIntBoundsExceeded

    Source§

    impl StructuralPartialEq for VarIntBoundsExceeded

    Auto Trait Implementations§

    Blanket Implementations§

    Source§

    impl<T> Any for T
    where T: 'static + ?Sized,

    Source§

    fn type_id(&self) -> TypeId

    Gets the TypeId of self. Read more
    Source§

    impl<T> Borrow<T> for T
    where diff --git a/pr/255/docs/iroh_quinn/struct.WeakConnectionHandle.html b/pr/255/docs/iroh_quinn/struct.WeakConnectionHandle.html index 46aa2f331..6ed06c21c 100644 --- a/pr/255/docs/iroh_quinn/struct.WeakConnectionHandle.html +++ b/pr/255/docs/iroh_quinn/struct.WeakConnectionHandle.html @@ -1,9 +1,9 @@ -WeakConnectionHandle in iroh_quinn - Rust

    WeakConnectionHandle

    Struct WeakConnectionHandle 

    Source
    pub struct WeakConnectionHandle(/* private fields */);
    Expand description

    A handle to some connection internals, use with care.

    +WeakConnectionHandle in iroh_quinn - Rust

    WeakConnectionHandle

    Struct WeakConnectionHandle 

    Source
    pub struct WeakConnectionHandle(/* private fields */);
    Expand description

    A handle to some connection internals, use with care.

    This contains a weak reference to the connection so will not itself keep the connection alive.

    -

    Implementations§

    Source§

    impl WeakConnectionHandle

    Source

    pub fn is_alive(&self) -> bool

    Returns true if the Connection associated with this handle is still alive.

    -
    Source

    pub fn upgrade(&self) -> Option<Connection>

    Upgrade the handle to a full Connection

    -

    Trait Implementations§

    Source§

    impl Clone for WeakConnectionHandle

    Source§

    fn clone(&self) -> WeakConnectionHandle

    Returns a duplicate of the value. Read more
    1.0.0 · Source§

    fn clone_from(&mut self, source: &Self)

    Performs copy-assignment from source. Read more
    Source§

    impl Debug for WeakConnectionHandle

    Source§

    fn fmt(&self, f: &mut Formatter<'_>) -> Result

    Formats the value using the given formatter. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Source§

    impl<T> Any for T
    where +

    Implementations§

    Source§

    impl WeakConnectionHandle

    Source

    pub fn is_alive(&self) -> bool

    Returns true if the Connection associated with this handle is still alive.

    +
    Source

    pub fn upgrade(&self) -> Option<Connection>

    Upgrade the handle to a full Connection

    +

    Trait Implementations§

    Source§

    impl Clone for WeakConnectionHandle

    Source§

    fn clone(&self) -> WeakConnectionHandle

    Returns a duplicate of the value. Read more
    1.0.0 · Source§

    fn clone_from(&mut self, source: &Self)

    Performs copy-assignment from source. Read more
    Source§

    impl Debug for WeakConnectionHandle

    Source§

    fn fmt(&self, f: &mut Formatter<'_>) -> Result

    Formats the value using the given formatter. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Source§

    impl<T> Any for T
    where T: 'static + ?Sized,

    Source§

    fn type_id(&self) -> TypeId

    Gets the TypeId of self. Read more
    Source§

    impl<T> Borrow<T> for T
    where T: ?Sized,

    Source§

    fn borrow(&self) -> &T

    Immutably borrows from an owned value. Read more
    Source§

    impl<T> BorrowMut<T> for T
    where T: ?Sized,

    Source§

    fn borrow_mut(&mut self) -> &mut T

    Mutably borrows from an owned value. Read more
    Source§

    impl<T> CloneToUninit for T
    where diff --git a/pr/255/docs/iroh_quinn/struct.Written.html b/pr/255/docs/iroh_quinn/struct.Written.html index daafa80a8..91d8099a4 100644 --- a/pr/255/docs/iroh_quinn/struct.Written.html +++ b/pr/255/docs/iroh_quinn/struct.Written.html @@ -1,12 +1,12 @@ -Written in iroh_quinn - Rust

    Written

    Struct Written 

    Source
    pub struct Written {
    +Written in iroh_quinn - Rust

    Written

    Struct Written 

    Source
    pub struct Written {
         pub bytes: usize,
         pub chunks: usize,
     }
    Expand description

    Indicates how many bytes and chunks had been transferred in a write operation

    Fields§

    §bytes: usize

    The amount of bytes which had been written

    §chunks: usize

    The amount of full chunks which had been written

    If a chunk was only partially written, it will not be counted by this field.

    -

    Trait Implementations§

    Source§

    impl Clone for Written

    Source§

    fn clone(&self) -> Written

    Returns a duplicate of the value. Read more
    1.0.0 · Source§

    fn clone_from(&mut self, source: &Self)

    Performs copy-assignment from source. Read more
    Source§

    impl Debug for Written

    Source§

    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

    Formats the value using the given formatter. Read more
    Source§

    impl Default for Written

    Source§

    fn default() -> Written

    Returns the “default value” for a type. Read more
    Source§

    impl PartialEq for Written

    Source§

    fn eq(&self, other: &Written) -> bool

    Tests for self and other values to be equal, and is used by ==.
    1.0.0 · Source§

    fn ne(&self, other: &Rhs) -> bool

    Tests for !=. The default implementation is almost always sufficient, -and should not be overridden without very good reason.
    Source§

    impl Copy for Written

    Source§

    impl Eq for Written

    Source§

    impl StructuralPartialEq for Written

    Auto Trait Implementations§

    Blanket Implementations§

    Source§

    impl<T> Any for T
    where +

    Trait Implementations§

    Source§

    impl Clone for Written

    Source§

    fn clone(&self) -> Written

    Returns a duplicate of the value. Read more
    1.0.0 · Source§

    fn clone_from(&mut self, source: &Self)

    Performs copy-assignment from source. Read more
    Source§

    impl Debug for Written

    Source§

    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

    Formats the value using the given formatter. Read more
    Source§

    impl Default for Written

    Source§

    fn default() -> Written

    Returns the “default value” for a type. Read more
    Source§

    impl PartialEq for Written

    Source§

    fn eq(&self, other: &Written) -> bool

    Tests for self and other values to be equal, and is used by ==.
    1.0.0 · Source§

    fn ne(&self, other: &Rhs) -> bool

    Tests for !=. The default implementation is almost always sufficient, +and should not be overridden without very good reason.
    Source§

    impl Copy for Written

    Source§

    impl Eq for Written

    Source§

    impl StructuralPartialEq for Written

    Auto Trait Implementations§

    Blanket Implementations§

    Source§

    impl<T> Any for T
    where T: 'static + ?Sized,

    Source§

    fn type_id(&self) -> TypeId

    Gets the TypeId of self. Read more
    Source§

    impl<T> Borrow<T> for T
    where T: ?Sized,

    Source§

    fn borrow(&self) -> &T

    Immutably borrows from an owned value. Read more
    Source§

    impl<T> BorrowMut<T> for T
    where T: ?Sized,

    Source§

    fn borrow_mut(&mut self) -> &mut T

    Mutably borrows from an owned value. Read more
    Source§

    impl<T> CloneToUninit for T
    where diff --git a/pr/255/docs/iroh_quinn/struct.ZeroRttAccepted.html b/pr/255/docs/iroh_quinn/struct.ZeroRttAccepted.html index c5d9c8129..a02732a89 100644 --- a/pr/255/docs/iroh_quinn/struct.ZeroRttAccepted.html +++ b/pr/255/docs/iroh_quinn/struct.ZeroRttAccepted.html @@ -1,4 +1,4 @@ -ZeroRttAccepted in iroh_quinn - Rust

    ZeroRttAccepted

    Struct ZeroRttAccepted 

    Source
    pub struct ZeroRttAccepted(/* private fields */);
    Expand description

    Future that completes when a connection is fully established

    +ZeroRttAccepted in iroh_quinn - Rust

    ZeroRttAccepted

    Struct ZeroRttAccepted 

    Source
    pub struct ZeroRttAccepted(/* private fields */);
    Expand description

    Future that completes when a connection is fully established

    For clients, the resulting value indicates if 0-RTT was accepted. For servers, the resulting value is meaningless.

    Trait Implementations§

    Source§

    impl Future for ZeroRttAccepted

    Source§

    type Output = bool

    The type of value produced on completion.
    Source§

    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>

    Attempts to resolve the future to a final value, registering diff --git a/pr/255/docs/iroh_quinn/trait.AsyncTimer.html b/pr/255/docs/iroh_quinn/trait.AsyncTimer.html index c8f214dd7..1f32a6063 100644 --- a/pr/255/docs/iroh_quinn/trait.AsyncTimer.html +++ b/pr/255/docs/iroh_quinn/trait.AsyncTimer.html @@ -1,4 +1,4 @@ -AsyncTimer in iroh_quinn - Rust

    AsyncTimer

    Trait AsyncTimer 

    Source
    pub trait AsyncTimer:
    +AsyncTimer in iroh_quinn - Rust

    AsyncTimer

    Trait AsyncTimer 

    Source
    pub trait AsyncTimer:
         Send
         + Debug
         + 'static {
    diff --git a/pr/255/docs/iroh_quinn/trait.AsyncUdpSocket.html b/pr/255/docs/iroh_quinn/trait.AsyncUdpSocket.html
    index f6885a6ca..3cff5d96a 100644
    --- a/pr/255/docs/iroh_quinn/trait.AsyncUdpSocket.html
    +++ b/pr/255/docs/iroh_quinn/trait.AsyncUdpSocket.html
    @@ -1,4 +1,4 @@
    -AsyncUdpSocket in iroh_quinn - Rust

    AsyncUdpSocket

    Trait AsyncUdpSocket 

    Source
    pub trait AsyncUdpSocket:
    +AsyncUdpSocket in iroh_quinn - Rust

    AsyncUdpSocket

    Trait AsyncUdpSocket 

    Source
    pub trait AsyncUdpSocket:
         Send
         + Sync
         + Debug
    diff --git a/pr/255/docs/iroh_quinn/trait.ConnectionIdGenerator.html b/pr/255/docs/iroh_quinn/trait.ConnectionIdGenerator.html
    index e7e811495..c3b18e385 100644
    --- a/pr/255/docs/iroh_quinn/trait.ConnectionIdGenerator.html
    +++ b/pr/255/docs/iroh_quinn/trait.ConnectionIdGenerator.html
    @@ -1,4 +1,4 @@
    -ConnectionIdGenerator in iroh_quinn - Rust

    ConnectionIdGenerator

    Trait ConnectionIdGenerator 

    Source
    pub trait ConnectionIdGenerator: Send + Sync {
    +ConnectionIdGenerator in iroh_quinn - Rust

    ConnectionIdGenerator

    Trait ConnectionIdGenerator 

    Source
    pub trait ConnectionIdGenerator: Send + Sync {
         // Required methods
         fn generate_cid(&mut self) -> ConnectionId;
         fn cid_len(&self) -> usize;
    diff --git a/pr/255/docs/iroh_quinn/trait.QlogFactory.html b/pr/255/docs/iroh_quinn/trait.QlogFactory.html
    index d5252406d..4c7cf78e8 100644
    --- a/pr/255/docs/iroh_quinn/trait.QlogFactory.html
    +++ b/pr/255/docs/iroh_quinn/trait.QlogFactory.html
    @@ -1,4 +1,4 @@
    -QlogFactory in iroh_quinn - Rust

    QlogFactory

    Trait QlogFactory 

    Source
    pub trait QlogFactory:
    +QlogFactory in iroh_quinn - Rust

    QlogFactory

    Trait QlogFactory 

    Source
    pub trait QlogFactory:
         Send
         + Sync
         + 'static {
    diff --git a/pr/255/docs/iroh_quinn/trait.Runtime.html b/pr/255/docs/iroh_quinn/trait.Runtime.html
    index f256e13f0..1765c2ff4 100644
    --- a/pr/255/docs/iroh_quinn/trait.Runtime.html
    +++ b/pr/255/docs/iroh_quinn/trait.Runtime.html
    @@ -1,4 +1,4 @@
    -Runtime in iroh_quinn - Rust

    Runtime

    Trait Runtime 

    Source
    pub trait Runtime:
    +Runtime in iroh_quinn - Rust

    Runtime

    Trait Runtime 

    Source
    pub trait Runtime:
         Send
         + Sync
         + Debug
    diff --git a/pr/255/docs/iroh_quinn/trait.TimeSource.html b/pr/255/docs/iroh_quinn/trait.TimeSource.html
    index f902865de..1aaca55c7 100644
    --- a/pr/255/docs/iroh_quinn/trait.TimeSource.html
    +++ b/pr/255/docs/iroh_quinn/trait.TimeSource.html
    @@ -1,4 +1,4 @@
    -TimeSource in iroh_quinn - Rust

    TimeSource

    Trait TimeSource 

    Source
    pub trait TimeSource: Send + Sync {
    +TimeSource in iroh_quinn - Rust

    TimeSource

    Trait TimeSource 

    Source
    pub trait TimeSource: Send + Sync {
         // Required method
         fn now(&self) -> SystemTime;
     }
    Expand description

    Object to get current SystemTime

    diff --git a/pr/255/docs/iroh_quinn/trait.TokenLog.html b/pr/255/docs/iroh_quinn/trait.TokenLog.html index 0b58ab6ec..d63384690 100644 --- a/pr/255/docs/iroh_quinn/trait.TokenLog.html +++ b/pr/255/docs/iroh_quinn/trait.TokenLog.html @@ -1,4 +1,4 @@ -TokenLog in iroh_quinn - Rust

    TokenLog

    Trait TokenLog 

    Source
    pub trait TokenLog: Send + Sync {
    +TokenLog in iroh_quinn - Rust

    TokenLog

    Trait TokenLog 

    Source
    pub trait TokenLog: Send + Sync {
         // Required method
         fn check_and_insert(
             &self,
    diff --git a/pr/255/docs/iroh_quinn/trait.TokenStore.html b/pr/255/docs/iroh_quinn/trait.TokenStore.html
    index b39308556..164f3e268 100644
    --- a/pr/255/docs/iroh_quinn/trait.TokenStore.html
    +++ b/pr/255/docs/iroh_quinn/trait.TokenStore.html
    @@ -1,4 +1,4 @@
    -TokenStore in iroh_quinn - Rust

    TokenStore

    Trait TokenStore 

    Source
    pub trait TokenStore: Send + Sync {
    +TokenStore in iroh_quinn - Rust

    TokenStore

    Trait TokenStore 

    Source
    pub trait TokenStore: Send + Sync {
         // Required methods
         fn insert(&self, server_name: &str, token: Bytes);
         fn take(&self, server_name: &str) -> Option<Bytes>;
    diff --git a/pr/255/docs/iroh_quinn/trait.UdpSender.html b/pr/255/docs/iroh_quinn/trait.UdpSender.html
    index 7076f3a68..d05da25b6 100644
    --- a/pr/255/docs/iroh_quinn/trait.UdpSender.html
    +++ b/pr/255/docs/iroh_quinn/trait.UdpSender.html
    @@ -1,4 +1,4 @@
    -UdpSender in iroh_quinn - Rust

    UdpSender

    Trait UdpSender 

    Source
    pub trait UdpSender:
    +UdpSender in iroh_quinn - Rust

    UdpSender

    Trait UdpSender 

    Source
    pub trait UdpSender:
         Send
         + Sync
         + Debug
    diff --git a/pr/255/docs/iroh_quinn_proto/all.html b/pr/255/docs/iroh_quinn_proto/all.html
    index dc1a2d901..2928c6b59 100644
    --- a/pr/255/docs/iroh_quinn_proto/all.html
    +++ b/pr/255/docs/iroh_quinn_proto/all.html
    @@ -1 +1 @@
    -List of all items in this crate

    All

    List of all items

    Structs

    Enums

    Traits

    Functions

    Type Aliases

    Constants

    \ No newline at end of file +List of all items in this crate

    All

    List of all items

    Structs

    Enums

    Traits

    Functions

    Type Aliases

    Constants

    \ No newline at end of file diff --git a/pr/255/docs/iroh_quinn_proto/bench_exports/index.html b/pr/255/docs/iroh_quinn_proto/bench_exports/index.html index ed857d58b..5a171899b 100644 --- a/pr/255/docs/iroh_quinn_proto/bench_exports/index.html +++ b/pr/255/docs/iroh_quinn_proto/bench_exports/index.html @@ -1,2 +1,2 @@ -iroh_quinn_proto::bench_exports - Rust

    Module bench_exports

    Module bench_exports 

    Source
    Expand description

    Exports for benchmarks

    +iroh_quinn_proto::bench_exports - Rust

    Module bench_exports

    Module bench_exports 

    Source
    Expand description

    Exports for benchmarks

    Modules§

    send_buffer_benches
    Bench fns for SendBuffer
    \ No newline at end of file diff --git a/pr/255/docs/iroh_quinn_proto/bench_exports/send_buffer_benches/fn.get_into_many_segments.html b/pr/255/docs/iroh_quinn_proto/bench_exports/send_buffer_benches/fn.get_into_many_segments.html index 50470093c..9e1ad4b85 100644 --- a/pr/255/docs/iroh_quinn_proto/bench_exports/send_buffer_benches/fn.get_into_many_segments.html +++ b/pr/255/docs/iroh_quinn_proto/bench_exports/send_buffer_benches/fn.get_into_many_segments.html @@ -1,2 +1,2 @@ -get_into_many_segments in iroh_quinn_proto::bench_exports::send_buffer_benches - Rust

    get_into_many_segments

    Function get_into_many_segments 

    Source
    pub fn get_into_many_segments(criterion: &mut Criterion)
    Expand description

    Pathological case: many segments, get from end

    +get_into_many_segments in iroh_quinn_proto::bench_exports::send_buffer_benches - Rust

    get_into_many_segments

    Function get_into_many_segments 

    Source
    pub fn get_into_many_segments(criterion: &mut Criterion)
    Expand description

    Pathological case: many segments, get from end

    \ No newline at end of file diff --git a/pr/255/docs/iroh_quinn_proto/bench_exports/send_buffer_benches/fn.get_loop_many_segments.html b/pr/255/docs/iroh_quinn_proto/bench_exports/send_buffer_benches/fn.get_loop_many_segments.html index 28284de52..44970f288 100644 --- a/pr/255/docs/iroh_quinn_proto/bench_exports/send_buffer_benches/fn.get_loop_many_segments.html +++ b/pr/255/docs/iroh_quinn_proto/bench_exports/send_buffer_benches/fn.get_loop_many_segments.html @@ -1,2 +1,2 @@ -get_loop_many_segments in iroh_quinn_proto::bench_exports::send_buffer_benches - Rust

    get_loop_many_segments

    Function get_loop_many_segments 

    Source
    pub fn get_loop_many_segments(criterion: &mut Criterion)
    Expand description

    Get segments in the old way, using a loop of get calls

    +get_loop_many_segments in iroh_quinn_proto::bench_exports::send_buffer_benches - Rust

    get_loop_many_segments

    Function get_loop_many_segments 

    Source
    pub fn get_loop_many_segments(criterion: &mut Criterion)
    Expand description

    Get segments in the old way, using a loop of get calls

    \ No newline at end of file diff --git a/pr/255/docs/iroh_quinn_proto/bench_exports/send_buffer_benches/index.html b/pr/255/docs/iroh_quinn_proto/bench_exports/send_buffer_benches/index.html index 00ca26f44..44de92d3f 100644 --- a/pr/255/docs/iroh_quinn_proto/bench_exports/send_buffer_benches/index.html +++ b/pr/255/docs/iroh_quinn_proto/bench_exports/send_buffer_benches/index.html @@ -1,4 +1,4 @@ -iroh_quinn_proto::bench_exports::send_buffer_benches - Rust

    Module send_buffer_benches

    Module send_buffer_benches 

    Source
    Expand description

    Bench fns for SendBuffer

    +iroh_quinn_proto::bench_exports::send_buffer_benches - Rust

    Module send_buffer_benches

    Module send_buffer_benches 

    Source
    Expand description

    Bench fns for SendBuffer

    These are defined here and re-exported via bench_exports in lib.rs, so we can access the private SendBuffer struct.

    Functions§

    get_into_many_segments
    Pathological case: many segments, get from end
    get_loop_many_segments
    Get segments in the old way, using a loop of get calls
    \ No newline at end of file diff --git a/pr/255/docs/iroh_quinn_proto/coding/index.html b/pr/255/docs/iroh_quinn_proto/coding/index.html index 97aa6bfc0..da3e32c3a 100644 --- a/pr/255/docs/iroh_quinn_proto/coding/index.html +++ b/pr/255/docs/iroh_quinn_proto/coding/index.html @@ -1,2 +1,2 @@ -iroh_quinn_proto::coding - Rust

    Module coding

    Module coding 

    Source
    Expand description

    Coding related traits.

    +iroh_quinn_proto::coding - Rust

    Module coding

    Module coding 

    Source
    Expand description

    Coding related traits.

    Structs§

    UnexpectedEnd
    Error indicating that the provided buffer was too small

    Traits§

    Decodable
    Decoding of QUIC primitives.
    Encodable
    Infallible encoding of QUIC primitives.

    Type Aliases§

    Result
    Coding result type
    \ No newline at end of file diff --git a/pr/255/docs/iroh_quinn_proto/coding/struct.UnexpectedEnd.html b/pr/255/docs/iroh_quinn_proto/coding/struct.UnexpectedEnd.html index ef3e8364d..a11ef9651 100644 --- a/pr/255/docs/iroh_quinn_proto/coding/struct.UnexpectedEnd.html +++ b/pr/255/docs/iroh_quinn_proto/coding/struct.UnexpectedEnd.html @@ -1,4 +1,4 @@ -UnexpectedEnd in iroh_quinn_proto::coding - Rust

    UnexpectedEnd

    Struct UnexpectedEnd 

    Source
    pub struct UnexpectedEnd;
    Expand description

    Error indicating that the provided buffer was too small

    +UnexpectedEnd in iroh_quinn_proto::coding - Rust

    UnexpectedEnd

    Struct UnexpectedEnd 

    Source
    pub struct UnexpectedEnd;
    Expand description

    Error indicating that the provided buffer was too small

    Trait Implementations§

    Source§

    impl Clone for UnexpectedEnd

    Source§

    fn clone(&self) -> UnexpectedEnd

    Returns a duplicate of the value. Read more
    1.0.0 · Source§

    fn clone_from(&mut self, source: &Self)

    Performs copy-assignment from source. Read more
    Source§

    impl Debug for UnexpectedEnd

    Source§

    fn fmt(&self, f: &mut Formatter<'_>) -> Result

    Formats the value using the given formatter. Read more
    Source§

    impl Display for UnexpectedEnd

    Source§

    fn fmt(&self, __formatter: &mut Formatter<'_>) -> Result

    Formats the value using the given formatter. Read more
    Source§

    impl Error for UnexpectedEnd

    1.30.0 · Source§

    fn source(&self) -> Option<&(dyn Error + 'static)>

    Returns the lower-level source of this error, if any. Read more
    1.0.0 · Source§

    fn description(&self) -> &str

    👎Deprecated since 1.42.0: use the Display impl or to_string()
    1.0.0 · Source§

    fn cause(&self) -> Option<&dyn Error>

    👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
    Source§

    fn provide<'a>(&'a self, request: &mut Request<'a>)

    🔬This is a nightly-only experimental API. (error_generic_member_access)
    Provides type-based access to context intended for error reports. Read more
    Source§

    impl From<UnexpectedEnd> for Error

    Source§

    fn from(_: UnexpectedEnd) -> Self

    Converts to this type from the input type.
    Source§

    impl From<UnexpectedEnd> for PacketDecodeError

    Source§

    fn from(_: UnexpectedEnd) -> Self

    Converts to this type from the input type.
    Source§

    impl PartialEq for UnexpectedEnd

    Source§

    fn eq(&self, other: &UnexpectedEnd) -> bool

    Tests for self and other values to be equal, and is used by ==.
    1.0.0 · Source§

    fn ne(&self, other: &Rhs) -> bool

    Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
    Source§

    impl Copy for UnexpectedEnd

    Source§

    impl Eq for UnexpectedEnd

    Source§

    impl StructuralPartialEq for UnexpectedEnd

    Auto Trait Implementations§

    Blanket Implementations§

    Source§

    impl<T> Any for T
    where T: 'static + ?Sized,

    Source§

    fn type_id(&self) -> TypeId

    Gets the TypeId of self. Read more
    Source§

    impl<T> Borrow<T> for T
    where diff --git a/pr/255/docs/iroh_quinn_proto/coding/trait.Decodable.html b/pr/255/docs/iroh_quinn_proto/coding/trait.Decodable.html index a5a57cfda..59d7c14f1 100644 --- a/pr/255/docs/iroh_quinn_proto/coding/trait.Decodable.html +++ b/pr/255/docs/iroh_quinn_proto/coding/trait.Decodable.html @@ -1,6 +1,6 @@ -Decodable in iroh_quinn_proto::coding - Rust

    Decodable

    Trait Decodable 

    Source
    pub trait Decodable: Sized {
    +Decodable in iroh_quinn_proto::coding - Rust

    Decodable

    Trait Decodable 

    Source
    pub trait Decodable: Sized {
         // Required method
         fn decode<B: Buf>(buf: &mut B) -> Result<Self>;
     }
    Expand description

    Decoding of QUIC primitives.

    Required Methods§

    Source

    fn decode<B: Buf>(buf: &mut B) -> Result<Self>

    Decode a Self from the provided buffer, if the buffer is large enough

    -

    Dyn Compatibility§

    This trait is not dyn compatible.

    In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

    Implementations on Foreign Types§

    Source§

    impl Decodable for u8

    Source§

    fn decode<B: Buf>(buf: &mut B) -> Result<Self>

    Source§

    impl Decodable for u16

    Source§

    fn decode<B: Buf>(buf: &mut B) -> Result<Self>

    Source§

    impl Decodable for u32

    Source§

    fn decode<B: Buf>(buf: &mut B) -> Result<Self>

    Source§

    impl Decodable for u64

    Source§

    fn decode<B: Buf>(buf: &mut B) -> Result<Self>

    Source§

    impl Decodable for Ipv4Addr

    Source§

    fn decode<B: Buf>(buf: &mut B) -> Result<Self>

    Source§

    impl Decodable for Ipv6Addr

    Source§

    fn decode<B: Buf>(buf: &mut B) -> Result<Self>

    Implementors§

    \ No newline at end of file +

    Dyn Compatibility§

    This trait is not dyn compatible.

    In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

    Implementations on Foreign Types§

    Source§

    impl Decodable for u8

    Source§

    fn decode<B: Buf>(buf: &mut B) -> Result<Self>

    Source§

    impl Decodable for u16

    Source§

    fn decode<B: Buf>(buf: &mut B) -> Result<Self>

    Source§

    impl Decodable for u32

    Source§

    fn decode<B: Buf>(buf: &mut B) -> Result<Self>

    Source§

    impl Decodable for u64

    Source§

    fn decode<B: Buf>(buf: &mut B) -> Result<Self>

    Source§

    impl Decodable for Ipv4Addr

    Source§

    fn decode<B: Buf>(buf: &mut B) -> Result<Self>

    Source§

    impl Decodable for Ipv6Addr

    Source§

    fn decode<B: Buf>(buf: &mut B) -> Result<Self>

    Implementors§

    \ No newline at end of file diff --git a/pr/255/docs/iroh_quinn_proto/coding/trait.Encodable.html b/pr/255/docs/iroh_quinn_proto/coding/trait.Encodable.html index 610662869..30d1d9852 100644 --- a/pr/255/docs/iroh_quinn_proto/coding/trait.Encodable.html +++ b/pr/255/docs/iroh_quinn_proto/coding/trait.Encodable.html @@ -1,6 +1,6 @@ -Encodable in iroh_quinn_proto::coding - Rust

    Encodable

    Trait Encodable 

    Source
    pub trait Encodable {
    +Encodable in iroh_quinn_proto::coding - Rust

    Encodable

    Trait Encodable 

    Source
    pub trait Encodable {
         // Required method
         fn encode<B: BufMut>(&self, buf: &mut B);
     }
    Expand description

    Infallible encoding of QUIC primitives.

    Required Methods§

    Source

    fn encode<B: BufMut>(&self, buf: &mut B)

    Append the encoding of self to the provided buffer.

    -

    Dyn Compatibility§

    This trait is not dyn compatible.

    In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

    Implementations on Foreign Types§

    Source§

    impl Encodable for u8

    Source§

    fn encode<B: BufMut>(&self, buf: &mut B)

    Source§

    impl Encodable for u16

    Source§

    fn encode<B: BufMut>(&self, buf: &mut B)

    Source§

    impl Encodable for u32

    Source§

    fn encode<B: BufMut>(&self, buf: &mut B)

    Source§

    impl Encodable for u64

    Source§

    fn encode<B: BufMut>(&self, buf: &mut B)

    Source§

    impl Encodable for Ipv4Addr

    Source§

    fn encode<B: BufMut>(&self, buf: &mut B)

    Source§

    impl Encodable for Ipv6Addr

    Source§

    fn encode<B: BufMut>(&self, buf: &mut B)

    Implementors§

    \ No newline at end of file +

    Dyn Compatibility§

    This trait is not dyn compatible.

    In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

    Implementations on Foreign Types§

    Source§

    impl Encodable for u8

    Source§

    fn encode<B: BufMut>(&self, buf: &mut B)

    Source§

    impl Encodable for u16

    Source§

    fn encode<B: BufMut>(&self, buf: &mut B)

    Source§

    impl Encodable for u32

    Source§

    fn encode<B: BufMut>(&self, buf: &mut B)

    Source§

    impl Encodable for u64

    Source§

    fn encode<B: BufMut>(&self, buf: &mut B)

    Source§

    impl Encodable for Ipv4Addr

    Source§

    fn encode<B: BufMut>(&self, buf: &mut B)

    Source§

    impl Encodable for Ipv6Addr

    Source§

    fn encode<B: BufMut>(&self, buf: &mut B)

    Implementors§

    \ No newline at end of file diff --git a/pr/255/docs/iroh_quinn_proto/coding/type.Result.html b/pr/255/docs/iroh_quinn_proto/coding/type.Result.html index 185875b69..a55c987e2 100644 --- a/pr/255/docs/iroh_quinn_proto/coding/type.Result.html +++ b/pr/255/docs/iroh_quinn_proto/coding/type.Result.html @@ -1,4 +1,4 @@ -Result in iroh_quinn_proto::coding - Rust

    Result

    Type Alias Result 

    Source
    pub type Result<T> = Result<T, UnexpectedEnd>;
    Expand description

    Coding result type

    +Result in iroh_quinn_proto::coding - Rust

    Result

    Type Alias Result 

    Source
    pub type Result<T> = Result<T, UnexpectedEnd>;
    Expand description

    Coding result type

    Aliased Type§

    pub enum Result<T> {
         Ok(T),
         Err(UnexpectedEnd),
    diff --git a/pr/255/docs/iroh_quinn_proto/congestion/index.html b/pr/255/docs/iroh_quinn_proto/congestion/index.html
    index 591662f1f..dd79a1645 100644
    --- a/pr/255/docs/iroh_quinn_proto/congestion/index.html
    +++ b/pr/255/docs/iroh_quinn_proto/congestion/index.html
    @@ -1,2 +1,2 @@
    -iroh_quinn_proto::congestion - Rust

    Module congestion

    Module congestion 

    Source
    Expand description

    Logic for controlling the rate at which data is sent

    +iroh_quinn_proto::congestion - Rust

    Module congestion

    Module congestion 

    Source
    Expand description

    Logic for controlling the rate at which data is sent

    Structs§

    Bbr
    Experimental! Use at your own risk.
    BbrConfig
    Configuration for the Bbr congestion controller
    ControllerMetrics
    Common congestion controller metrics
    Cubic
    The RFC8312 congestion controller, as widely used for TCP
    CubicConfig
    Configuration for the Cubic congestion controller
    NewReno
    A simple, standard congestion controller
    NewRenoConfig
    Configuration for the NewReno congestion controller

    Traits§

    Controller
    Common interface for different congestion controllers
    ControllerFactory
    Constructs controllers on demand
    \ No newline at end of file diff --git a/pr/255/docs/iroh_quinn_proto/congestion/struct.Bbr.html b/pr/255/docs/iroh_quinn_proto/congestion/struct.Bbr.html index 3487f2cd9..ba96feffe 100644 --- a/pr/255/docs/iroh_quinn_proto/congestion/struct.Bbr.html +++ b/pr/255/docs/iroh_quinn_proto/congestion/struct.Bbr.html @@ -1,4 +1,4 @@ -Bbr in iroh_quinn_proto::congestion - Rust

    Bbr

    Struct Bbr 

    Source
    pub struct Bbr { /* private fields */ }
    Expand description

    Experimental! Use at your own risk.

    +Bbr in iroh_quinn_proto::congestion - Rust

    Bbr

    Struct Bbr 

    Source
    pub struct Bbr { /* private fields */ }
    Expand description

    Experimental! Use at your own risk.

    Aims for reduced buffer bloat and improved performance over high bandwidth-delay product networks. Based on google’s quiche implementation https://source.chromium.org/chromium/chromium/src/+/master:net/third_party/quiche/src/quic/core/congestion_control/bbr_sender.cc of BBR https://datatracker.ietf.org/doc/html/draft-cardwell-iccrg-bbr-congestion-control. diff --git a/pr/255/docs/iroh_quinn_proto/congestion/struct.BbrConfig.html b/pr/255/docs/iroh_quinn_proto/congestion/struct.BbrConfig.html index a12fb6965..999923d27 100644 --- a/pr/255/docs/iroh_quinn_proto/congestion/struct.BbrConfig.html +++ b/pr/255/docs/iroh_quinn_proto/congestion/struct.BbrConfig.html @@ -1,4 +1,4 @@ -BbrConfig in iroh_quinn_proto::congestion - Rust

    BbrConfig

    Struct BbrConfig 

    Source
    pub struct BbrConfig { /* private fields */ }
    Expand description

    Configuration for the Bbr congestion controller

    +BbrConfig in iroh_quinn_proto::congestion - Rust

    BbrConfig

    Struct BbrConfig 

    Source
    pub struct BbrConfig { /* private fields */ }
    Expand description

    Configuration for the Bbr congestion controller

    Implementations§

    Source§

    impl BbrConfig

    Source

    pub fn initial_window(&mut self, value: u64) -> &mut Self

    Default limit on the amount of outstanding data in bytes.

    Recommended value: min(10 * max_datagram_size, max(2 * max_datagram_size, 14720))

    Trait Implementations§

    Source§

    impl Clone for BbrConfig

    Source§

    fn clone(&self) -> BbrConfig

    Returns a duplicate of the value. Read more
    1.0.0 · Source§

    fn clone_from(&mut self, source: &Self)

    Performs copy-assignment from source. Read more
    Source§

    impl ControllerFactory for BbrConfig

    Source§

    fn build( diff --git a/pr/255/docs/iroh_quinn_proto/congestion/struct.ControllerMetrics.html b/pr/255/docs/iroh_quinn_proto/congestion/struct.ControllerMetrics.html index 59e99e093..edb94135a 100644 --- a/pr/255/docs/iroh_quinn_proto/congestion/struct.ControllerMetrics.html +++ b/pr/255/docs/iroh_quinn_proto/congestion/struct.ControllerMetrics.html @@ -1,4 +1,4 @@ -ControllerMetrics in iroh_quinn_proto::congestion - Rust

    ControllerMetrics

    Struct ControllerMetrics 

    Source
    #[non_exhaustive]
    pub struct ControllerMetrics { +ControllerMetrics in iroh_quinn_proto::congestion - Rust

    ControllerMetrics

    Struct ControllerMetrics 

    Source
    #[non_exhaustive]
    pub struct ControllerMetrics { pub congestion_window: u64, pub ssthresh: Option<u64>, pub pacing_rate: Option<u64>, diff --git a/pr/255/docs/iroh_quinn_proto/congestion/struct.Cubic.html b/pr/255/docs/iroh_quinn_proto/congestion/struct.Cubic.html index 17c3030b3..3e9c3dc9a 100644 --- a/pr/255/docs/iroh_quinn_proto/congestion/struct.Cubic.html +++ b/pr/255/docs/iroh_quinn_proto/congestion/struct.Cubic.html @@ -1,4 +1,4 @@ -Cubic in iroh_quinn_proto::congestion - Rust

    Cubic

    Struct Cubic 

    Source
    pub struct Cubic { /* private fields */ }
    Expand description

    The RFC8312 congestion controller, as widely used for TCP

    +Cubic in iroh_quinn_proto::congestion - Rust

    Cubic

    Struct Cubic 

    Source
    pub struct Cubic { /* private fields */ }
    Expand description

    The RFC8312 congestion controller, as widely used for TCP

    Implementations§

    Source§

    impl Cubic

    Source

    pub fn new(config: Arc<CubicConfig>, _now: Instant, current_mtu: u16) -> Self

    Construct a state using the given config and current time now

    Trait Implementations§

    Source§

    impl Clone for Cubic

    Source§

    fn clone(&self) -> Cubic

    Returns a duplicate of the value. Read more
    1.0.0 · Source§

    fn clone_from(&mut self, source: &Self)

    Performs copy-assignment from source. Read more
    Source§

    impl Controller for Cubic

    Source§

    fn on_ack( &mut self, diff --git a/pr/255/docs/iroh_quinn_proto/congestion/struct.CubicConfig.html b/pr/255/docs/iroh_quinn_proto/congestion/struct.CubicConfig.html index 0c60fb969..2fb22485f 100644 --- a/pr/255/docs/iroh_quinn_proto/congestion/struct.CubicConfig.html +++ b/pr/255/docs/iroh_quinn_proto/congestion/struct.CubicConfig.html @@ -1,4 +1,4 @@ -CubicConfig in iroh_quinn_proto::congestion - Rust

    CubicConfig

    Struct CubicConfig 

    Source
    pub struct CubicConfig { /* private fields */ }
    Expand description

    Configuration for the Cubic congestion controller

    +CubicConfig in iroh_quinn_proto::congestion - Rust

    CubicConfig

    Struct CubicConfig 

    Source
    pub struct CubicConfig { /* private fields */ }
    Expand description

    Configuration for the Cubic congestion controller

    Implementations§

    Source§

    impl CubicConfig

    Source

    pub fn initial_window(&mut self, value: u64) -> &mut Self

    Default limit on the amount of outstanding data in bytes.

    Recommended value: min(10 * max_datagram_size, max(2 * max_datagram_size, 14720))

    Trait Implementations§

    Source§

    impl Clone for CubicConfig

    Source§

    fn clone(&self) -> CubicConfig

    Returns a duplicate of the value. Read more
    1.0.0 · Source§

    fn clone_from(&mut self, source: &Self)

    Performs copy-assignment from source. Read more
    Source§

    impl ControllerFactory for CubicConfig

    Source§

    fn build(self: Arc<Self>, now: Instant, current_mtu: u16) -> Box<dyn Controller>

    Construct a fresh Controller
    Source§

    impl Debug for CubicConfig

    Source§

    fn fmt(&self, f: &mut Formatter<'_>) -> Result

    Formats the value using the given formatter. Read more
    Source§

    impl Default for CubicConfig

    Source§

    fn default() -> Self

    Returns the “default value” for a type. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Source§

    impl<T> Any for T
    where diff --git a/pr/255/docs/iroh_quinn_proto/congestion/struct.NewReno.html b/pr/255/docs/iroh_quinn_proto/congestion/struct.NewReno.html index 7d8fa8071..7c67c3138 100644 --- a/pr/255/docs/iroh_quinn_proto/congestion/struct.NewReno.html +++ b/pr/255/docs/iroh_quinn_proto/congestion/struct.NewReno.html @@ -1,4 +1,4 @@ -NewReno in iroh_quinn_proto::congestion - Rust

    NewReno

    Struct NewReno 

    Source
    pub struct NewReno { /* private fields */ }
    Expand description

    A simple, standard congestion controller

    +NewReno in iroh_quinn_proto::congestion - Rust

    NewReno

    Struct NewReno 

    Source
    pub struct NewReno { /* private fields */ }
    Expand description

    A simple, standard congestion controller

    Implementations§

    Source§

    impl NewReno

    Source

    pub fn new(config: Arc<NewRenoConfig>, now: Instant, current_mtu: u16) -> Self

    Construct a state using the given config and current time now

    Trait Implementations§

    Source§

    impl Clone for NewReno

    Source§

    fn clone(&self) -> NewReno

    Returns a duplicate of the value. Read more
    1.0.0 · Source§

    fn clone_from(&mut self, source: &Self)

    Performs copy-assignment from source. Read more
    Source§

    impl Controller for NewReno

    Source§

    fn on_ack( &mut self, diff --git a/pr/255/docs/iroh_quinn_proto/congestion/struct.NewRenoConfig.html b/pr/255/docs/iroh_quinn_proto/congestion/struct.NewRenoConfig.html index 9d618e249..5328eaa38 100644 --- a/pr/255/docs/iroh_quinn_proto/congestion/struct.NewRenoConfig.html +++ b/pr/255/docs/iroh_quinn_proto/congestion/struct.NewRenoConfig.html @@ -1,4 +1,4 @@ -NewRenoConfig in iroh_quinn_proto::congestion - Rust

    NewRenoConfig

    Struct NewRenoConfig 

    Source
    pub struct NewRenoConfig { /* private fields */ }
    Expand description

    Configuration for the NewReno congestion controller

    +NewRenoConfig in iroh_quinn_proto::congestion - Rust

    NewRenoConfig

    Struct NewRenoConfig 

    Source
    pub struct NewRenoConfig { /* private fields */ }
    Expand description

    Configuration for the NewReno congestion controller

    Implementations§

    Source§

    impl NewRenoConfig

    Source

    pub fn initial_window(&mut self, value: u64) -> &mut Self

    Default limit on the amount of outstanding data in bytes.

    Recommended value: min(10 * max_datagram_size, max(2 * max_datagram_size, 14720))

    Source

    pub fn loss_reduction_factor(&mut self, value: f32) -> &mut Self

    Reduction in congestion window when a new loss event is detected.

    diff --git a/pr/255/docs/iroh_quinn_proto/congestion/trait.Controller.html b/pr/255/docs/iroh_quinn_proto/congestion/trait.Controller.html index b57591df3..f4888d696 100644 --- a/pr/255/docs/iroh_quinn_proto/congestion/trait.Controller.html +++ b/pr/255/docs/iroh_quinn_proto/congestion/trait.Controller.html @@ -1,4 +1,4 @@ -Controller in iroh_quinn_proto::congestion - Rust

    Controller

    Trait Controller 

    Source
    pub trait Controller:
    +Controller in iroh_quinn_proto::congestion - Rust

    Controller

    Trait Controller 

    Source
    pub trait Controller:
         Send
         + Sync
         + Debug {
    diff --git a/pr/255/docs/iroh_quinn_proto/congestion/trait.ControllerFactory.html b/pr/255/docs/iroh_quinn_proto/congestion/trait.ControllerFactory.html
    index 8e98dac9d..cddde05fd 100644
    --- a/pr/255/docs/iroh_quinn_proto/congestion/trait.ControllerFactory.html
    +++ b/pr/255/docs/iroh_quinn_proto/congestion/trait.ControllerFactory.html
    @@ -1,4 +1,4 @@
    -ControllerFactory in iroh_quinn_proto::congestion - Rust

    ControllerFactory

    Trait ControllerFactory 

    Source
    pub trait ControllerFactory {
    +ControllerFactory in iroh_quinn_proto::congestion - Rust

    ControllerFactory

    Trait ControllerFactory 

    Source
    pub trait ControllerFactory {
         // Required method
         fn build(
             self: Arc<Self>,
    diff --git a/pr/255/docs/iroh_quinn_proto/constant.DEFAULT_CONCURRENT_MULTIPATH_PATHS_WHEN_ENABLED.html b/pr/255/docs/iroh_quinn_proto/constant.DEFAULT_CONCURRENT_MULTIPATH_PATHS_WHEN_ENABLED.html
    index 20952ccea..697595e72 100644
    --- a/pr/255/docs/iroh_quinn_proto/constant.DEFAULT_CONCURRENT_MULTIPATH_PATHS_WHEN_ENABLED.html
    +++ b/pr/255/docs/iroh_quinn_proto/constant.DEFAULT_CONCURRENT_MULTIPATH_PATHS_WHEN_ENABLED.html
    @@ -1,3 +1,3 @@
    -DEFAULT_CONCURRENT_MULTIPATH_PATHS_WHEN_ENABLED in iroh_quinn_proto - Rust

    DEFAULT_CONCURRENT_MULTIPATH_PATHS_WHEN_ENABLED

    Constant DEFAULT_CONCURRENT_MULTIPATH_PATHS_WHEN_ENABLED 

    Source
    pub const DEFAULT_CONCURRENT_MULTIPATH_PATHS_WHEN_ENABLED: NonZeroU32;
    Expand description

    When multipath is required and has not been explicitly enabled, this value will be used for

    +DEFAULT_CONCURRENT_MULTIPATH_PATHS_WHEN_ENABLED in iroh_quinn_proto - Rust

    DEFAULT_CONCURRENT_MULTIPATH_PATHS_WHEN_ENABLED

    Constant DEFAULT_CONCURRENT_MULTIPATH_PATHS_WHEN_ENABLED 

    Source
    pub const DEFAULT_CONCURRENT_MULTIPATH_PATHS_WHEN_ENABLED: NonZeroU32;
    Expand description

    When multipath is required and has not been explicitly enabled, this value will be used for

    TransportConfig::max_concurrent_multipath_paths.

    \ No newline at end of file diff --git a/pr/255/docs/iroh_quinn_proto/constant.DEFAULT_SUPPORTED_VERSIONS.html b/pr/255/docs/iroh_quinn_proto/constant.DEFAULT_SUPPORTED_VERSIONS.html index b3e942496..dbcd33bd3 100644 --- a/pr/255/docs/iroh_quinn_proto/constant.DEFAULT_SUPPORTED_VERSIONS.html +++ b/pr/255/docs/iroh_quinn_proto/constant.DEFAULT_SUPPORTED_VERSIONS.html @@ -1,2 +1,2 @@ -DEFAULT_SUPPORTED_VERSIONS in iroh_quinn_proto - Rust

    DEFAULT_SUPPORTED_VERSIONS

    Constant DEFAULT_SUPPORTED_VERSIONS 

    Source
    pub const DEFAULT_SUPPORTED_VERSIONS: &[u32];
    Expand description

    The QUIC protocol version implemented.

    +DEFAULT_SUPPORTED_VERSIONS in iroh_quinn_proto - Rust

    DEFAULT_SUPPORTED_VERSIONS

    Constant DEFAULT_SUPPORTED_VERSIONS 

    Source
    pub const DEFAULT_SUPPORTED_VERSIONS: &[u32];
    Expand description

    The QUIC protocol version implemented.

    \ No newline at end of file diff --git a/pr/255/docs/iroh_quinn_proto/crypto/index.html b/pr/255/docs/iroh_quinn_proto/crypto/index.html index f315f347c..7ed775f0b 100644 --- a/pr/255/docs/iroh_quinn_proto/crypto/index.html +++ b/pr/255/docs/iroh_quinn_proto/crypto/index.html @@ -1,4 +1,4 @@ -iroh_quinn_proto::crypto - Rust

    Module crypto

    Module crypto 

    Source
    Expand description

    Traits and implementations for the QUIC cryptography protocol

    +iroh_quinn_proto::crypto - Rust

    Module crypto

    Module crypto 

    Source
    Expand description

    Traits and implementations for the QUIC cryptography protocol

    The protocol logic in Quinn is contained in types that abstract over the actual cryptographic protocol used. This module contains the traits used for this abstraction layer as well as a single implementation of these traits that uses diff --git a/pr/255/docs/iroh_quinn_proto/crypto/rustls/enum.Error.html b/pr/255/docs/iroh_quinn_proto/crypto/rustls/enum.Error.html index 20765085f..c2044990b 100644 --- a/pr/255/docs/iroh_quinn_proto/crypto/rustls/enum.Error.html +++ b/pr/255/docs/iroh_quinn_proto/crypto/rustls/enum.Error.html @@ -1,4 +1,4 @@ -Error in iroh_quinn_proto::crypto::rustls - Rust

    Error

    Enum Error 

    #[non_exhaustive]
    pub enum Error { +Error in iroh_quinn_proto::crypto::rustls - Rust

    Error

    Enum Error 

    #[non_exhaustive]
    pub enum Error {
    Show 22 variants InappropriateMessage { expect_types: Vec<ContentType>, got_type: ContentType, diff --git a/pr/255/docs/iroh_quinn_proto/crypto/rustls/index.html b/pr/255/docs/iroh_quinn_proto/crypto/rustls/index.html index 96919ee18..0bb19bef3 100644 --- a/pr/255/docs/iroh_quinn_proto/crypto/rustls/index.html +++ b/pr/255/docs/iroh_quinn_proto/crypto/rustls/index.html @@ -1,2 +1,2 @@ -iroh_quinn_proto::crypto::rustls - Rust

    Module rustls

    Module rustls 

    Source
    Expand description

    TLS interface based on rustls

    +iroh_quinn_proto::crypto::rustls - Rust

    Module rustls

    Module rustls 

    Source
    Expand description

    TLS interface based on rustls

    Structs§

    HandshakeData
    Authentication data for (rustls) TLS session
    NoInitialCipherSuite
    The initial cipher suite (AES-128-GCM-SHA256) is not available
    QuicClientConfig
    A QUIC-compatible TLS client configuration
    QuicServerConfig
    A QUIC-compatible TLS server configuration
    TlsSession
    A rustls TLS session

    Enums§

    Error
    rustls reports protocol errors using this type.
    \ No newline at end of file diff --git a/pr/255/docs/iroh_quinn_proto/crypto/rustls/struct.HandshakeData.html b/pr/255/docs/iroh_quinn_proto/crypto/rustls/struct.HandshakeData.html index e170d4694..1f8e698a2 100644 --- a/pr/255/docs/iroh_quinn_proto/crypto/rustls/struct.HandshakeData.html +++ b/pr/255/docs/iroh_quinn_proto/crypto/rustls/struct.HandshakeData.html @@ -1,4 +1,4 @@ -HandshakeData in iroh_quinn_proto::crypto::rustls - Rust

    HandshakeData

    Struct HandshakeData 

    Source
    pub struct HandshakeData {
    +HandshakeData in iroh_quinn_proto::crypto::rustls - Rust

    HandshakeData

    Struct HandshakeData 

    Source
    pub struct HandshakeData {
         pub protocol: Option<Vec<u8>>,
         pub server_name: Option<String>,
         pub negotiated_key_exchange_group: NamedGroup,
    diff --git a/pr/255/docs/iroh_quinn_proto/crypto/rustls/struct.NoInitialCipherSuite.html b/pr/255/docs/iroh_quinn_proto/crypto/rustls/struct.NoInitialCipherSuite.html
    index 929b72d9f..bb27427aa 100644
    --- a/pr/255/docs/iroh_quinn_proto/crypto/rustls/struct.NoInitialCipherSuite.html
    +++ b/pr/255/docs/iroh_quinn_proto/crypto/rustls/struct.NoInitialCipherSuite.html
    @@ -1,4 +1,4 @@
    -NoInitialCipherSuite in iroh_quinn_proto::crypto::rustls - Rust

    NoInitialCipherSuite

    Struct NoInitialCipherSuite 

    Source
    pub struct NoInitialCipherSuite { /* private fields */ }
    Expand description

    The initial cipher suite (AES-128-GCM-SHA256) is not available

    +NoInitialCipherSuite in iroh_quinn_proto::crypto::rustls - Rust

    NoInitialCipherSuite

    Struct NoInitialCipherSuite 

    Source
    pub struct NoInitialCipherSuite { /* private fields */ }
    Expand description

    The initial cipher suite (AES-128-GCM-SHA256) is not available

    When the cipher suite is supplied with_initial(), it must be [CipherSuite::TLS13_AES_128_GCM_SHA256]. When the cipher suite is derived from a config’s CryptoProvider, that provider must reference a cipher suite with the same ID.

    diff --git a/pr/255/docs/iroh_quinn_proto/crypto/rustls/struct.QuicClientConfig.html b/pr/255/docs/iroh_quinn_proto/crypto/rustls/struct.QuicClientConfig.html index 353aed3a5..56d8327b9 100644 --- a/pr/255/docs/iroh_quinn_proto/crypto/rustls/struct.QuicClientConfig.html +++ b/pr/255/docs/iroh_quinn_proto/crypto/rustls/struct.QuicClientConfig.html @@ -1,4 +1,4 @@ -QuicClientConfig in iroh_quinn_proto::crypto::rustls - Rust

    QuicClientConfig

    Struct QuicClientConfig 

    Source
    pub struct QuicClientConfig { /* private fields */ }
    Expand description

    A QUIC-compatible TLS client configuration

    +QuicClientConfig in iroh_quinn_proto::crypto::rustls - Rust

    QuicClientConfig

    Struct QuicClientConfig 

    Source
    pub struct QuicClientConfig { /* private fields */ }
    Expand description

    A QUIC-compatible TLS client configuration

    Quinn implicitly constructs a QuicClientConfig with reasonable defaults within ClientConfig::with_root_certificates() and ClientConfig::with_platform_verifier(). Alternatively, QuicClientConfig’s TryFrom implementation can be used to wrap around a diff --git a/pr/255/docs/iroh_quinn_proto/crypto/rustls/struct.QuicServerConfig.html b/pr/255/docs/iroh_quinn_proto/crypto/rustls/struct.QuicServerConfig.html index bb1d795f3..d5801f0e9 100644 --- a/pr/255/docs/iroh_quinn_proto/crypto/rustls/struct.QuicServerConfig.html +++ b/pr/255/docs/iroh_quinn_proto/crypto/rustls/struct.QuicServerConfig.html @@ -1,4 +1,4 @@ -QuicServerConfig in iroh_quinn_proto::crypto::rustls - Rust

    QuicServerConfig

    Struct QuicServerConfig 

    Source
    pub struct QuicServerConfig { /* private fields */ }
    Expand description

    A QUIC-compatible TLS server configuration

    +QuicServerConfig in iroh_quinn_proto::crypto::rustls - Rust

    QuicServerConfig

    Struct QuicServerConfig 

    Source
    pub struct QuicServerConfig { /* private fields */ }
    Expand description

    A QUIC-compatible TLS server configuration

    Quinn implicitly constructs a QuicServerConfig with reasonable defaults within ServerConfig::with_single_cert(). Alternatively, QuicServerConfig’s TryFrom implementation or with_initial method can be used to wrap around a custom diff --git a/pr/255/docs/iroh_quinn_proto/crypto/rustls/struct.TlsSession.html b/pr/255/docs/iroh_quinn_proto/crypto/rustls/struct.TlsSession.html index d2e01165f..5a27fcded 100644 --- a/pr/255/docs/iroh_quinn_proto/crypto/rustls/struct.TlsSession.html +++ b/pr/255/docs/iroh_quinn_proto/crypto/rustls/struct.TlsSession.html @@ -1,4 +1,4 @@ -TlsSession in iroh_quinn_proto::crypto::rustls - Rust

    TlsSession

    Struct TlsSession 

    Source
    pub struct TlsSession { /* private fields */ }
    Expand description

    A rustls TLS session

    +TlsSession in iroh_quinn_proto::crypto::rustls - Rust

    TlsSession

    Struct TlsSession 

    Source
    pub struct TlsSession { /* private fields */ }
    Expand description

    A rustls TLS session

    Trait Implementations§

    Source§

    impl Session for TlsSession

    Source§

    fn peer_identity(&self) -> Option<Box<dyn Any>>

    For the rustls TlsSession, the Any type is Vec<rustls::pki_types::CertificateDer>

    Source§

    fn initial_keys(&self, dst_cid: ConnectionId, side: Side) -> Keys

    Create the initial set of keys given the client’s initial destination ConnectionId
    Source§

    fn handshake_data(&self) -> Option<Box<dyn Any>>

    Get data negotiated during the handshake, if available Read more
    Source§

    fn early_crypto(&self) -> Option<(Box<dyn HeaderKey>, Box<dyn PacketKey>)>

    Get the 0-RTT keys if available (clients only) Read more
    Source§

    fn early_data_accepted(&self) -> Option<bool>

    If the 0-RTT-encrypted data has been accepted by the peer
    Source§

    fn is_handshaking(&self) -> bool

    Returns true until the connection is fully established.
    Source§

    fn read_handshake(&mut self, buf: &[u8]) -> Result<bool, TransportError>

    Read bytes of handshake data Read more
    Source§

    fn transport_parameters( &self, diff --git a/pr/255/docs/iroh_quinn_proto/crypto/struct.CryptoError.html b/pr/255/docs/iroh_quinn_proto/crypto/struct.CryptoError.html index 096170b26..012193d63 100644 --- a/pr/255/docs/iroh_quinn_proto/crypto/struct.CryptoError.html +++ b/pr/255/docs/iroh_quinn_proto/crypto/struct.CryptoError.html @@ -1,4 +1,4 @@ -CryptoError in iroh_quinn_proto::crypto - Rust

    CryptoError

    Struct CryptoError 

    Source
    pub struct CryptoError;
    Expand description

    Generic crypto errors

    +CryptoError in iroh_quinn_proto::crypto - Rust

    CryptoError

    Struct CryptoError 

    Source
    pub struct CryptoError;
    Expand description

    Generic crypto errors

    Trait Implementations§

    Source§

    impl Debug for CryptoError

    Source§

    fn fmt(&self, f: &mut Formatter<'_>) -> Result

    Formats the value using the given formatter. Read more
    Source§

    impl From<Unspecified> for CryptoError

    Source§

    fn from(_: Unspecified) -> Self

    Converts to this type from the input type.

    Auto Trait Implementations§

    Blanket Implementations§

    Source§

    impl<T> Any for T
    where T: 'static + ?Sized,

    Source§

    fn type_id(&self) -> TypeId

    Gets the TypeId of self. Read more
    Source§

    impl<T> Borrow<T> for T
    where T: ?Sized,

    Source§

    fn borrow(&self) -> &T

    Immutably borrows from an owned value. Read more
    Source§

    impl<T> BorrowMut<T> for T
    where diff --git a/pr/255/docs/iroh_quinn_proto/crypto/struct.ExportKeyingMaterialError.html b/pr/255/docs/iroh_quinn_proto/crypto/struct.ExportKeyingMaterialError.html index 9fca4b488..630d28672 100644 --- a/pr/255/docs/iroh_quinn_proto/crypto/struct.ExportKeyingMaterialError.html +++ b/pr/255/docs/iroh_quinn_proto/crypto/struct.ExportKeyingMaterialError.html @@ -1,4 +1,4 @@ -ExportKeyingMaterialError in iroh_quinn_proto::crypto - Rust

    ExportKeyingMaterialError

    Struct ExportKeyingMaterialError 

    Source
    pub struct ExportKeyingMaterialError;
    Expand description

    Error returned by Session::export_keying_material.

    +ExportKeyingMaterialError in iroh_quinn_proto::crypto - Rust

    ExportKeyingMaterialError

    Struct ExportKeyingMaterialError 

    Source
    pub struct ExportKeyingMaterialError;
    Expand description

    Error returned by Session::export_keying_material.

    This error occurs if the requested output length is too large.

    Trait Implementations§

    Source§

    impl Debug for ExportKeyingMaterialError

    Source§

    fn fmt(&self, f: &mut Formatter<'_>) -> Result

    Formats the value using the given formatter. Read more
    Source§

    impl PartialEq for ExportKeyingMaterialError

    Source§

    fn eq(&self, other: &ExportKeyingMaterialError) -> bool

    Tests for self and other values to be equal, and is used by ==.
    1.0.0 · Source§

    fn ne(&self, other: &Rhs) -> bool

    Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
    Source§

    impl Eq for ExportKeyingMaterialError

    Source§

    impl StructuralPartialEq for ExportKeyingMaterialError

    Auto Trait Implementations§

    Blanket Implementations§

    Source§

    impl<T> Any for T
    where diff --git a/pr/255/docs/iroh_quinn_proto/crypto/struct.KeyPair.html b/pr/255/docs/iroh_quinn_proto/crypto/struct.KeyPair.html index fbfd5d65d..171e56950 100644 --- a/pr/255/docs/iroh_quinn_proto/crypto/struct.KeyPair.html +++ b/pr/255/docs/iroh_quinn_proto/crypto/struct.KeyPair.html @@ -1,4 +1,4 @@ -KeyPair in iroh_quinn_proto::crypto - Rust

    KeyPair

    Struct KeyPair 

    Source
    pub struct KeyPair<T> {
    +KeyPair in iroh_quinn_proto::crypto - Rust

    KeyPair

    Struct KeyPair 

    Source
    pub struct KeyPair<T> {
         pub local: T,
         pub remote: T,
     }
    Expand description

    A pair of keys for bidirectional communication

    diff --git a/pr/255/docs/iroh_quinn_proto/crypto/struct.Keys.html b/pr/255/docs/iroh_quinn_proto/crypto/struct.Keys.html index cfb062097..0a921c42f 100644 --- a/pr/255/docs/iroh_quinn_proto/crypto/struct.Keys.html +++ b/pr/255/docs/iroh_quinn_proto/crypto/struct.Keys.html @@ -1,4 +1,4 @@ -Keys in iroh_quinn_proto::crypto - Rust

    Keys

    Struct Keys 

    Source
    pub struct Keys {
    +Keys in iroh_quinn_proto::crypto - Rust

    Keys

    Struct Keys 

    Source
    pub struct Keys {
         pub header: KeyPair<Box<dyn HeaderKey>>,
         pub packet: KeyPair<Box<dyn PacketKey>>,
     }
    Expand description

    A complete set of keys for a certain packet space

    diff --git a/pr/255/docs/iroh_quinn_proto/crypto/struct.UnsupportedVersion.html b/pr/255/docs/iroh_quinn_proto/crypto/struct.UnsupportedVersion.html index 0d7e13f7e..71680e154 100644 --- a/pr/255/docs/iroh_quinn_proto/crypto/struct.UnsupportedVersion.html +++ b/pr/255/docs/iroh_quinn_proto/crypto/struct.UnsupportedVersion.html @@ -1,4 +1,4 @@ -UnsupportedVersion in iroh_quinn_proto::crypto - Rust

    UnsupportedVersion

    Struct UnsupportedVersion 

    Source
    pub struct UnsupportedVersion;
    Expand description

    Error indicating that the specified QUIC version is not supported

    +UnsupportedVersion in iroh_quinn_proto::crypto - Rust

    UnsupportedVersion

    Struct UnsupportedVersion 

    Source
    pub struct UnsupportedVersion;
    Expand description

    Error indicating that the specified QUIC version is not supported

    Trait Implementations§

    Source§

    impl Debug for UnsupportedVersion

    Source§

    fn fmt(&self, f: &mut Formatter<'_>) -> Result

    Formats the value using the given formatter. Read more
    Source§

    impl From<UnsupportedVersion> for ConnectError

    Source§

    fn from(_: UnsupportedVersion) -> Self

    Converts to this type from the input type.

    Auto Trait Implementations§

    Blanket Implementations§

    Source§

    impl<T> Any for T
    where T: 'static + ?Sized,

    Source§

    fn type_id(&self) -> TypeId

    Gets the TypeId of self. Read more
    Source§

    impl<T> Borrow<T> for T
    where T: ?Sized,

    Source§

    fn borrow(&self) -> &T

    Immutably borrows from an owned value. Read more
    Source§

    impl<T> BorrowMut<T> for T
    where diff --git a/pr/255/docs/iroh_quinn_proto/crypto/trait.AeadKey.html b/pr/255/docs/iroh_quinn_proto/crypto/trait.AeadKey.html index e1abdf405..bab18eb43 100644 --- a/pr/255/docs/iroh_quinn_proto/crypto/trait.AeadKey.html +++ b/pr/255/docs/iroh_quinn_proto/crypto/trait.AeadKey.html @@ -1,4 +1,4 @@ -AeadKey in iroh_quinn_proto::crypto - Rust

    AeadKey

    Trait AeadKey 

    Source
    pub trait AeadKey {
    +AeadKey in iroh_quinn_proto::crypto - Rust

    AeadKey

    Trait AeadKey 

    Source
    pub trait AeadKey {
         // Required methods
         fn seal(
             &self,
    diff --git a/pr/255/docs/iroh_quinn_proto/crypto/trait.ClientConfig.html b/pr/255/docs/iroh_quinn_proto/crypto/trait.ClientConfig.html
    index b45349488..4c3291188 100644
    --- a/pr/255/docs/iroh_quinn_proto/crypto/trait.ClientConfig.html
    +++ b/pr/255/docs/iroh_quinn_proto/crypto/trait.ClientConfig.html
    @@ -1,4 +1,4 @@
    -ClientConfig in iroh_quinn_proto::crypto - Rust

    ClientConfig

    Trait ClientConfig 

    Source
    pub trait ClientConfig: Send + Sync {
    +ClientConfig in iroh_quinn_proto::crypto - Rust

    ClientConfig

    Trait ClientConfig 

    Source
    pub trait ClientConfig: Send + Sync {
         // Required method
         fn start_session(
             self: Arc<Self>,
    diff --git a/pr/255/docs/iroh_quinn_proto/crypto/trait.HandshakeTokenKey.html b/pr/255/docs/iroh_quinn_proto/crypto/trait.HandshakeTokenKey.html
    index ca4a39808..58f268f25 100644
    --- a/pr/255/docs/iroh_quinn_proto/crypto/trait.HandshakeTokenKey.html
    +++ b/pr/255/docs/iroh_quinn_proto/crypto/trait.HandshakeTokenKey.html
    @@ -1,4 +1,4 @@
    -HandshakeTokenKey in iroh_quinn_proto::crypto - Rust

    HandshakeTokenKey

    Trait HandshakeTokenKey 

    Source
    pub trait HandshakeTokenKey: Send + Sync {
    +HandshakeTokenKey in iroh_quinn_proto::crypto - Rust

    HandshakeTokenKey

    Trait HandshakeTokenKey 

    Source
    pub trait HandshakeTokenKey: Send + Sync {
         // Required method
         fn aead_from_hkdf(&self, random_bytes: &[u8]) -> Box<dyn AeadKey>;
     }
    Expand description

    A pseudo random key for HKDF

    diff --git a/pr/255/docs/iroh_quinn_proto/crypto/trait.HeaderKey.html b/pr/255/docs/iroh_quinn_proto/crypto/trait.HeaderKey.html index cc36c1859..57f2aa774 100644 --- a/pr/255/docs/iroh_quinn_proto/crypto/trait.HeaderKey.html +++ b/pr/255/docs/iroh_quinn_proto/crypto/trait.HeaderKey.html @@ -1,4 +1,4 @@ -HeaderKey in iroh_quinn_proto::crypto - Rust

    HeaderKey

    Trait HeaderKey 

    Source
    pub trait HeaderKey: Send + Sync {
    +HeaderKey in iroh_quinn_proto::crypto - Rust

    HeaderKey

    Trait HeaderKey 

    Source
    pub trait HeaderKey: Send + Sync {
         // Required methods
         fn decrypt(&self, pn_offset: usize, packet: &mut [u8]);
         fn encrypt(&self, pn_offset: usize, packet: &mut [u8]);
    diff --git a/pr/255/docs/iroh_quinn_proto/crypto/trait.HmacKey.html b/pr/255/docs/iroh_quinn_proto/crypto/trait.HmacKey.html
    index 26cf8079b..f3fc2bdff 100644
    --- a/pr/255/docs/iroh_quinn_proto/crypto/trait.HmacKey.html
    +++ b/pr/255/docs/iroh_quinn_proto/crypto/trait.HmacKey.html
    @@ -1,4 +1,4 @@
    -HmacKey in iroh_quinn_proto::crypto - Rust

    HmacKey

    Trait HmacKey 

    Source
    pub trait HmacKey: Send + Sync {
    +HmacKey in iroh_quinn_proto::crypto - Rust

    HmacKey

    Trait HmacKey 

    Source
    pub trait HmacKey: Send + Sync {
         // Required methods
         fn sign(&self, data: &[u8], signature_out: &mut [u8]);
         fn signature_len(&self) -> usize;
    diff --git a/pr/255/docs/iroh_quinn_proto/crypto/trait.PacketKey.html b/pr/255/docs/iroh_quinn_proto/crypto/trait.PacketKey.html
    index 737f4ef77..d62e41c85 100644
    --- a/pr/255/docs/iroh_quinn_proto/crypto/trait.PacketKey.html
    +++ b/pr/255/docs/iroh_quinn_proto/crypto/trait.PacketKey.html
    @@ -1,4 +1,4 @@
    -PacketKey in iroh_quinn_proto::crypto - Rust

    PacketKey

    Trait PacketKey 

    Source
    pub trait PacketKey: Send + Sync {
    +PacketKey in iroh_quinn_proto::crypto - Rust

    PacketKey

    Trait PacketKey 

    Source
    pub trait PacketKey: Send + Sync {
         // Required methods
         fn encrypt(
             &self,
    diff --git a/pr/255/docs/iroh_quinn_proto/crypto/trait.ServerConfig.html b/pr/255/docs/iroh_quinn_proto/crypto/trait.ServerConfig.html
    index d540cbd8e..7c8a3d4d8 100644
    --- a/pr/255/docs/iroh_quinn_proto/crypto/trait.ServerConfig.html
    +++ b/pr/255/docs/iroh_quinn_proto/crypto/trait.ServerConfig.html
    @@ -1,4 +1,4 @@
    -ServerConfig in iroh_quinn_proto::crypto - Rust

    ServerConfig

    Trait ServerConfig 

    Source
    pub trait ServerConfig: Send + Sync {
    +ServerConfig in iroh_quinn_proto::crypto - Rust

    ServerConfig

    Trait ServerConfig 

    Source
    pub trait ServerConfig: Send + Sync {
         // Required methods
         fn initial_keys(
             &self,
    diff --git a/pr/255/docs/iroh_quinn_proto/crypto/trait.Session.html b/pr/255/docs/iroh_quinn_proto/crypto/trait.Session.html
    index cb10cecaa..1b12ac7e2 100644
    --- a/pr/255/docs/iroh_quinn_proto/crypto/trait.Session.html
    +++ b/pr/255/docs/iroh_quinn_proto/crypto/trait.Session.html
    @@ -1,4 +1,4 @@
    -Session in iroh_quinn_proto::crypto - Rust

    Session

    Trait Session 

    Source
    pub trait Session:
    +Session in iroh_quinn_proto::crypto - Rust

    Session

    Trait Session 

    Source
    pub trait Session:
         Send
         + Sync
         + 'static {
    diff --git a/pr/255/docs/iroh_quinn_proto/enum.ClosePathError.html b/pr/255/docs/iroh_quinn_proto/enum.ClosePathError.html
    index f2631dafb..02d875e7c 100644
    --- a/pr/255/docs/iroh_quinn_proto/enum.ClosePathError.html
    +++ b/pr/255/docs/iroh_quinn_proto/enum.ClosePathError.html
    @@ -1,4 +1,4 @@
    -ClosePathError in iroh_quinn_proto - Rust

    ClosePathError

    Enum ClosePathError 

    Source
    pub enum ClosePathError {
    +ClosePathError in iroh_quinn_proto - Rust

    ClosePathError

    Enum ClosePathError 

    Source
    pub enum ClosePathError {
         ClosedPath,
         LastOpenPath,
     }
    Expand description

    Errors triggered when abandoning a path

    diff --git a/pr/255/docs/iroh_quinn_proto/enum.ConfigError.html b/pr/255/docs/iroh_quinn_proto/enum.ConfigError.html index dad9b87e9..75c59e163 100644 --- a/pr/255/docs/iroh_quinn_proto/enum.ConfigError.html +++ b/pr/255/docs/iroh_quinn_proto/enum.ConfigError.html @@ -1,4 +1,4 @@ -ConfigError in iroh_quinn_proto - Rust

    ConfigError

    Enum ConfigError 

    Source
    #[non_exhaustive]
    pub enum ConfigError { +ConfigError in iroh_quinn_proto - Rust

    ConfigError

    Enum ConfigError 

    Source
    #[non_exhaustive]
    pub enum ConfigError { OutOfBounds, }
    Expand description

    Errors in the configuration of an endpoint

    Variants (Non-exhaustive)§

    This enum is marked as non-exhaustive
    Non-exhaustive enums could have additional variants added in future. Therefore, when matching against variants of non-exhaustive enums, an extra wildcard arm must be added to account for any future variants.
    §

    OutOfBounds

    Value exceeds supported bounds

    diff --git a/pr/255/docs/iroh_quinn_proto/enum.ConnectError.html b/pr/255/docs/iroh_quinn_proto/enum.ConnectError.html index 428ecd896..212bf8180 100644 --- a/pr/255/docs/iroh_quinn_proto/enum.ConnectError.html +++ b/pr/255/docs/iroh_quinn_proto/enum.ConnectError.html @@ -1,4 +1,4 @@ -ConnectError in iroh_quinn_proto - Rust

    ConnectError

    Enum ConnectError 

    Source
    pub enum ConnectError {
    +ConnectError in iroh_quinn_proto - Rust

    ConnectError

    Enum ConnectError 

    Source
    pub enum ConnectError {
         EndpointStopping,
         CidsExhausted,
         InvalidServerName(String),
    diff --git a/pr/255/docs/iroh_quinn_proto/enum.ConnectionError.html b/pr/255/docs/iroh_quinn_proto/enum.ConnectionError.html
    index 5276fea61..284a9f387 100644
    --- a/pr/255/docs/iroh_quinn_proto/enum.ConnectionError.html
    +++ b/pr/255/docs/iroh_quinn_proto/enum.ConnectionError.html
    @@ -1,4 +1,4 @@
    -ConnectionError in iroh_quinn_proto - Rust

    ConnectionError

    Enum ConnectionError 

    Source
    pub enum ConnectionError {
    +ConnectionError in iroh_quinn_proto - Rust

    ConnectionError

    Enum ConnectionError 

    Source
    pub enum ConnectionError {
         VersionMismatch,
         TransportError(TransportError),
         ConnectionClosed(ConnectionClose),
    diff --git a/pr/255/docs/iroh_quinn_proto/enum.DatagramEvent.html b/pr/255/docs/iroh_quinn_proto/enum.DatagramEvent.html
    index 84cf0f163..2f66a49ac 100644
    --- a/pr/255/docs/iroh_quinn_proto/enum.DatagramEvent.html
    +++ b/pr/255/docs/iroh_quinn_proto/enum.DatagramEvent.html
    @@ -1,4 +1,4 @@
    -DatagramEvent in iroh_quinn_proto - Rust

    DatagramEvent

    Enum DatagramEvent 

    Source
    pub enum DatagramEvent {
    +DatagramEvent in iroh_quinn_proto - Rust

    DatagramEvent

    Enum DatagramEvent 

    Source
    pub enum DatagramEvent {
         ConnectionEvent(ConnectionHandle, ConnectionEvent),
         NewConnection(Incoming),
         Response(Transmit),
    diff --git a/pr/255/docs/iroh_quinn_proto/enum.Dir.html b/pr/255/docs/iroh_quinn_proto/enum.Dir.html
    index 277b0a09f..29d7e4f54 100644
    --- a/pr/255/docs/iroh_quinn_proto/enum.Dir.html
    +++ b/pr/255/docs/iroh_quinn_proto/enum.Dir.html
    @@ -1,4 +1,4 @@
    -Dir in iroh_quinn_proto - Rust

    Dir

    Enum Dir 

    Source
    pub enum Dir {
    +Dir in iroh_quinn_proto - Rust

    Dir

    Enum Dir 

    Source
    pub enum Dir {
         Bi = 0,
         Uni = 1,
     }
    Expand description

    Whether a stream communicates data in both directions or only from the initiator

    diff --git a/pr/255/docs/iroh_quinn_proto/enum.EcnCodepoint.html b/pr/255/docs/iroh_quinn_proto/enum.EcnCodepoint.html index bc04c010d..1902c2953 100644 --- a/pr/255/docs/iroh_quinn_proto/enum.EcnCodepoint.html +++ b/pr/255/docs/iroh_quinn_proto/enum.EcnCodepoint.html @@ -1,4 +1,4 @@ -EcnCodepoint in iroh_quinn_proto - Rust

    EcnCodepoint

    Enum EcnCodepoint 

    Source
    #[repr(u8)]
    pub enum EcnCodepoint { +EcnCodepoint in iroh_quinn_proto - Rust

    EcnCodepoint

    Enum EcnCodepoint 

    Source
    #[repr(u8)]
    pub enum EcnCodepoint { Ect0 = 2, Ect1 = 1, Ce = 3, diff --git a/pr/255/docs/iroh_quinn_proto/enum.Event.html b/pr/255/docs/iroh_quinn_proto/enum.Event.html index b545403c4..01c8225cc 100644 --- a/pr/255/docs/iroh_quinn_proto/enum.Event.html +++ b/pr/255/docs/iroh_quinn_proto/enum.Event.html @@ -1,4 +1,4 @@ -Event in iroh_quinn_proto - Rust

    Event

    Enum Event 

    Source
    pub enum Event {
    +Event in iroh_quinn_proto - Rust

    Event

    Enum Event 

    Source
    pub enum Event {
         HandshakeDataReady,
         Connected,
         HandshakeConfirmed,
    diff --git a/pr/255/docs/iroh_quinn_proto/enum.FinishError.html b/pr/255/docs/iroh_quinn_proto/enum.FinishError.html
    index 660398d07..7e2265853 100644
    --- a/pr/255/docs/iroh_quinn_proto/enum.FinishError.html
    +++ b/pr/255/docs/iroh_quinn_proto/enum.FinishError.html
    @@ -1,4 +1,4 @@
    -FinishError in iroh_quinn_proto - Rust

    FinishError

    Enum FinishError 

    Source
    pub enum FinishError {
    +FinishError in iroh_quinn_proto - Rust

    FinishError

    Enum FinishError 

    Source
    pub enum FinishError {
         Stopped(VarInt),
         ClosedStream,
     }
    Expand description

    Reasons why attempting to finish a stream might fail

    @@ -6,8 +6,8 @@ StreamEvent::Finished event will be emitted for this stream.

    Carries an application-defined error code.

    §

    ClosedStream

    The stream has not been opened or was already finished or reset

    -

    Trait Implementations§

    Source§

    impl Clone for FinishError

    Source§

    fn clone(&self) -> FinishError

    Returns a duplicate of the value. Read more
    1.0.0 · Source§

    fn clone_from(&mut self, source: &Self)

    Performs copy-assignment from source. Read more
    Source§

    impl Debug for FinishError

    Source§

    fn fmt(&self, f: &mut Formatter<'_>) -> Result

    Formats the value using the given formatter. Read more
    Source§

    impl Display for FinishError

    Source§

    fn fmt(&self, __formatter: &mut Formatter<'_>) -> Result

    Formats the value using the given formatter. Read more
    Source§

    impl Error for FinishError

    1.30.0 · Source§

    fn source(&self) -> Option<&(dyn Error + 'static)>

    Returns the lower-level source of this error, if any. Read more
    1.0.0 · Source§

    fn description(&self) -> &str

    👎Deprecated since 1.42.0: use the Display impl or to_string()
    1.0.0 · Source§

    fn cause(&self) -> Option<&dyn Error>

    👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
    Source§

    fn provide<'a>(&'a self, request: &mut Request<'a>)

    🔬This is a nightly-only experimental API. (error_generic_member_access)
    Provides type-based access to context intended for error reports. Read more
    Source§

    impl PartialEq for FinishError

    Source§

    fn eq(&self, other: &FinishError) -> bool

    Tests for self and other values to be equal, and is used by ==.
    1.0.0 · Source§

    fn ne(&self, other: &Rhs) -> bool

    Tests for !=. The default implementation is almost always sufficient, -and should not be overridden without very good reason.
    Source§

    impl Eq for FinishError

    Source§

    impl StructuralPartialEq for FinishError

    Auto Trait Implementations§

    Blanket Implementations§

    Source§

    impl<T> Any for T
    where +

    Trait Implementations§

    Source§

    impl Clone for FinishError

    Source§

    fn clone(&self) -> FinishError

    Returns a duplicate of the value. Read more
    1.0.0 · Source§

    fn clone_from(&mut self, source: &Self)

    Performs copy-assignment from source. Read more
    Source§

    impl Debug for FinishError

    Source§

    fn fmt(&self, f: &mut Formatter<'_>) -> Result

    Formats the value using the given formatter. Read more
    Source§

    impl Display for FinishError

    Source§

    fn fmt(&self, __formatter: &mut Formatter<'_>) -> Result

    Formats the value using the given formatter. Read more
    Source§

    impl Error for FinishError

    1.30.0 · Source§

    fn source(&self) -> Option<&(dyn Error + 'static)>

    Returns the lower-level source of this error, if any. Read more
    1.0.0 · Source§

    fn description(&self) -> &str

    👎Deprecated since 1.42.0: use the Display impl or to_string()
    1.0.0 · Source§

    fn cause(&self) -> Option<&dyn Error>

    👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
    Source§

    fn provide<'a>(&'a self, request: &mut Request<'a>)

    🔬This is a nightly-only experimental API. (error_generic_member_access)
    Provides type-based access to context intended for error reports. Read more
    Source§

    impl PartialEq for FinishError

    Source§

    fn eq(&self, other: &FinishError) -> bool

    Tests for self and other values to be equal, and is used by ==.
    1.0.0 · Source§

    fn ne(&self, other: &Rhs) -> bool

    Tests for !=. The default implementation is almost always sufficient, +and should not be overridden without very good reason.
    Source§

    impl Eq for FinishError

    Source§

    impl StructuralPartialEq for FinishError

    Auto Trait Implementations§

    Blanket Implementations§

    Source§

    impl<T> Any for T
    where T: 'static + ?Sized,

    Source§

    fn type_id(&self) -> TypeId

    Gets the TypeId of self. Read more
    Source§

    impl<T> Borrow<T> for T
    where T: ?Sized,

    Source§

    fn borrow(&self) -> &T

    Immutably borrows from an owned value. Read more
    Source§

    impl<T> BorrowMut<T> for T
    where T: ?Sized,

    Source§

    fn borrow_mut(&mut self) -> &mut T

    Mutably borrows from an owned value. Read more
    Source§

    impl<T> CloneToUninit for T
    where diff --git a/pr/255/docs/iroh_quinn_proto/enum.FrameType.html b/pr/255/docs/iroh_quinn_proto/enum.FrameType.html index 04ae717ef..674bc43ea 100644 --- a/pr/255/docs/iroh_quinn_proto/enum.FrameType.html +++ b/pr/255/docs/iroh_quinn_proto/enum.FrameType.html @@ -1,4 +1,4 @@ -FrameType in iroh_quinn_proto - Rust

    FrameType

    Enum FrameType 

    Source
    pub enum FrameType {
    +FrameType in iroh_quinn_proto - Rust

    FrameType

    Enum FrameType 

    Source
    pub enum FrameType {
     
    Show 44 variants Padding, Ping, Ack, @@ -43,9 +43,8 @@ ReachOutAtIpv4, ReachOutAtIpv6, RemoveAddress, -
    }
    Expand description

    A QUIC frame type

    -

    Variants§

    §

    Padding

    §

    Ping

    §

    Ack

    §

    AckEcn

    §

    ResetStream

    §

    StopSending

    §

    Crypto

    §

    NewToken

    §

    Stream(StreamInfo)

    §

    MaxData

    §

    MaxStreamData

    §

    MaxStreamsBidi

    §

    MaxStreamsUni

    §

    DataBlocked

    §

    StreamDataBlocked

    §

    StreamsBlockedBidi

    §

    StreamsBlockedUni

    §

    NewConnectionId

    §

    RetireConnectionId

    §

    PathChallenge

    §

    PathResponse

    §

    ConnectionClose

    §

    ApplicationClose

    §

    HandshakeDone

    §

    AckFrequency

    §

    ImmediateAck

    §

    Datagram(DatagramInfo)

    §

    ObservedIpv4Addr

    §

    ObservedIpv6Addr

    §

    PathAck

    §

    PathAckEcn

    §

    PathAbandon

    §

    PathStatusBackup

    §

    PathStatusAvailable

    §

    PathNewConnectionId

    §

    PathRetireConnectionId

    §

    MaxPathId

    §

    PathsBlocked

    §

    PathCidsBlocked

    §

    AddIpv4Address

    §

    AddIpv6Address

    §

    ReachOutAtIpv4

    §

    ReachOutAtIpv6

    §

    RemoveAddress

    Trait Implementations§

    Source§

    impl Clone for FrameType

    Source§

    fn clone(&self) -> FrameType

    Returns a duplicate of the value. Read more
    1.0.0 · Source§

    fn clone_from(&mut self, source: &Self)

    Performs copy-assignment from source. Read more
    Source§

    impl Debug for FrameType

    Source§

    fn fmt(&self, __derive_more_f: &mut Formatter<'_>) -> Result

    Formats the value using the given formatter. Read more
    Source§

    impl Decodable for FrameType

    Source§

    fn decode<B: Buf>(buf: &mut B) -> Result<Self>

    Decode a Self from the provided buffer, if the buffer is large enough
    Source§

    impl Display for FrameType

    Source§

    fn fmt(&self, __derive_more_f: &mut Formatter<'_>) -> Result

    Formats the value using the given formatter. Read more
    Source§

    impl Encodable for FrameType

    Source§

    fn encode<B: BufMut>(&self, buf: &mut B)

    Append the encoding of self to the provided buffer.
    Source§

    impl PartialEq for FrameType

    Source§

    fn eq(&self, other: &FrameType) -> bool

    Tests for self and other values to be equal, and is used by ==.
    1.0.0 · Source§

    fn ne(&self, other: &Rhs) -> bool

    Tests for !=. The default implementation is almost always sufficient, -and should not be overridden without very good reason.
    Source§

    impl TryFrom<u64> for FrameType

    Source§

    type Error = InvalidFrameId

    The type returned in the event of a conversion error.
    Source§

    fn try_from(value: u64) -> Result<Self, Self::Error>

    Performs the conversion.
    Source§

    impl Copy for FrameType

    Source§

    impl Eq for FrameType

    Source§

    impl StructuralPartialEq for FrameType

    Auto Trait Implementations§

    Blanket Implementations§

    Source§

    impl<T> Any for T
    where +

    }

    Variants§

    §

    Padding

    §

    Ping

    §

    Ack

    §

    AckEcn

    §

    ResetStream

    §

    StopSending

    §

    Crypto

    §

    NewToken

    §

    Stream(StreamInfo)

    §

    MaxData

    §

    MaxStreamData

    §

    MaxStreamsBidi

    §

    MaxStreamsUni

    §

    DataBlocked

    §

    StreamDataBlocked

    §

    StreamsBlockedBidi

    §

    StreamsBlockedUni

    §

    NewConnectionId

    §

    RetireConnectionId

    §

    PathChallenge

    §

    PathResponse

    §

    ConnectionClose

    §

    ApplicationClose

    §

    HandshakeDone

    §

    AckFrequency

    §

    ImmediateAck

    §

    Datagram(DatagramInfo)

    §

    ObservedIpv4Addr

    §

    ObservedIpv6Addr

    §

    PathAck

    §

    PathAckEcn

    §

    PathAbandon

    §

    PathStatusBackup

    §

    PathStatusAvailable

    §

    PathNewConnectionId

    §

    PathRetireConnectionId

    §

    MaxPathId

    §

    PathsBlocked

    §

    PathCidsBlocked

    §

    AddIpv4Address

    §

    AddIpv6Address

    §

    ReachOutAtIpv4

    §

    ReachOutAtIpv6

    §

    RemoveAddress

    Trait Implementations§

    Source§

    impl Clone for FrameType

    Source§

    fn clone(&self) -> FrameType

    Returns a duplicate of the value. Read more
    1.0.0 · Source§

    fn clone_from(&mut self, source: &Self)

    Performs copy-assignment from source. Read more
    Source§

    impl Debug for FrameType

    Source§

    fn fmt(&self, __derive_more_f: &mut Formatter<'_>) -> Result

    Formats the value using the given formatter. Read more
    Source§

    impl Decodable for FrameType

    Source§

    fn decode<B: Buf>(buf: &mut B) -> Result<Self>

    Decode a Self from the provided buffer, if the buffer is large enough
    Source§

    impl Display for FrameType

    Source§

    fn fmt(&self, __derive_more_f: &mut Formatter<'_>) -> Result

    Formats the value using the given formatter. Read more
    Source§

    impl Encodable for FrameType

    Source§

    fn encode<B: BufMut>(&self, buf: &mut B)

    Append the encoding of self to the provided buffer.
    Source§

    impl PartialEq for FrameType

    Source§

    fn eq(&self, other: &FrameType) -> bool

    Tests for self and other values to be equal, and is used by ==.
    1.0.0 · Source§

    fn ne(&self, other: &Rhs) -> bool

    Tests for !=. The default implementation is almost always sufficient, +and should not be overridden without very good reason.
    Source§

    impl TryFrom<u64> for FrameType

    Source§

    type Error = InvalidFrameId

    The type returned in the event of a conversion error.
    Source§

    fn try_from(value: u64) -> Result<Self, Self::Error>

    Performs the conversion.
    Source§

    impl Copy for FrameType

    Source§

    impl Eq for FrameType

    Source§

    impl StructuralPartialEq for FrameType

    Auto Trait Implementations§

    Blanket Implementations§

    Source§

    impl<T> Any for T
    where T: 'static + ?Sized,

    Source§

    fn type_id(&self) -> TypeId

    Gets the TypeId of self. Read more
    Source§

    impl<T> Borrow<T> for T
    where T: ?Sized,

    Source§

    fn borrow(&self) -> &T

    Immutably borrows from an owned value. Read more
    Source§

    impl<T> BorrowMut<T> for T
    where T: ?Sized,

    Source§

    fn borrow_mut(&mut self) -> &mut T

    Mutably borrows from an owned value. Read more
    Source§

    impl<T> CloneToUninit for T
    where diff --git a/pr/255/docs/iroh_quinn_proto/enum.LongType.html b/pr/255/docs/iroh_quinn_proto/enum.LongType.html index cbd494dbb..8f07318d2 100644 --- a/pr/255/docs/iroh_quinn_proto/enum.LongType.html +++ b/pr/255/docs/iroh_quinn_proto/enum.LongType.html @@ -1,4 +1,4 @@ -LongType in iroh_quinn_proto - Rust

    LongType

    Enum LongType 

    Source
    pub enum LongType {
    +LongType in iroh_quinn_proto - Rust

    LongType

    Enum LongType 

    Source
    pub enum LongType {
         Handshake,
         ZeroRtt,
     }
    Expand description

    Long packet types with uniform header structure

    diff --git a/pr/255/docs/iroh_quinn_proto/enum.PacketDecodeError.html b/pr/255/docs/iroh_quinn_proto/enum.PacketDecodeError.html index f9f1e48f1..ae013578f 100644 --- a/pr/255/docs/iroh_quinn_proto/enum.PacketDecodeError.html +++ b/pr/255/docs/iroh_quinn_proto/enum.PacketDecodeError.html @@ -1,4 +1,4 @@ -PacketDecodeError in iroh_quinn_proto - Rust

    PacketDecodeError

    Enum PacketDecodeError 

    Source
    pub enum PacketDecodeError {
    +PacketDecodeError in iroh_quinn_proto - Rust

    PacketDecodeError

    Enum PacketDecodeError 

    Source
    pub enum PacketDecodeError {
         UnsupportedVersion {
             src_cid: ConnectionId,
             dst_cid: ConnectionId,
    diff --git a/pr/255/docs/iroh_quinn_proto/enum.PathError.html b/pr/255/docs/iroh_quinn_proto/enum.PathError.html
    index 9d90ceb03..9b5979fac 100644
    --- a/pr/255/docs/iroh_quinn_proto/enum.PathError.html
    +++ b/pr/255/docs/iroh_quinn_proto/enum.PathError.html
    @@ -1,4 +1,4 @@
    -PathError in iroh_quinn_proto - Rust

    PathError

    Enum PathError 

    Source
    pub enum PathError {
    +PathError in iroh_quinn_proto - Rust

    PathError

    Enum PathError 

    Source
    pub enum PathError {
         MultipathNotNegotiated,
         ServerSideNotAllowed,
         MaxPathIdReached,
    diff --git a/pr/255/docs/iroh_quinn_proto/enum.PathEvent.html b/pr/255/docs/iroh_quinn_proto/enum.PathEvent.html
    index ca5d9ec0e..682088cd1 100644
    --- a/pr/255/docs/iroh_quinn_proto/enum.PathEvent.html
    +++ b/pr/255/docs/iroh_quinn_proto/enum.PathEvent.html
    @@ -1,4 +1,4 @@
    -PathEvent in iroh_quinn_proto - Rust

    PathEvent

    Enum PathEvent 

    Source
    pub enum PathEvent {
    +PathEvent in iroh_quinn_proto - Rust

    PathEvent

    Enum PathEvent 

    Source
    pub enum PathEvent {
         Opened {
             id: PathId,
         },
    diff --git a/pr/255/docs/iroh_quinn_proto/enum.PathStatus.html b/pr/255/docs/iroh_quinn_proto/enum.PathStatus.html
    index 5318c4db4..f5e5880cd 100644
    --- a/pr/255/docs/iroh_quinn_proto/enum.PathStatus.html
    +++ b/pr/255/docs/iroh_quinn_proto/enum.PathStatus.html
    @@ -1,4 +1,4 @@
    -PathStatus in iroh_quinn_proto - Rust

    PathStatus

    Enum PathStatus 

    Source
    pub enum PathStatus {
    +PathStatus in iroh_quinn_proto - Rust

    PathStatus

    Enum PathStatus 

    Source
    pub enum PathStatus {
         Available,
         Backup,
     }
    Expand description

    The QUIC-MULTIPATH path status

    diff --git a/pr/255/docs/iroh_quinn_proto/enum.ProtectedHeader.html b/pr/255/docs/iroh_quinn_proto/enum.ProtectedHeader.html index 649046f60..35912ec51 100644 --- a/pr/255/docs/iroh_quinn_proto/enum.ProtectedHeader.html +++ b/pr/255/docs/iroh_quinn_proto/enum.ProtectedHeader.html @@ -1,4 +1,4 @@ -ProtectedHeader in iroh_quinn_proto - Rust

    ProtectedHeader

    Enum ProtectedHeader 

    Source
    pub enum ProtectedHeader {
    +ProtectedHeader in iroh_quinn_proto - Rust

    ProtectedHeader

    Enum ProtectedHeader 

    Source
    pub enum ProtectedHeader {
         Initial(ProtectedInitialHeader),
         Long {
             ty: LongType,
    diff --git a/pr/255/docs/iroh_quinn_proto/enum.ReadError.html b/pr/255/docs/iroh_quinn_proto/enum.ReadError.html
    index 74f8a512f..b48a7205a 100644
    --- a/pr/255/docs/iroh_quinn_proto/enum.ReadError.html
    +++ b/pr/255/docs/iroh_quinn_proto/enum.ReadError.html
    @@ -1,4 +1,4 @@
    -ReadError in iroh_quinn_proto - Rust

    ReadError

    Enum ReadError 

    Source
    pub enum ReadError {
    +ReadError in iroh_quinn_proto - Rust

    ReadError

    Enum ReadError 

    Source
    pub enum ReadError {
         Blocked,
         Reset(VarInt),
     }
    Expand description

    Errors triggered when reading from a recv stream

    diff --git a/pr/255/docs/iroh_quinn_proto/enum.ReadableError.html b/pr/255/docs/iroh_quinn_proto/enum.ReadableError.html index 8213c3e0a..831d99698 100644 --- a/pr/255/docs/iroh_quinn_proto/enum.ReadableError.html +++ b/pr/255/docs/iroh_quinn_proto/enum.ReadableError.html @@ -1,4 +1,4 @@ -ReadableError in iroh_quinn_proto - Rust

    ReadableError

    Enum ReadableError 

    Source
    pub enum ReadableError {
    +ReadableError in iroh_quinn_proto - Rust

    ReadableError

    Enum ReadableError 

    Source
    pub enum ReadableError {
         ClosedStream,
         IllegalOrderedRead,
     }
    Expand description

    Errors triggered when opening a recv stream for reading

    diff --git a/pr/255/docs/iroh_quinn_proto/enum.SendDatagramError.html b/pr/255/docs/iroh_quinn_proto/enum.SendDatagramError.html index c3f0463e1..cb460b1ab 100644 --- a/pr/255/docs/iroh_quinn_proto/enum.SendDatagramError.html +++ b/pr/255/docs/iroh_quinn_proto/enum.SendDatagramError.html @@ -1,4 +1,4 @@ -SendDatagramError in iroh_quinn_proto - Rust

    SendDatagramError

    Enum SendDatagramError 

    Source
    pub enum SendDatagramError {
    +SendDatagramError in iroh_quinn_proto - Rust

    SendDatagramError

    Enum SendDatagramError 

    Source
    pub enum SendDatagramError {
         UnsupportedByPeer,
         Disabled,
         TooLarge,
    diff --git a/pr/255/docs/iroh_quinn_proto/enum.SetPathStatusError.html b/pr/255/docs/iroh_quinn_proto/enum.SetPathStatusError.html
    index 0140b49ad..bc7faf94b 100644
    --- a/pr/255/docs/iroh_quinn_proto/enum.SetPathStatusError.html
    +++ b/pr/255/docs/iroh_quinn_proto/enum.SetPathStatusError.html
    @@ -1,4 +1,4 @@
    -SetPathStatusError in iroh_quinn_proto - Rust

    SetPathStatusError

    Enum SetPathStatusError 

    Source
    pub enum SetPathStatusError {
    +SetPathStatusError in iroh_quinn_proto - Rust

    SetPathStatusError

    Enum SetPathStatusError 

    Source
    pub enum SetPathStatusError {
         ClosedPath,
         MultipathNotNegotiated,
     }
    Expand description

    Error from setting path status

    diff --git a/pr/255/docs/iroh_quinn_proto/enum.Side.html b/pr/255/docs/iroh_quinn_proto/enum.Side.html index 2f7721962..1d2227792 100644 --- a/pr/255/docs/iroh_quinn_proto/enum.Side.html +++ b/pr/255/docs/iroh_quinn_proto/enum.Side.html @@ -1,4 +1,4 @@ -Side in iroh_quinn_proto - Rust

    Side

    Enum Side 

    Source
    pub enum Side {
    +Side in iroh_quinn_proto - Rust

    Side

    Enum Side 

    Source
    pub enum Side {
         Client = 0,
         Server = 1,
     }
    Expand description

    Whether an endpoint was the initiator of a connection

    diff --git a/pr/255/docs/iroh_quinn_proto/enum.StreamEvent.html b/pr/255/docs/iroh_quinn_proto/enum.StreamEvent.html index 98a80dc3d..52a5abb4a 100644 --- a/pr/255/docs/iroh_quinn_proto/enum.StreamEvent.html +++ b/pr/255/docs/iroh_quinn_proto/enum.StreamEvent.html @@ -1,4 +1,4 @@ -StreamEvent in iroh_quinn_proto - Rust

    StreamEvent

    Enum StreamEvent 

    Source
    pub enum StreamEvent {
    +StreamEvent in iroh_quinn_proto - Rust

    StreamEvent

    Enum StreamEvent 

    Source
    pub enum StreamEvent {
         Opened {
             dir: Dir,
         },
    @@ -33,8 +33,8 @@
     
    §error_code: VarInt

    Error code supplied by the peer

    §

    Available

    At least one new stream of a certain directionality may be opened

    Fields

    §dir: Dir

    Directionality for which streams are newly available

    -

    Trait Implementations§

    Source§

    impl Debug for StreamEvent

    Source§

    fn fmt(&self, f: &mut Formatter<'_>) -> Result

    Formats the value using the given formatter. Read more
    Source§

    impl PartialEq for StreamEvent

    Source§

    fn eq(&self, other: &StreamEvent) -> bool

    Tests for self and other values to be equal, and is used by ==.
    1.0.0 · Source§

    fn ne(&self, other: &Rhs) -> bool

    Tests for !=. The default implementation is almost always sufficient, -and should not be overridden without very good reason.
    Source§

    impl Eq for StreamEvent

    Source§

    impl StructuralPartialEq for StreamEvent

    Auto Trait Implementations§

    Blanket Implementations§

    Source§

    impl<T> Any for T
    where +

    Trait Implementations§

    Source§

    impl Debug for StreamEvent

    Source§

    fn fmt(&self, f: &mut Formatter<'_>) -> Result

    Formats the value using the given formatter. Read more
    Source§

    impl PartialEq for StreamEvent

    Source§

    fn eq(&self, other: &StreamEvent) -> bool

    Tests for self and other values to be equal, and is used by ==.
    1.0.0 · Source§

    fn ne(&self, other: &Rhs) -> bool

    Tests for !=. The default implementation is almost always sufficient, +and should not be overridden without very good reason.
    Source§

    impl Eq for StreamEvent

    Source§

    impl StructuralPartialEq for StreamEvent

    Auto Trait Implementations§

    Blanket Implementations§

    Source§

    impl<T> Any for T
    where T: 'static + ?Sized,

    Source§

    fn type_id(&self) -> TypeId

    Gets the TypeId of self. Read more
    Source§

    impl<T> Borrow<T> for T
    where T: ?Sized,

    Source§

    fn borrow(&self) -> &T

    Immutably borrows from an owned value. Read more
    Source§

    impl<T> BorrowMut<T> for T
    where T: ?Sized,

    Source§

    fn borrow_mut(&mut self) -> &mut T

    Mutably borrows from an owned value. Read more
    §

    impl<Q, K> Equivalent<K> for Q
    where diff --git a/pr/255/docs/iroh_quinn_proto/enum.WriteError.html b/pr/255/docs/iroh_quinn_proto/enum.WriteError.html index 6047c4ea6..b1df6fa67 100644 --- a/pr/255/docs/iroh_quinn_proto/enum.WriteError.html +++ b/pr/255/docs/iroh_quinn_proto/enum.WriteError.html @@ -1,4 +1,4 @@ -WriteError in iroh_quinn_proto - Rust

    WriteError

    Enum WriteError 

    Source
    pub enum WriteError {
    +WriteError in iroh_quinn_proto - Rust

    WriteError

    Enum WriteError 

    Source
    pub enum WriteError {
         Blocked,
         Stopped(VarInt),
         ClosedStream,
    @@ -10,16 +10,16 @@ be generated, indicating that retrying the write might succeed.

    stream cannot be finished or further written to.

    Carries an application-defined error code.

    §

    ClosedStream

    The stream has not been opened or has already been finished or reset

    -

    Trait Implementations§

    Source§

    impl Clone for WriteError

    Source§

    fn clone(&self) -> WriteError

    Returns a duplicate of the value. Read more
    1.0.0 · Source§

    fn clone_from(&mut self, source: &Self)

    Performs copy-assignment from source. Read more
    Source§

    impl Debug for WriteError

    Source§

    fn fmt(&self, f: &mut Formatter<'_>) -> Result

    Formats the value using the given formatter. Read more
    Source§

    impl Display for WriteError

    Source§

    fn fmt(&self, __formatter: &mut Formatter<'_>) -> Result

    Formats the value using the given formatter. Read more
    Source§

    impl Error for WriteError

    1.30.0 · Source§

    fn source(&self) -> Option<&(dyn Error + 'static)>

    Returns the lower-level source of this error, if any. Read more
    1.0.0 · Source§

    fn description(&self) -> &str

    👎Deprecated since 1.42.0: use the Display impl or to_string()
    1.0.0 · Source§

    fn cause(&self) -> Option<&dyn Error>

    👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
    Source§

    fn provide<'a>(&'a self, request: &mut Request<'a>)

    🔬This is a nightly-only experimental API. (error_generic_member_access)
    Provides type-based access to context intended for error reports. Read more
    Source§

    impl Hash for WriteError

    Source§

    fn hash<__H: Hasher>(&self, state: &mut __H)

    Feeds this value into the given Hasher. Read more
    1.3.0 · Source§

    fn hash_slice<H>(data: &[Self], state: &mut H)
    where +

    Trait Implementations§

    Source§

    impl Clone for WriteError

    Source§

    fn clone(&self) -> WriteError

    Returns a duplicate of the value. Read more
    1.0.0 · Source§

    fn clone_from(&mut self, source: &Self)

    Performs copy-assignment from source. Read more
    Source§

    impl Debug for WriteError

    Source§

    fn fmt(&self, f: &mut Formatter<'_>) -> Result

    Formats the value using the given formatter. Read more
    Source§

    impl Display for WriteError

    Source§

    fn fmt(&self, __formatter: &mut Formatter<'_>) -> Result

    Formats the value using the given formatter. Read more
    Source§

    impl Error for WriteError

    1.30.0 · Source§

    fn source(&self) -> Option<&(dyn Error + 'static)>

    Returns the lower-level source of this error, if any. Read more
    1.0.0 · Source§

    fn description(&self) -> &str

    👎Deprecated since 1.42.0: use the Display impl or to_string()
    1.0.0 · Source§

    fn cause(&self) -> Option<&dyn Error>

    👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
    Source§

    fn provide<'a>(&'a self, request: &mut Request<'a>)

    🔬This is a nightly-only experimental API. (error_generic_member_access)
    Provides type-based access to context intended for error reports. Read more
    Source§

    impl Hash for WriteError

    Source§

    fn hash<__H: Hasher>(&self, state: &mut __H)

    Feeds this value into the given Hasher. Read more
    1.3.0 · Source§

    fn hash_slice<H>(data: &[Self], state: &mut H)
    where H: Hasher, - Self: Sized,

    Feeds a slice of this type into the given Hasher. Read more
    Source§

    impl Ord for WriteError

    Source§

    fn cmp(&self, other: &WriteError) -> Ordering

    This method returns an Ordering between self and other. Read more
    1.21.0 · Source§

    fn max(self, other: Self) -> Self
    where + Self: Sized,

    Feeds a slice of this type into the given Hasher. Read more
    Source§

    impl Ord for WriteError

    Source§

    fn cmp(&self, other: &WriteError) -> Ordering

    This method returns an Ordering between self and other. Read more
    1.21.0 · Source§

    fn max(self, other: Self) -> Self
    where Self: Sized,

    Compares and returns the maximum of two values. Read more
    1.21.0 · Source§

    fn min(self, other: Self) -> Self
    where Self: Sized,

    Compares and returns the minimum of two values. Read more
    1.50.0 · Source§

    fn clamp(self, min: Self, max: Self) -> Self
    where - Self: Sized,

    Restrict a value to a certain interval. Read more
    Source§

    impl PartialEq for WriteError

    Source§

    fn eq(&self, other: &WriteError) -> bool

    Tests for self and other values to be equal, and is used by ==.
    1.0.0 · Source§

    fn ne(&self, other: &Rhs) -> bool

    Tests for !=. The default implementation is almost always sufficient, -and should not be overridden without very good reason.
    Source§

    impl PartialOrd for WriteError

    Source§

    fn partial_cmp(&self, other: &WriteError) -> Option<Ordering>

    This method returns an ordering between self and other values if one exists. Read more
    1.0.0 · Source§

    fn lt(&self, other: &Rhs) -> bool

    Tests less than (for self and other) and is used by the < operator. Read more
    1.0.0 · Source§

    fn le(&self, other: &Rhs) -> bool

    Tests less than or equal to (for self and other) and is used by the + Self: Sized,

    Restrict a value to a certain interval. Read more
    Source§

    impl PartialEq for WriteError

    Source§

    fn eq(&self, other: &WriteError) -> bool

    Tests for self and other values to be equal, and is used by ==.
    1.0.0 · Source§

    fn ne(&self, other: &Rhs) -> bool

    Tests for !=. The default implementation is almost always sufficient, +and should not be overridden without very good reason.
    Source§

    impl PartialOrd for WriteError

    Source§

    fn partial_cmp(&self, other: &WriteError) -> Option<Ordering>

    This method returns an ordering between self and other values if one exists. Read more
    1.0.0 · Source§

    fn lt(&self, other: &Rhs) -> bool

    Tests less than (for self and other) and is used by the < operator. Read more
    1.0.0 · Source§

    fn le(&self, other: &Rhs) -> bool

    Tests less than or equal to (for self and other) and is used by the <= operator. Read more
    1.0.0 · Source§

    fn gt(&self, other: &Rhs) -> bool

    Tests greater than (for self and other) and is used by the > operator. Read more
    1.0.0 · Source§

    fn ge(&self, other: &Rhs) -> bool

    Tests greater than or equal to (for self and other) and is used by -the >= operator. Read more
    Source§

    impl Eq for WriteError

    Source§

    impl StructuralPartialEq for WriteError

    Auto Trait Implementations§

    Blanket Implementations§

    Source§

    impl<T> Any for T
    where +the >= operator. Read more

    Source§

    impl Eq for WriteError

    Source§

    impl StructuralPartialEq for WriteError

    Auto Trait Implementations§

    Blanket Implementations§

    Source§

    impl<T> Any for T
    where T: 'static + ?Sized,

    Source§

    fn type_id(&self) -> TypeId

    Gets the TypeId of self. Read more
    Source§

    impl<T> Borrow<T> for T
    where T: ?Sized,

    Source§

    fn borrow(&self) -> &T

    Immutably borrows from an owned value. Read more
    Source§

    impl<T> BorrowMut<T> for T
    where T: ?Sized,

    Source§

    fn borrow_mut(&mut self) -> &mut T

    Mutably borrows from an owned value. Read more
    Source§

    impl<T> CloneToUninit for T
    where diff --git a/pr/255/docs/iroh_quinn_proto/index.html b/pr/255/docs/iroh_quinn_proto/index.html index d6bf51224..7d9ff3932 100644 --- a/pr/255/docs/iroh_quinn_proto/index.html +++ b/pr/255/docs/iroh_quinn_proto/index.html @@ -1,4 +1,4 @@ -iroh_quinn_proto - Rust

    Crate iroh_quinn_proto

    Crate iroh_quinn_proto 

    Source
    Expand description

    Low-level protocol logic for the QUIC protoocol

    +iroh_quinn_proto - Rust

    Crate iroh_quinn_proto

    Crate iroh_quinn_proto 

    Source
    Expand description

    Low-level protocol logic for the QUIC protoocol

    quinn-proto contains a fully deterministic implementation of QUIC protocol logic. It contains no networking code and does not get any relevant timestamps from the operating system. Most users may want to use the futures-based quinn API instead.

    @@ -10,5 +10,5 @@ related Connection. Connection types contain the bulk managing a single connection and all the related state (such as streams).

    Re-exports§

    pub use rustls;

    Modules§

    bench_exports
    Exports for benchmarks
    coding
    Coding related traits.
    congestion
    Logic for controlling the rate at which data is sent
    crypto
    Traits and implementations for the QUIC cryptography protocol
    iroh_hp
    iroh NAT Traversal
    transport_parameters
    QUIC connection transport parameters

    Structs§

    AcceptError
    Error type for attempting to accept an Incoming
    AckFrequencyConfig
    Parameters for controlling the peer’s acknowledgement frequency
    ApplicationClose
    Reason given by an application for closing the connection
    BloomTokenLog
    Bloom filter-based TokenLog
    Chunk
    A chunk of data from the receive stream
    Chunks
    Chunks returned from RecvStream::read().
    ClientConfig
    Configuration for outgoing connections
    ClosedPath
    Error indicating that a path has not been opened or has already been abandoned
    ClosedStream
    Error indicating that a stream has not been opened or has already been finished or reset
    Connection
    Protocol state and logic for a single QUIC connection
    ConnectionClose
    Reason given by the transport for closing the connection
    ConnectionEvent
    Events sent from an Endpoint to a Connection
    ConnectionHandle
    Internal identifier for a Connection currently associated with an endpoint
    ConnectionId
    Protocol-level identifier for a connection.
    ConnectionStats
    Connection statistics
    Datagram
    An unreliable datagram
    Datagrams
    API to control datagram traffic
    Endpoint
    The main entry point to the library
    EndpointConfig
    Global configuration for the endpoint, affecting all connections
    EndpointEvent
    Events sent from a Connection to an Endpoint
    FixedLengthConnectionIdParser
    A ConnectionIdParser implementation that assumes the connection ID is of fixed length
    FourTuple
    Identifies a network path by the combination of remote and local addresses
    FrameStats
    Number of frames transmitted or received of each frame type
    HashedConnectionIdGenerator
    Generates 8-byte connection IDs that can be efficiently validated
    IdleTimeout
    Maximum duration of inactivity to accept before timing out the connection
    Incoming
    An incoming connection for which the server has not yet begun its part of the handshake.
    InvalidCid
    The connection ID was not recognized by the ConnectionIdGenerator
    MtuDiscoveryConfig
    Parameters governing MTU discovery.
    NoneTokenLog
    Null implementation of TokenLog, which never accepts tokens
    NoneTokenStore
    Null implementation of TokenStore, which does not store any tokens
    PartialDecode
    Decodes a QUIC packet’s invariant header
    PathId
    Id representing different paths when using multipath extension
    PathStats
    Statistics related to a transmission path
    ProtectedInitialHeader
    Header of an Initial packet, before decryption
    QlogConfig
    Configuration for qlog trace logging.
    QlogFileFactory
    Enables writing qlog traces to a directory.
    RandomConnectionIdGenerator
    Generates purely random connection IDs of a specified length
    RecvStream
    Access to streams
    RetryError
    Error for attempting to retry an Incoming which already bears a token from a previous retry
    RttEstimator
    RTT estimation for a particular network path
    SendStream
    Access to streams
    ServerConfig
    Parameters governing incoming connections
    ShouldTransmit
    Indicates whether a frame needs to be transmitted
    StdSystemTime
    Default implementation of TimeSource
    StreamId
    Identifier for a stream within a particular connection
    Streams
    Access to streams
    TokenMemoryCache
    TokenStore implementation that stores up to N tokens per server name for up to a -limited number of server names, in-memory
    TokenReuseError
    Error for when a validation token may have been reused
    Transmit
    An outgoing packet
    TransportConfig
    Parameters governing the core QUIC state machine
    TransportError
    Transport-level errors occur when a peer violates the protocol specification
    TransportErrorCode
    Transport-level error code
    UdpStats
    Statistics about UDP datagrams transmitted or received on a connection
    ValidationTokenConfig
    Configuration for sending and handling validation tokens in incoming connections
    VarInt
    An integer less than 2^62
    VarIntBoundsExceeded
    Error returned when constructing a VarInt from a value >= 2^62
    Written
    Indicates how many bytes and chunks had been transferred in a write operation

    Enums§

    ClosePathError
    Errors triggered when abandoning a path
    ConfigError
    Errors in the configuration of an endpoint
    ConnectError
    Errors in the parameters being used to create a new connection
    ConnectionError
    Reasons why a connection might be lost
    DatagramEvent
    Event resulting from processing a single datagram
    Dir
    Whether a stream communicates data in both directions or only from the initiator
    EcnCodepoint
    Explicit congestion notification codepoint
    Event
    Events of interest to the application
    FinishError
    Reasons why attempting to finish a stream might fail
    FrameType
    A QUIC frame type
    LongType
    Long packet types with uniform header structure
    PacketDecodeError
    Packet decode error
    PathError
    Errors that might trigger a path being closed
    PathEvent
    Application events about paths
    PathStatus
    The QUIC-MULTIPATH path status
    ProtectedHeader
    Plain packet header
    ReadError
    Errors triggered when reading from a recv stream
    ReadableError
    Errors triggered when opening a recv stream for reading
    SendDatagramError
    Errors that can arise when sending a datagram
    SetPathStatusError
    Error from setting path status
    Side
    Whether an endpoint was the initiator of a connection
    StreamEvent
    Application events about streams
    WriteError
    Errors triggered while writing to a send stream

    Constants§

    DEFAULT_CONCURRENT_MULTIPATH_PATHS_WHEN_ENABLED
    When multipath is required and has not been explicitly enabled, this value will be used for
    DEFAULT_SUPPORTED_VERSIONS
    The QUIC protocol version implemented.

    Traits§

    ConnectionIdGenerator
    Generates connection IDs for incoming connections
    ConnectionIdParser
    Parse connection id in short header packet
    QlogFactory
    Constructs a QlogConfig for individual connections.
    TimeSource
    Object to get current SystemTime
    TokenLog
    Responsible for limiting clients’ ability to reuse validation tokens
    TokenStore
    Responsible for storing validation tokens received from servers and retrieving them for use in +limited number of server names, in-memory
    TokenReuseError
    Error for when a validation token may have been reused
    Transmit
    An outgoing packet
    TransportConfig
    Parameters governing the core QUIC state machine
    TransportError
    Transport-level errors occur when a peer violates the protocol specification
    TransportErrorCode
    Transport-level error code
    UdpStats
    Statistics about UDP datagrams transmitted or received on a connection
    ValidationTokenConfig
    Configuration for sending and handling validation tokens in incoming connections
    VarInt
    An integer less than 2^62
    VarIntBoundsExceeded
    Error returned when constructing a VarInt from a value >= 2^62
    Written
    Indicates how many bytes and chunks had been transferred in a write operation

    Enums§

    ClosePathError
    Errors triggered when abandoning a path
    ConfigError
    Errors in the configuration of an endpoint
    ConnectError
    Errors in the parameters being used to create a new connection
    ConnectionError
    Reasons why a connection might be lost
    DatagramEvent
    Event resulting from processing a single datagram
    Dir
    Whether a stream communicates data in both directions or only from the initiator
    EcnCodepoint
    Explicit congestion notification codepoint
    Event
    Events of interest to the application
    FinishError
    Reasons why attempting to finish a stream might fail
    FrameType
    LongType
    Long packet types with uniform header structure
    PacketDecodeError
    Packet decode error
    PathError
    Errors that might trigger a path being closed
    PathEvent
    Application events about paths
    PathStatus
    The QUIC-MULTIPATH path status
    ProtectedHeader
    Plain packet header
    ReadError
    Errors triggered when reading from a recv stream
    ReadableError
    Errors triggered when opening a recv stream for reading
    SendDatagramError
    Errors that can arise when sending a datagram
    SetPathStatusError
    Error from setting path status
    Side
    Whether an endpoint was the initiator of a connection
    StreamEvent
    Application events about streams
    WriteError
    Errors triggered while writing to a send stream

    Constants§

    DEFAULT_CONCURRENT_MULTIPATH_PATHS_WHEN_ENABLED
    When multipath is required and has not been explicitly enabled, this value will be used for
    DEFAULT_SUPPORTED_VERSIONS
    The QUIC protocol version implemented.

    Traits§

    ConnectionIdGenerator
    Generates connection IDs for incoming connections
    ConnectionIdParser
    Parse connection id in short header packet
    QlogFactory
    Constructs a QlogConfig for individual connections.
    TimeSource
    Object to get current SystemTime
    TokenLog
    Responsible for limiting clients’ ability to reuse validation tokens
    TokenStore
    Responsible for storing validation tokens received from servers and retrieving them for use in subsequent connections
    \ No newline at end of file diff --git a/pr/255/docs/iroh_quinn_proto/iroh_hp/enum.Error.html b/pr/255/docs/iroh_quinn_proto/iroh_hp/enum.Error.html index e3a8c133a..c4b6d9ce6 100644 --- a/pr/255/docs/iroh_quinn_proto/iroh_hp/enum.Error.html +++ b/pr/255/docs/iroh_quinn_proto/iroh_hp/enum.Error.html @@ -1,4 +1,4 @@ -Error in iroh_quinn_proto::iroh_hp - Rust

    Error

    Enum Error 

    Source
    pub enum Error {
    +Error in iroh_quinn_proto::iroh_hp - Rust

    Error

    Enum Error 

    Source
    pub enum Error {
         TooManyAddresses,
         WrongConnectionSide,
         ExtensionNotNegotiated,
    diff --git a/pr/255/docs/iroh_quinn_proto/iroh_hp/enum.Event.html b/pr/255/docs/iroh_quinn_proto/iroh_hp/enum.Event.html
    index 29ca12c48..d14026f0e 100644
    --- a/pr/255/docs/iroh_quinn_proto/iroh_hp/enum.Event.html
    +++ b/pr/255/docs/iroh_quinn_proto/iroh_hp/enum.Event.html
    @@ -1,4 +1,4 @@
    -Event in iroh_quinn_proto::iroh_hp - Rust

    Event

    Enum Event 

    Source
    pub enum Event {
    +Event in iroh_quinn_proto::iroh_hp - Rust

    Event

    Enum Event 

    Source
    pub enum Event {
         AddressAdded(SocketAddr),
         AddressRemoved(SocketAddr),
     }
    Expand description

    Event emitted when the client receives ADD_ADDRESS or REMOVE_ADDRESS frames.

    diff --git a/pr/255/docs/iroh_quinn_proto/iroh_hp/index.html b/pr/255/docs/iroh_quinn_proto/iroh_hp/index.html index 7ca8317c0..b3aa066b9 100644 --- a/pr/255/docs/iroh_quinn_proto/iroh_hp/index.html +++ b/pr/255/docs/iroh_quinn_proto/iroh_hp/index.html @@ -1,2 +1,2 @@ -iroh_quinn_proto::iroh_hp - Rust

    Module iroh_hp

    Module iroh_hp 

    Source
    Expand description

    iroh NAT Traversal

    +iroh_quinn_proto::iroh_hp - Rust

    Module iroh_hp

    Module iroh_hp 

    Source
    Expand description

    iroh NAT Traversal

    Enums§

    Error
    Errors that the nat traversal state might encounter.
    Event
    Event emitted when the client receives ADD_ADDRESS or REMOVE_ADDRESS frames.
    \ No newline at end of file diff --git a/pr/255/docs/iroh_quinn_proto/struct.AcceptError.html b/pr/255/docs/iroh_quinn_proto/struct.AcceptError.html index 7be3486e3..20891dda1 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.AcceptError.html +++ b/pr/255/docs/iroh_quinn_proto/struct.AcceptError.html @@ -1,4 +1,4 @@ -AcceptError in iroh_quinn_proto - Rust

    AcceptError

    Struct AcceptError 

    Source
    pub struct AcceptError {
    +AcceptError in iroh_quinn_proto - Rust

    AcceptError

    Struct AcceptError 

    Source
    pub struct AcceptError {
         pub cause: ConnectionError,
         pub response: Option<Transmit>,
     }
    Expand description

    Error type for attempting to accept an Incoming

    diff --git a/pr/255/docs/iroh_quinn_proto/struct.AckFrequencyConfig.html b/pr/255/docs/iroh_quinn_proto/struct.AckFrequencyConfig.html index 3b8fd2463..427520e8d 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.AckFrequencyConfig.html +++ b/pr/255/docs/iroh_quinn_proto/struct.AckFrequencyConfig.html @@ -1,4 +1,4 @@ -AckFrequencyConfig in iroh_quinn_proto - Rust

    AckFrequencyConfig

    Struct AckFrequencyConfig 

    Source
    pub struct AckFrequencyConfig { /* private fields */ }
    Expand description

    Parameters for controlling the peer’s acknowledgement frequency

    +AckFrequencyConfig in iroh_quinn_proto - Rust

    AckFrequencyConfig

    Struct AckFrequencyConfig 

    Source
    pub struct AckFrequencyConfig { /* private fields */ }
    Expand description

    Parameters for controlling the peer’s acknowledgement frequency

    The parameters provided in this config will be sent to the peer at the beginning of the connection, so it can take them into account when sending acknowledgements (see each parameter’s description for details on how it influences acknowledgement frequency).

    diff --git a/pr/255/docs/iroh_quinn_proto/struct.ApplicationClose.html b/pr/255/docs/iroh_quinn_proto/struct.ApplicationClose.html index 1a5ef541d..54540d008 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.ApplicationClose.html +++ b/pr/255/docs/iroh_quinn_proto/struct.ApplicationClose.html @@ -1,11 +1,11 @@ -ApplicationClose in iroh_quinn_proto - Rust

    ApplicationClose

    Struct ApplicationClose 

    Source
    pub struct ApplicationClose {
    +ApplicationClose in iroh_quinn_proto - Rust

    ApplicationClose

    Struct ApplicationClose 

    Source
    pub struct ApplicationClose {
         pub error_code: VarInt,
         pub reason: Bytes,
     }
    Expand description

    Reason given by an application for closing the connection

    Fields§

    §error_code: VarInt

    Application-specific reason code

    §reason: Bytes

    Human-readable reason for the close

    -

    Trait Implementations§

    Source§

    impl Clone for ApplicationClose

    Source§

    fn clone(&self) -> ApplicationClose

    Returns a duplicate of the value. Read more
    1.0.0 · Source§

    fn clone_from(&mut self, source: &Self)

    Performs copy-assignment from source. Read more
    Source§

    impl Debug for ApplicationClose

    Source§

    fn fmt(&self, f: &mut Formatter<'_>) -> Result

    Formats the value using the given formatter. Read more
    Source§

    impl Display for ApplicationClose

    Source§

    fn fmt(&self, f: &mut Formatter<'_>) -> Result

    Formats the value using the given formatter. Read more
    Source§

    impl PartialEq for ApplicationClose

    Source§

    fn eq(&self, other: &ApplicationClose) -> bool

    Tests for self and other values to be equal, and is used by ==.
    1.0.0 · Source§

    fn ne(&self, other: &Rhs) -> bool

    Tests for !=. The default implementation is almost always sufficient, -and should not be overridden without very good reason.
    Source§

    impl Eq for ApplicationClose

    Source§

    impl StructuralPartialEq for ApplicationClose

    Auto Trait Implementations§

    Blanket Implementations§

    Source§

    impl<T> Any for T
    where +

    Trait Implementations§

    Source§

    impl Clone for ApplicationClose

    Source§

    fn clone(&self) -> ApplicationClose

    Returns a duplicate of the value. Read more
    1.0.0 · Source§

    fn clone_from(&mut self, source: &Self)

    Performs copy-assignment from source. Read more
    Source§

    impl Debug for ApplicationClose

    Source§

    fn fmt(&self, f: &mut Formatter<'_>) -> Result

    Formats the value using the given formatter. Read more
    Source§

    impl Display for ApplicationClose

    Source§

    fn fmt(&self, f: &mut Formatter<'_>) -> Result

    Formats the value using the given formatter. Read more
    Source§

    impl PartialEq for ApplicationClose

    Source§

    fn eq(&self, other: &ApplicationClose) -> bool

    Tests for self and other values to be equal, and is used by ==.
    1.0.0 · Source§

    fn ne(&self, other: &Rhs) -> bool

    Tests for !=. The default implementation is almost always sufficient, +and should not be overridden without very good reason.
    Source§

    impl Eq for ApplicationClose

    Source§

    impl StructuralPartialEq for ApplicationClose

    Auto Trait Implementations§

    Blanket Implementations§

    Source§

    impl<T> Any for T
    where T: 'static + ?Sized,

    Source§

    fn type_id(&self) -> TypeId

    Gets the TypeId of self. Read more
    Source§

    impl<T> Borrow<T> for T
    where T: ?Sized,

    Source§

    fn borrow(&self) -> &T

    Immutably borrows from an owned value. Read more
    Source§

    impl<T> BorrowMut<T> for T
    where T: ?Sized,

    Source§

    fn borrow_mut(&mut self) -> &mut T

    Mutably borrows from an owned value. Read more
    Source§

    impl<T> CloneToUninit for T
    where diff --git a/pr/255/docs/iroh_quinn_proto/struct.BloomTokenLog.html b/pr/255/docs/iroh_quinn_proto/struct.BloomTokenLog.html index 1f352b52f..322922097 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.BloomTokenLog.html +++ b/pr/255/docs/iroh_quinn_proto/struct.BloomTokenLog.html @@ -1,4 +1,4 @@ -BloomTokenLog in iroh_quinn_proto - Rust

    BloomTokenLog

    Struct BloomTokenLog 

    Source
    pub struct BloomTokenLog(/* private fields */);
    Expand description

    Bloom filter-based TokenLog

    +BloomTokenLog in iroh_quinn_proto - Rust

    BloomTokenLog

    Struct BloomTokenLog 

    Source
    pub struct BloomTokenLog(/* private fields */);
    Expand description

    Bloom filter-based TokenLog

    Parameterizable over an approximate maximum number of bytes to allocate. Starts out by storing used tokens in a hash set. Once the hash set becomes too large, converts it to a bloom filter. This achieves a memory profile of linear growth with an upper bound.

    diff --git a/pr/255/docs/iroh_quinn_proto/struct.Chunk.html b/pr/255/docs/iroh_quinn_proto/struct.Chunk.html index 3cf405208..13c532fbf 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.Chunk.html +++ b/pr/255/docs/iroh_quinn_proto/struct.Chunk.html @@ -1,4 +1,4 @@ -Chunk in iroh_quinn_proto - Rust

    Chunk

    Struct Chunk 

    Source
    pub struct Chunk {
    +Chunk in iroh_quinn_proto - Rust

    Chunk

    Struct Chunk 

    Source
    pub struct Chunk {
         pub offset: u64,
         pub bytes: Bytes,
     }
    Expand description

    A chunk of data from the receive stream

    diff --git a/pr/255/docs/iroh_quinn_proto/struct.Chunks.html b/pr/255/docs/iroh_quinn_proto/struct.Chunks.html index 559792dda..85a757548 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.Chunks.html +++ b/pr/255/docs/iroh_quinn_proto/struct.Chunks.html @@ -1,4 +1,4 @@ -Chunks in iroh_quinn_proto - Rust

    Chunks

    Struct Chunks 

    Source
    pub struct Chunks<'a> { /* private fields */ }
    Expand description

    Chunks returned from RecvStream::read().

    +Chunks in iroh_quinn_proto - Rust

    Chunks

    Struct Chunks 

    Source
    pub struct Chunks<'a> { /* private fields */ }
    Expand description

    Chunks returned from RecvStream::read().

    §Note: Finalization Needed

    Bytes read from the stream are not released from the congestion window until either Self::finalize() is called, or this type is dropped.

    diff --git a/pr/255/docs/iroh_quinn_proto/struct.ClientConfig.html b/pr/255/docs/iroh_quinn_proto/struct.ClientConfig.html index 5e7d545b9..108a34dee 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.ClientConfig.html +++ b/pr/255/docs/iroh_quinn_proto/struct.ClientConfig.html @@ -1,4 +1,4 @@ -ClientConfig in iroh_quinn_proto - Rust

    ClientConfig

    Struct ClientConfig 

    Source
    #[non_exhaustive]
    pub struct ClientConfig { /* private fields */ }
    Expand description

    Configuration for outgoing connections

    +ClientConfig in iroh_quinn_proto - Rust

    ClientConfig

    Struct ClientConfig 

    Source
    #[non_exhaustive]
    pub struct ClientConfig { /* private fields */ }
    Expand description

    Configuration for outgoing connections

    Default values should be suitable for most internet applications.

    Implementations§

    Source§

    impl ClientConfig

    Source

    pub fn new(crypto: Arc<dyn ClientConfig>) -> Self

    Create a default config with a particular cryptographic config

    Source

    pub fn initial_dst_cid_provider( diff --git a/pr/255/docs/iroh_quinn_proto/struct.ClosedPath.html b/pr/255/docs/iroh_quinn_proto/struct.ClosedPath.html index 1dc5bce25..cf0a70100 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.ClosedPath.html +++ b/pr/255/docs/iroh_quinn_proto/struct.ClosedPath.html @@ -1,4 +1,4 @@ -ClosedPath in iroh_quinn_proto - Rust

    ClosedPath

    Struct ClosedPath 

    Source
    pub struct ClosedPath { /* private fields */ }
    Expand description

    Error indicating that a path has not been opened or has already been abandoned

    +ClosedPath in iroh_quinn_proto - Rust

    ClosedPath

    Struct ClosedPath 

    Source
    pub struct ClosedPath { /* private fields */ }
    Expand description

    Error indicating that a path has not been opened or has already been abandoned

    Trait Implementations§

    Source§

    impl Clone for ClosedPath

    Source§

    fn clone(&self) -> ClosedPath

    Returns a duplicate of the value. Read more
    1.0.0 · Source§

    fn clone_from(&mut self, source: &Self)

    Performs copy-assignment from source. Read more
    Source§

    impl Debug for ClosedPath

    Source§

    fn fmt(&self, f: &mut Formatter<'_>) -> Result

    Formats the value using the given formatter. Read more
    Source§

    impl Default for ClosedPath

    Source§

    fn default() -> ClosedPath

    Returns the “default value” for a type. Read more
    Source§

    impl Display for ClosedPath

    Source§

    fn fmt(&self, __formatter: &mut Formatter<'_>) -> Result

    Formats the value using the given formatter. Read more
    Source§

    impl Error for ClosedPath

    1.30.0 · Source§

    fn source(&self) -> Option<&(dyn Error + 'static)>

    Returns the lower-level source of this error, if any. Read more
    1.0.0 · Source§

    fn description(&self) -> &str

    👎Deprecated since 1.42.0: use the Display impl or to_string()
    1.0.0 · Source§

    fn cause(&self) -> Option<&dyn Error>

    👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
    Source§

    fn provide<'a>(&'a self, request: &mut Request<'a>)

    🔬This is a nightly-only experimental API. (error_generic_member_access)
    Provides type-based access to context intended for error reports. Read more
    Source§

    impl PartialEq for ClosedPath

    Source§

    fn eq(&self, other: &ClosedPath) -> bool

    Tests for self and other values to be equal, and is used by ==.
    1.0.0 · Source§

    fn ne(&self, other: &Rhs) -> bool

    Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
    Source§

    impl Eq for ClosedPath

    Source§

    impl StructuralPartialEq for ClosedPath

    Auto Trait Implementations§

    Blanket Implementations§

    Source§

    impl<T> Any for T
    where T: 'static + ?Sized,

    Source§

    fn type_id(&self) -> TypeId

    Gets the TypeId of self. Read more
    Source§

    impl<T> Borrow<T> for T
    where diff --git a/pr/255/docs/iroh_quinn_proto/struct.ClosedStream.html b/pr/255/docs/iroh_quinn_proto/struct.ClosedStream.html index 247ee08fd..0c785238a 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.ClosedStream.html +++ b/pr/255/docs/iroh_quinn_proto/struct.ClosedStream.html @@ -1,6 +1,6 @@ -ClosedStream in iroh_quinn_proto - Rust

    ClosedStream

    Struct ClosedStream 

    Source
    pub struct ClosedStream { /* private fields */ }
    Expand description

    Error indicating that a stream has not been opened or has already been finished or reset

    -

    Trait Implementations§

    Source§

    impl Clone for ClosedStream

    Source§

    fn clone(&self) -> ClosedStream

    Returns a duplicate of the value. Read more
    1.0.0 · Source§

    fn clone_from(&mut self, source: &Self)

    Performs copy-assignment from source. Read more
    Source§

    impl Debug for ClosedStream

    Source§

    fn fmt(&self, f: &mut Formatter<'_>) -> Result

    Formats the value using the given formatter. Read more
    Source§

    impl Default for ClosedStream

    Source§

    fn default() -> ClosedStream

    Returns the “default value” for a type. Read more
    Source§

    impl Display for ClosedStream

    Source§

    fn fmt(&self, __formatter: &mut Formatter<'_>) -> Result

    Formats the value using the given formatter. Read more
    Source§

    impl Error for ClosedStream

    1.30.0 · Source§

    fn source(&self) -> Option<&(dyn Error + 'static)>

    Returns the lower-level source of this error, if any. Read more
    1.0.0 · Source§

    fn description(&self) -> &str

    👎Deprecated since 1.42.0: use the Display impl or to_string()
    1.0.0 · Source§

    fn cause(&self) -> Option<&dyn Error>

    👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
    Source§

    fn provide<'a>(&'a self, request: &mut Request<'a>)

    🔬This is a nightly-only experimental API. (error_generic_member_access)
    Provides type-based access to context intended for error reports. Read more
    Source§

    impl From<ClosedStream> for Error

    Source§

    fn from(x: ClosedStream) -> Self

    Converts to this type from the input type.
    Source§

    impl PartialEq for ClosedStream

    Source§

    fn eq(&self, other: &ClosedStream) -> bool

    Tests for self and other values to be equal, and is used by ==.
    1.0.0 · Source§

    fn ne(&self, other: &Rhs) -> bool

    Tests for !=. The default implementation is almost always sufficient, -and should not be overridden without very good reason.
    Source§

    impl Eq for ClosedStream

    Source§

    impl StructuralPartialEq for ClosedStream

    Auto Trait Implementations§

    Blanket Implementations§

    Source§

    impl<T> Any for T
    where +ClosedStream in iroh_quinn_proto - Rust

    ClosedStream

    Struct ClosedStream 

    Source
    pub struct ClosedStream { /* private fields */ }
    Expand description

    Error indicating that a stream has not been opened or has already been finished or reset

    +

    Trait Implementations§

    Source§

    impl Clone for ClosedStream

    Source§

    fn clone(&self) -> ClosedStream

    Returns a duplicate of the value. Read more
    1.0.0 · Source§

    fn clone_from(&mut self, source: &Self)

    Performs copy-assignment from source. Read more
    Source§

    impl Debug for ClosedStream

    Source§

    fn fmt(&self, f: &mut Formatter<'_>) -> Result

    Formats the value using the given formatter. Read more
    Source§

    impl Default for ClosedStream

    Source§

    fn default() -> ClosedStream

    Returns the “default value” for a type. Read more
    Source§

    impl Display for ClosedStream

    Source§

    fn fmt(&self, __formatter: &mut Formatter<'_>) -> Result

    Formats the value using the given formatter. Read more
    Source§

    impl Error for ClosedStream

    1.30.0 · Source§

    fn source(&self) -> Option<&(dyn Error + 'static)>

    Returns the lower-level source of this error, if any. Read more
    1.0.0 · Source§

    fn description(&self) -> &str

    👎Deprecated since 1.42.0: use the Display impl or to_string()
    1.0.0 · Source§

    fn cause(&self) -> Option<&dyn Error>

    👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
    Source§

    fn provide<'a>(&'a self, request: &mut Request<'a>)

    🔬This is a nightly-only experimental API. (error_generic_member_access)
    Provides type-based access to context intended for error reports. Read more
    Source§

    impl From<ClosedStream> for Error

    Source§

    fn from(x: ClosedStream) -> Self

    Converts to this type from the input type.
    Source§

    impl PartialEq for ClosedStream

    Source§

    fn eq(&self, other: &ClosedStream) -> bool

    Tests for self and other values to be equal, and is used by ==.
    1.0.0 · Source§

    fn ne(&self, other: &Rhs) -> bool

    Tests for !=. The default implementation is almost always sufficient, +and should not be overridden without very good reason.
    Source§

    impl Eq for ClosedStream

    Source§

    impl StructuralPartialEq for ClosedStream

    Auto Trait Implementations§

    Blanket Implementations§

    Source§

    impl<T> Any for T
    where T: 'static + ?Sized,

    Source§

    fn type_id(&self) -> TypeId

    Gets the TypeId of self. Read more
    Source§

    impl<T> Borrow<T> for T
    where T: ?Sized,

    Source§

    fn borrow(&self) -> &T

    Immutably borrows from an owned value. Read more
    Source§

    impl<T> BorrowMut<T> for T
    where T: ?Sized,

    Source§

    fn borrow_mut(&mut self) -> &mut T

    Mutably borrows from an owned value. Read more
    Source§

    impl<T> CloneToUninit for T
    where diff --git a/pr/255/docs/iroh_quinn_proto/struct.Connection.html b/pr/255/docs/iroh_quinn_proto/struct.Connection.html index f0156fdd0..38be109b3 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.Connection.html +++ b/pr/255/docs/iroh_quinn_proto/struct.Connection.html @@ -1,4 +1,4 @@ -Connection in iroh_quinn_proto - Rust

    Connection

    Struct Connection 

    Source
    pub struct Connection { /* private fields */ }
    Expand description

    Protocol state and logic for a single QUIC connection

    +Connection in iroh_quinn_proto - Rust

    Connection

    Struct Connection 

    Source
    pub struct Connection { /* private fields */ }
    Expand description

    Protocol state and logic for a single QUIC connection

    Objects of this type receive ConnectionEvents and emit EndpointEvents and application Events to make progress. To handle timeouts, a Connection returns timer updates and expects timeouts through various methods. A number of simple getter methods are exposed diff --git a/pr/255/docs/iroh_quinn_proto/struct.ConnectionClose.html b/pr/255/docs/iroh_quinn_proto/struct.ConnectionClose.html index b19fa6ec2..35ff90299 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.ConnectionClose.html +++ b/pr/255/docs/iroh_quinn_proto/struct.ConnectionClose.html @@ -1,4 +1,4 @@ -ConnectionClose in iroh_quinn_proto - Rust

    ConnectionClose

    Struct ConnectionClose 

    Source
    pub struct ConnectionClose {
    +ConnectionClose in iroh_quinn_proto - Rust

    ConnectionClose

    Struct ConnectionClose 

    Source
    pub struct ConnectionClose {
         pub error_code: TransportErrorCode,
         pub frame_type: MaybeFrame,
         pub reason: Bytes,
    @@ -6,8 +6,8 @@
     

    Fields§

    §error_code: TransportErrorCode

    Class of error as encoded in the specification

    §frame_type: MaybeFrame

    Type of frame that caused the close

    §reason: Bytes

    Human-readable reason for the close

    -

    Trait Implementations§

    Source§

    impl Clone for ConnectionClose

    Source§

    fn clone(&self) -> ConnectionClose

    Returns a duplicate of the value. Read more
    1.0.0 · Source§

    fn clone_from(&mut self, source: &Self)

    Performs copy-assignment from source. Read more
    Source§

    impl Debug for ConnectionClose

    Source§

    fn fmt(&self, f: &mut Formatter<'_>) -> Result

    Formats the value using the given formatter. Read more
    Source§

    impl Display for ConnectionClose

    Source§

    fn fmt(&self, f: &mut Formatter<'_>) -> Result

    Formats the value using the given formatter. Read more
    Source§

    impl From<Error> for ConnectionClose

    Source§

    fn from(x: TransportError) -> Self

    Converts to this type from the input type.
    Source§

    impl PartialEq for ConnectionClose

    Source§

    fn eq(&self, other: &ConnectionClose) -> bool

    Tests for self and other values to be equal, and is used by ==.
    1.0.0 · Source§

    fn ne(&self, other: &Rhs) -> bool

    Tests for !=. The default implementation is almost always sufficient, -and should not be overridden without very good reason.
    Source§

    impl Eq for ConnectionClose

    Source§

    impl StructuralPartialEq for ConnectionClose

    Auto Trait Implementations§

    Blanket Implementations§

    Source§

    impl<T> Any for T
    where +

    Trait Implementations§

    Source§

    impl Clone for ConnectionClose

    Source§

    fn clone(&self) -> ConnectionClose

    Returns a duplicate of the value. Read more
    1.0.0 · Source§

    fn clone_from(&mut self, source: &Self)

    Performs copy-assignment from source. Read more
    Source§

    impl Debug for ConnectionClose

    Source§

    fn fmt(&self, f: &mut Formatter<'_>) -> Result

    Formats the value using the given formatter. Read more
    Source§

    impl Display for ConnectionClose

    Source§

    fn fmt(&self, f: &mut Formatter<'_>) -> Result

    Formats the value using the given formatter. Read more
    Source§

    impl From<Error> for ConnectionClose

    Source§

    fn from(x: TransportError) -> Self

    Converts to this type from the input type.
    Source§

    impl PartialEq for ConnectionClose

    Source§

    fn eq(&self, other: &ConnectionClose) -> bool

    Tests for self and other values to be equal, and is used by ==.
    1.0.0 · Source§

    fn ne(&self, other: &Rhs) -> bool

    Tests for !=. The default implementation is almost always sufficient, +and should not be overridden without very good reason.
    Source§

    impl Eq for ConnectionClose

    Source§

    impl StructuralPartialEq for ConnectionClose

    Auto Trait Implementations§

    Blanket Implementations§

    Source§

    impl<T> Any for T
    where T: 'static + ?Sized,

    Source§

    fn type_id(&self) -> TypeId

    Gets the TypeId of self. Read more
    Source§

    impl<T> Borrow<T> for T
    where T: ?Sized,

    Source§

    fn borrow(&self) -> &T

    Immutably borrows from an owned value. Read more
    Source§

    impl<T> BorrowMut<T> for T
    where T: ?Sized,

    Source§

    fn borrow_mut(&mut self) -> &mut T

    Mutably borrows from an owned value. Read more
    Source§

    impl<T> CloneToUninit for T
    where diff --git a/pr/255/docs/iroh_quinn_proto/struct.ConnectionEvent.html b/pr/255/docs/iroh_quinn_proto/struct.ConnectionEvent.html index e317ca983..bdc444606 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.ConnectionEvent.html +++ b/pr/255/docs/iroh_quinn_proto/struct.ConnectionEvent.html @@ -1,4 +1,4 @@ -ConnectionEvent in iroh_quinn_proto - Rust

    ConnectionEvent

    Struct ConnectionEvent 

    Source
    pub struct ConnectionEvent(/* private fields */);
    Expand description

    Events sent from an Endpoint to a Connection

    +ConnectionEvent in iroh_quinn_proto - Rust

    ConnectionEvent

    Struct ConnectionEvent 

    Source
    pub struct ConnectionEvent(/* private fields */);
    Expand description

    Events sent from an Endpoint to a Connection

    Trait Implementations§

    Source§

    impl Debug for ConnectionEvent

    Source§

    fn fmt(&self, f: &mut Formatter<'_>) -> Result

    Formats the value using the given formatter. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Source§

    impl<T> Any for T
    where T: 'static + ?Sized,

    Source§

    fn type_id(&self) -> TypeId

    Gets the TypeId of self. Read more
    Source§

    impl<T> Borrow<T> for T
    where T: ?Sized,

    Source§

    fn borrow(&self) -> &T

    Immutably borrows from an owned value. Read more
    Source§

    impl<T> BorrowMut<T> for T
    where diff --git a/pr/255/docs/iroh_quinn_proto/struct.ConnectionHandle.html b/pr/255/docs/iroh_quinn_proto/struct.ConnectionHandle.html index d1ca9f2a7..38330352c 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.ConnectionHandle.html +++ b/pr/255/docs/iroh_quinn_proto/struct.ConnectionHandle.html @@ -1,4 +1,4 @@ -ConnectionHandle in iroh_quinn_proto - Rust

    ConnectionHandle

    Struct ConnectionHandle 

    Source
    pub struct ConnectionHandle(pub usize);
    Expand description

    Internal identifier for a Connection currently associated with an endpoint

    +ConnectionHandle in iroh_quinn_proto - Rust

    ConnectionHandle

    Struct ConnectionHandle 

    Source
    pub struct ConnectionHandle(pub usize);
    Expand description

    Internal identifier for a Connection currently associated with an endpoint

    Tuple Fields§

    §0: usize

    Trait Implementations§

    Source§

    impl Clone for ConnectionHandle

    Source§

    fn clone(&self) -> ConnectionHandle

    Returns a duplicate of the value. Read more
    1.0.0 · Source§

    fn clone_from(&mut self, source: &Self)

    Performs copy-assignment from source. Read more
    Source§

    impl Debug for ConnectionHandle

    Source§

    fn fmt(&self, f: &mut Formatter<'_>) -> Result

    Formats the value using the given formatter. Read more
    Source§

    impl From<ConnectionHandle> for usize

    Source§

    fn from(x: ConnectionHandle) -> Self

    Converts to this type from the input type.
    Source§

    impl Hash for ConnectionHandle

    Source§

    fn hash<__H: Hasher>(&self, state: &mut __H)

    Feeds this value into the given Hasher. Read more
    1.3.0 · Source§

    fn hash_slice<H>(data: &[Self], state: &mut H)
    where H: Hasher, Self: Sized,

    Feeds a slice of this type into the given Hasher. Read more
    Source§

    impl Index<ConnectionHandle> for Slab<ConnectionMeta>

    Source§

    type Output = ConnectionMeta

    The returned type after indexing.
    Source§

    fn index(&self, ch: ConnectionHandle) -> &ConnectionMeta

    Performs the indexing (container[index]) operation. Read more
    Source§

    impl IndexMut<ConnectionHandle> for Slab<ConnectionMeta>

    Source§

    fn index_mut(&mut self, ch: ConnectionHandle) -> &mut ConnectionMeta

    Performs the mutable indexing (container[index]) operation. Read more
    Source§

    impl Ord for ConnectionHandle

    Source§

    fn cmp(&self, other: &ConnectionHandle) -> Ordering

    This method returns an Ordering between self and other. Read more
    1.21.0 · Source§

    fn max(self, other: Self) -> Self
    where diff --git a/pr/255/docs/iroh_quinn_proto/struct.ConnectionId.html b/pr/255/docs/iroh_quinn_proto/struct.ConnectionId.html index 6228c6140..e8f7253d0 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.ConnectionId.html +++ b/pr/255/docs/iroh_quinn_proto/struct.ConnectionId.html @@ -1,4 +1,4 @@ -ConnectionId in iroh_quinn_proto - Rust

    ConnectionId

    Struct ConnectionId 

    Source
    pub struct ConnectionId { /* private fields */ }
    Expand description

    Protocol-level identifier for a connection.

    +ConnectionId in iroh_quinn_proto - Rust

    ConnectionId

    Struct ConnectionId 

    Source
    pub struct ConnectionId { /* private fields */ }
    Expand description

    Protocol-level identifier for a connection.

    Mainly useful for identifying this connection’s packets on the wire with tools like Wireshark.

    Implementations§

    Source§

    impl ConnectionId

    Source

    pub fn new(bytes: &[u8]) -> Self

    Construct cid from byte array

    Source

    pub fn from_buf(buf: &mut (impl Buf + ?Sized), len: usize) -> Self

    Constructs cid by reading len bytes from a Buf

    diff --git a/pr/255/docs/iroh_quinn_proto/struct.ConnectionStats.html b/pr/255/docs/iroh_quinn_proto/struct.ConnectionStats.html index cd892b6e1..8059b91e7 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.ConnectionStats.html +++ b/pr/255/docs/iroh_quinn_proto/struct.ConnectionStats.html @@ -1,4 +1,4 @@ -ConnectionStats in iroh_quinn_proto - Rust

    ConnectionStats

    Struct ConnectionStats 

    Source
    #[non_exhaustive]
    pub struct ConnectionStats { +ConnectionStats in iroh_quinn_proto - Rust

    ConnectionStats

    Struct ConnectionStats 

    Source
    #[non_exhaustive]
    pub struct ConnectionStats { pub udp_tx: UdpStats, pub udp_rx: UdpStats, pub frame_tx: FrameStats, diff --git a/pr/255/docs/iroh_quinn_proto/struct.Datagram.html b/pr/255/docs/iroh_quinn_proto/struct.Datagram.html index ec2ce553a..739eade7c 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.Datagram.html +++ b/pr/255/docs/iroh_quinn_proto/struct.Datagram.html @@ -1,8 +1,8 @@ -Datagram in iroh_quinn_proto - Rust

    Datagram

    Struct Datagram 

    Source
    pub struct Datagram {
    +Datagram in iroh_quinn_proto - Rust

    Datagram

    Struct Datagram 

    Source
    pub struct Datagram {
         pub data: Bytes,
     }
    Expand description

    An unreliable datagram

    Fields§

    §data: Bytes

    Payload

    -

    Trait Implementations§

    Source§

    impl Clone for Datagram

    Source§

    fn clone(&self) -> Datagram

    Returns a duplicate of the value. Read more
    1.0.0 · Source§

    fn clone_from(&mut self, source: &Self)

    Performs copy-assignment from source. Read more
    Source§

    impl Debug for Datagram

    Source§

    fn fmt(&self, f: &mut Formatter<'_>) -> Result

    Formats the value using the given formatter. Read more
    Source§

    impl Encodable for Datagram

    Source§

    fn encode<B: BufMut>(&self, out: &mut B)

    Append the encoding of self to the provided buffer.

    Auto Trait Implementations§

    Blanket Implementations§

    Source§

    impl<T> Any for T
    where +

    Trait Implementations§

    Source§

    impl Clone for Datagram

    Source§

    fn clone(&self) -> Datagram

    Returns a duplicate of the value. Read more
    1.0.0 · Source§

    fn clone_from(&mut self, source: &Self)

    Performs copy-assignment from source. Read more
    Source§

    impl Debug for Datagram

    Source§

    fn fmt(&self, f: &mut Formatter<'_>) -> Result

    Formats the value using the given formatter. Read more
    Source§

    impl Encodable for Datagram

    Source§

    fn encode<B: BufMut>(&self, out: &mut B)

    Append the encoding of self to the provided buffer.

    Auto Trait Implementations§

    Blanket Implementations§

    Source§

    impl<T> Any for T
    where T: 'static + ?Sized,

    Source§

    fn type_id(&self) -> TypeId

    Gets the TypeId of self. Read more
    Source§

    impl<T> Borrow<T> for T
    where T: ?Sized,

    Source§

    fn borrow(&self) -> &T

    Immutably borrows from an owned value. Read more
    Source§

    impl<T> BorrowMut<T> for T
    where T: ?Sized,

    Source§

    fn borrow_mut(&mut self) -> &mut T

    Mutably borrows from an owned value. Read more
    Source§

    impl<T> CloneToUninit for T
    where diff --git a/pr/255/docs/iroh_quinn_proto/struct.Datagrams.html b/pr/255/docs/iroh_quinn_proto/struct.Datagrams.html index 24d7b019a..c683008b1 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.Datagrams.html +++ b/pr/255/docs/iroh_quinn_proto/struct.Datagrams.html @@ -1,4 +1,4 @@ -Datagrams in iroh_quinn_proto - Rust

    Datagrams

    Struct Datagrams 

    Source
    pub struct Datagrams<'a> { /* private fields */ }
    Expand description

    API to control datagram traffic

    +Datagrams in iroh_quinn_proto - Rust

    Datagrams

    Struct Datagrams 

    Source
    pub struct Datagrams<'a> { /* private fields */ }
    Expand description

    API to control datagram traffic

    Implementations§

    Source§

    impl Datagrams<'_>

    Source

    pub fn send(&mut self, data: Bytes, drop: bool) -> Result<(), SendDatagramError>

    Queue an unreliable, unordered datagram for immediate transmission

    If drop is true, previously queued datagrams which are still unsent may be discarded to make space for this datagram, in order of oldest to newest. If drop is false, and there diff --git a/pr/255/docs/iroh_quinn_proto/struct.Endpoint.html b/pr/255/docs/iroh_quinn_proto/struct.Endpoint.html index f8bd5e32f..52f7d5d5e 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.Endpoint.html +++ b/pr/255/docs/iroh_quinn_proto/struct.Endpoint.html @@ -1,4 +1,4 @@ -Endpoint in iroh_quinn_proto - Rust

    Endpoint

    Struct Endpoint 

    Source
    pub struct Endpoint { /* private fields */ }
    Expand description

    The main entry point to the library

    +Endpoint in iroh_quinn_proto - Rust

    Endpoint

    Struct Endpoint 

    Source
    pub struct Endpoint { /* private fields */ }
    Expand description

    The main entry point to the library

    This object performs no I/O whatsoever. Instead, it consumes incoming packets and connection-generated events via handle and handle_event.

    Implementations§

    Source§

    impl Endpoint

    Source

    pub fn new( diff --git a/pr/255/docs/iroh_quinn_proto/struct.EndpointConfig.html b/pr/255/docs/iroh_quinn_proto/struct.EndpointConfig.html index 50830c687..2fa14cb3a 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.EndpointConfig.html +++ b/pr/255/docs/iroh_quinn_proto/struct.EndpointConfig.html @@ -1,4 +1,4 @@ -EndpointConfig in iroh_quinn_proto - Rust

    EndpointConfig

    Struct EndpointConfig 

    Source
    pub struct EndpointConfig { /* private fields */ }
    Expand description

    Global configuration for the endpoint, affecting all connections

    +EndpointConfig in iroh_quinn_proto - Rust

    EndpointConfig

    Struct EndpointConfig 

    Source
    pub struct EndpointConfig { /* private fields */ }
    Expand description

    Global configuration for the endpoint, affecting all connections

    Default values should be suitable for most internet applications.

    Implementations§

    Source§

    impl EndpointConfig

    Source

    pub fn new(reset_key: Arc<dyn HmacKey>) -> Self

    Create a default config with a particular reset_key

    Source

    pub fn cid_generator<F: Fn() -> Box<dyn ConnectionIdGenerator> + Send + Sync + 'static>( diff --git a/pr/255/docs/iroh_quinn_proto/struct.EndpointEvent.html b/pr/255/docs/iroh_quinn_proto/struct.EndpointEvent.html index 5ba222115..6e0fb88df 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.EndpointEvent.html +++ b/pr/255/docs/iroh_quinn_proto/struct.EndpointEvent.html @@ -1,4 +1,4 @@ -EndpointEvent in iroh_quinn_proto - Rust

    EndpointEvent

    Struct EndpointEvent 

    Source
    pub struct EndpointEvent(/* private fields */);
    Expand description

    Events sent from a Connection to an Endpoint

    +EndpointEvent in iroh_quinn_proto - Rust

    EndpointEvent

    Struct EndpointEvent 

    Source
    pub struct EndpointEvent(/* private fields */);
    Expand description

    Events sent from a Connection to an Endpoint

    Implementations§

    Source§

    impl EndpointEvent

    Source

    pub fn drained() -> Self

    Construct an event that indicating that a Connection will no longer emit events

    Useful for notifying an Endpoint that a Connection has been destroyed outside of the usual state machine flow, e.g. when being dropped by the user.

    diff --git a/pr/255/docs/iroh_quinn_proto/struct.FixedLengthConnectionIdParser.html b/pr/255/docs/iroh_quinn_proto/struct.FixedLengthConnectionIdParser.html index 4c7502c43..3a71a6b61 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.FixedLengthConnectionIdParser.html +++ b/pr/255/docs/iroh_quinn_proto/struct.FixedLengthConnectionIdParser.html @@ -1,4 +1,4 @@ -FixedLengthConnectionIdParser in iroh_quinn_proto - Rust

    FixedLengthConnectionIdParser

    Struct FixedLengthConnectionIdParser 

    Source
    pub struct FixedLengthConnectionIdParser { /* private fields */ }
    Expand description

    A ConnectionIdParser implementation that assumes the connection ID is of fixed length

    +FixedLengthConnectionIdParser in iroh_quinn_proto - Rust

    FixedLengthConnectionIdParser

    Struct FixedLengthConnectionIdParser 

    Source
    pub struct FixedLengthConnectionIdParser { /* private fields */ }
    Expand description

    A ConnectionIdParser implementation that assumes the connection ID is of fixed length

    Implementations§

    Source§

    impl FixedLengthConnectionIdParser

    Source

    pub fn new(expected_len: usize) -> Self

    Create a new instance of FixedLengthConnectionIdParser

    Trait Implementations§

    Source§

    impl ConnectionIdParser for FixedLengthConnectionIdParser

    Source§

    fn parse(&self, buffer: &mut dyn Buf) -> Result<ConnectionId, PacketDecodeError>

    Parse a connection id from given buffer

    Auto Trait Implementations§

    Blanket Implementations§

    Source§

    impl<T> Any for T
    where T: 'static + ?Sized,

    Source§

    fn type_id(&self) -> TypeId

    Gets the TypeId of self. Read more
    Source§

    impl<T> Borrow<T> for T
    where diff --git a/pr/255/docs/iroh_quinn_proto/struct.FourTuple.html b/pr/255/docs/iroh_quinn_proto/struct.FourTuple.html index bf77a177d..f5ede5851 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.FourTuple.html +++ b/pr/255/docs/iroh_quinn_proto/struct.FourTuple.html @@ -1,4 +1,4 @@ -FourTuple in iroh_quinn_proto - Rust

    FourTuple

    Struct FourTuple 

    Source
    pub struct FourTuple {
    +FourTuple in iroh_quinn_proto - Rust

    FourTuple

    Struct FourTuple 

    Source
    pub struct FourTuple {
         pub remote: SocketAddr,
         pub local_ip: Option<IpAddr>,
     }
    Expand description

    Identifies a network path by the combination of remote and local addresses

    diff --git a/pr/255/docs/iroh_quinn_proto/struct.FrameStats.html b/pr/255/docs/iroh_quinn_proto/struct.FrameStats.html index adad219dd..fcbc9fe92 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.FrameStats.html +++ b/pr/255/docs/iroh_quinn_proto/struct.FrameStats.html @@ -1,4 +1,4 @@ -FrameStats in iroh_quinn_proto - Rust

    FrameStats

    Struct FrameStats 

    Source
    #[non_exhaustive]
    pub struct FrameStats {
    Show 37 fields +FrameStats in iroh_quinn_proto - Rust

    FrameStats

    Struct FrameStats 

    Source
    #[non_exhaustive]
    pub struct FrameStats {
    Show 37 fields pub acks: u64, pub path_acks: u64, pub ack_frequency: u64, diff --git a/pr/255/docs/iroh_quinn_proto/struct.HashedConnectionIdGenerator.html b/pr/255/docs/iroh_quinn_proto/struct.HashedConnectionIdGenerator.html index 71e6e2820..97c506fd8 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.HashedConnectionIdGenerator.html +++ b/pr/255/docs/iroh_quinn_proto/struct.HashedConnectionIdGenerator.html @@ -1,4 +1,4 @@ -HashedConnectionIdGenerator in iroh_quinn_proto - Rust

    HashedConnectionIdGenerator

    Struct HashedConnectionIdGenerator 

    Source
    pub struct HashedConnectionIdGenerator { /* private fields */ }
    Expand description

    Generates 8-byte connection IDs that can be efficiently +HashedConnectionIdGenerator in iroh_quinn_proto - Rust

    HashedConnectionIdGenerator

    Struct HashedConnectionIdGenerator 

    Source
    pub struct HashedConnectionIdGenerator { /* private fields */ }
    Expand description

    Generates 8-byte connection IDs that can be efficiently validated

    This generator uses a non-cryptographic hash and can therefore still be spoofed, but nonetheless helps prevents Quinn from responding to non-QUIC packets at very low cost.

    diff --git a/pr/255/docs/iroh_quinn_proto/struct.IdleTimeout.html b/pr/255/docs/iroh_quinn_proto/struct.IdleTimeout.html index dd762ac5a..1390468ed 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.IdleTimeout.html +++ b/pr/255/docs/iroh_quinn_proto/struct.IdleTimeout.html @@ -1,4 +1,4 @@ -IdleTimeout in iroh_quinn_proto - Rust

    IdleTimeout

    Struct IdleTimeout 

    Source
    pub struct IdleTimeout(/* private fields */);
    Expand description

    Maximum duration of inactivity to accept before timing out the connection

    +IdleTimeout in iroh_quinn_proto - Rust

    IdleTimeout

    Struct IdleTimeout 

    Source
    pub struct IdleTimeout(/* private fields */);
    Expand description

    Maximum duration of inactivity to accept before timing out the connection

    This wraps an underlying VarInt, representing the duration in milliseconds. Values can be constructed by converting directly from VarInt, or using TryFrom<Duration>.

    diff --git a/pr/255/docs/iroh_quinn_proto/struct.Incoming.html b/pr/255/docs/iroh_quinn_proto/struct.Incoming.html index 961800b4f..bf7a5e8fe 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.Incoming.html +++ b/pr/255/docs/iroh_quinn_proto/struct.Incoming.html @@ -1,4 +1,4 @@ -Incoming in iroh_quinn_proto - Rust

    Incoming

    Struct Incoming 

    Source
    pub struct Incoming { /* private fields */ }
    Expand description

    An incoming connection for which the server has not yet begun its part of the handshake.

    +Incoming in iroh_quinn_proto - Rust

    Incoming

    Struct Incoming 

    Source
    pub struct Incoming { /* private fields */ }
    Expand description

    An incoming connection for which the server has not yet begun its part of the handshake.

    Implementations§

    Source§

    impl Incoming

    Source

    pub fn local_ip(&self) -> Option<IpAddr>

    The local IP address which was used when the peer established the connection

    This has the same behavior as [Connection::local_ip].

    Source

    pub fn remote_address(&self) -> SocketAddr

    The peer’s UDP address

    diff --git a/pr/255/docs/iroh_quinn_proto/struct.InvalidCid.html b/pr/255/docs/iroh_quinn_proto/struct.InvalidCid.html index 15b72eae8..3438b2a5c 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.InvalidCid.html +++ b/pr/255/docs/iroh_quinn_proto/struct.InvalidCid.html @@ -1,4 +1,4 @@ -InvalidCid in iroh_quinn_proto - Rust

    InvalidCid

    Struct InvalidCid 

    Source
    pub struct InvalidCid;
    Expand description

    The connection ID was not recognized by the ConnectionIdGenerator

    +InvalidCid in iroh_quinn_proto - Rust

    InvalidCid

    Struct InvalidCid 

    Source
    pub struct InvalidCid;
    Expand description

    The connection ID was not recognized by the ConnectionIdGenerator

    Trait Implementations§

    Source§

    impl Clone for InvalidCid

    Source§

    fn clone(&self) -> InvalidCid

    Returns a duplicate of the value. Read more
    1.0.0 · Source§

    fn clone_from(&mut self, source: &Self)

    Performs copy-assignment from source. Read more
    Source§

    impl Debug for InvalidCid

    Source§

    fn fmt(&self, f: &mut Formatter<'_>) -> Result

    Formats the value using the given formatter. Read more
    Source§

    impl Copy for InvalidCid

    Auto Trait Implementations§

    Blanket Implementations§

    Source§

    impl<T> Any for T
    where T: 'static + ?Sized,

    Source§

    fn type_id(&self) -> TypeId

    Gets the TypeId of self. Read more
    Source§

    impl<T> Borrow<T> for T
    where T: ?Sized,

    Source§

    fn borrow(&self) -> &T

    Immutably borrows from an owned value. Read more
    Source§

    impl<T> BorrowMut<T> for T
    where diff --git a/pr/255/docs/iroh_quinn_proto/struct.MtuDiscoveryConfig.html b/pr/255/docs/iroh_quinn_proto/struct.MtuDiscoveryConfig.html index d9665f60f..3b3ba684b 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.MtuDiscoveryConfig.html +++ b/pr/255/docs/iroh_quinn_proto/struct.MtuDiscoveryConfig.html @@ -1,4 +1,4 @@ -MtuDiscoveryConfig in iroh_quinn_proto - Rust

    MtuDiscoveryConfig

    Struct MtuDiscoveryConfig 

    Source
    pub struct MtuDiscoveryConfig { /* private fields */ }
    Expand description

    Parameters governing MTU discovery.

    +MtuDiscoveryConfig in iroh_quinn_proto - Rust

    MtuDiscoveryConfig

    Struct MtuDiscoveryConfig 

    Source
    pub struct MtuDiscoveryConfig { /* private fields */ }
    Expand description

    Parameters governing MTU discovery.

    §The why of MTU discovery

    By design, QUIC ensures during the handshake that the network path between the client and the server is able to transmit unfragmented UDP packets with a body of 1200 bytes. In other words, diff --git a/pr/255/docs/iroh_quinn_proto/struct.NoneTokenLog.html b/pr/255/docs/iroh_quinn_proto/struct.NoneTokenLog.html index 39c959fc2..59501559e 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.NoneTokenLog.html +++ b/pr/255/docs/iroh_quinn_proto/struct.NoneTokenLog.html @@ -1,4 +1,4 @@ -NoneTokenLog in iroh_quinn_proto - Rust

    NoneTokenLog

    Struct NoneTokenLog 

    Source
    pub struct NoneTokenLog;
    Expand description

    Null implementation of TokenLog, which never accepts tokens

    +NoneTokenLog in iroh_quinn_proto - Rust

    NoneTokenLog

    Struct NoneTokenLog 

    Source
    pub struct NoneTokenLog;
    Expand description

    Null implementation of TokenLog, which never accepts tokens

    Trait Implementations§

    Source§

    impl TokenLog for NoneTokenLog

    Source§

    fn check_and_insert( &self, _: u128, diff --git a/pr/255/docs/iroh_quinn_proto/struct.NoneTokenStore.html b/pr/255/docs/iroh_quinn_proto/struct.NoneTokenStore.html index 34ac91044..5aec2ab6b 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.NoneTokenStore.html +++ b/pr/255/docs/iroh_quinn_proto/struct.NoneTokenStore.html @@ -1,4 +1,4 @@ -NoneTokenStore in iroh_quinn_proto - Rust

    NoneTokenStore

    Struct NoneTokenStore 

    Source
    pub struct NoneTokenStore;
    Expand description

    Null implementation of TokenStore, which does not store any tokens

    +NoneTokenStore in iroh_quinn_proto - Rust

    NoneTokenStore

    Struct NoneTokenStore 

    Source
    pub struct NoneTokenStore;
    Expand description

    Null implementation of TokenStore, which does not store any tokens

    Trait Implementations§

    Source§

    impl TokenStore for NoneTokenStore

    Source§

    fn insert(&self, _: &str, _: Bytes)

    Potentially store a token for later one-time use Read more
    Source§

    fn take(&self, _: &str) -> Option<Bytes>

    Try to find and take a token that was stored with the given server name Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Source§

    impl<T> Any for T
    where T: 'static + ?Sized,

    Source§

    fn type_id(&self) -> TypeId

    Gets the TypeId of self. Read more
    Source§

    impl<T> Borrow<T> for T
    where T: ?Sized,

    Source§

    fn borrow(&self) -> &T

    Immutably borrows from an owned value. Read more
    Source§

    impl<T> BorrowMut<T> for T
    where diff --git a/pr/255/docs/iroh_quinn_proto/struct.PartialDecode.html b/pr/255/docs/iroh_quinn_proto/struct.PartialDecode.html index 52b9d3ebc..a9bde69fe 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.PartialDecode.html +++ b/pr/255/docs/iroh_quinn_proto/struct.PartialDecode.html @@ -1,4 +1,4 @@ -PartialDecode in iroh_quinn_proto - Rust

    PartialDecode

    Struct PartialDecode 

    Source
    pub struct PartialDecode { /* private fields */ }
    Expand description

    Decodes a QUIC packet’s invariant header

    +PartialDecode in iroh_quinn_proto - Rust

    PartialDecode

    Struct PartialDecode 

    Source
    pub struct PartialDecode { /* private fields */ }
    Expand description

    Decodes a QUIC packet’s invariant header

    Due to packet number encryption, it is impossible to fully decode a header (which includes a variable-length packet number) without crypto context. The crypto context (represented by the Crypto type in Quinn) is usually diff --git a/pr/255/docs/iroh_quinn_proto/struct.PathId.html b/pr/255/docs/iroh_quinn_proto/struct.PathId.html index 394c67c30..30c4774ca 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.PathId.html +++ b/pr/255/docs/iroh_quinn_proto/struct.PathId.html @@ -1,4 +1,4 @@ -PathId in iroh_quinn_proto - Rust

    PathId

    Struct PathId 

    Source
    pub struct PathId(/* private fields */);
    Expand description

    Id representing different paths when using multipath extension

    +PathId in iroh_quinn_proto - Rust

    PathId

    Struct PathId 

    Source
    pub struct PathId(/* private fields */);
    Expand description

    Id representing different paths when using multipath extension

    Implementations§

    Source§

    impl PathId

    Source

    pub const MAX: Self

    The maximum path ID allowed.

    Source

    pub const ZERO: Self

    The 0 path id.

    Source

    pub fn saturating_add(self, rhs: impl Into<Self>) -> Self

    Saturating integer addition. Computes self + rhs, saturating at the numeric bounds instead diff --git a/pr/255/docs/iroh_quinn_proto/struct.PathStats.html b/pr/255/docs/iroh_quinn_proto/struct.PathStats.html index 6568dc40a..76d16c997 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.PathStats.html +++ b/pr/255/docs/iroh_quinn_proto/struct.PathStats.html @@ -1,4 +1,4 @@ -PathStats in iroh_quinn_proto - Rust

    PathStats

    Struct PathStats 

    Source
    #[non_exhaustive]
    pub struct PathStats { +PathStats in iroh_quinn_proto - Rust

    PathStats

    Struct PathStats 

    Source
    #[non_exhaustive]
    pub struct PathStats { pub rtt: Duration, pub cwnd: u64, pub congestion_events: u64, diff --git a/pr/255/docs/iroh_quinn_proto/struct.ProtectedInitialHeader.html b/pr/255/docs/iroh_quinn_proto/struct.ProtectedInitialHeader.html index cd5ce3d70..6db7877fc 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.ProtectedInitialHeader.html +++ b/pr/255/docs/iroh_quinn_proto/struct.ProtectedInitialHeader.html @@ -1,4 +1,4 @@ -ProtectedInitialHeader in iroh_quinn_proto - Rust

    ProtectedInitialHeader

    Struct ProtectedInitialHeader 

    Source
    pub struct ProtectedInitialHeader {
    +ProtectedInitialHeader in iroh_quinn_proto - Rust

    ProtectedInitialHeader

    Struct ProtectedInitialHeader 

    Source
    pub struct ProtectedInitialHeader {
         pub dst_cid: ConnectionId,
         pub src_cid: ConnectionId,
         pub token_pos: Range<usize>,
    diff --git a/pr/255/docs/iroh_quinn_proto/struct.QlogConfig.html b/pr/255/docs/iroh_quinn_proto/struct.QlogConfig.html
    index 72429d45c..b90392c66 100644
    --- a/pr/255/docs/iroh_quinn_proto/struct.QlogConfig.html
    +++ b/pr/255/docs/iroh_quinn_proto/struct.QlogConfig.html
    @@ -1,4 +1,4 @@
    -QlogConfig in iroh_quinn_proto - Rust

    QlogConfig

    Struct QlogConfig 

    Source
    pub struct QlogConfig { /* private fields */ }
    Expand description

    Configuration for qlog trace logging.

    +QlogConfig in iroh_quinn_proto - Rust

    QlogConfig

    Struct QlogConfig 

    Source
    pub struct QlogConfig { /* private fields */ }
    Expand description

    Configuration for qlog trace logging.

    This struct is returned from QlogFactory::for_connection if qlog logging should be enabled for a connection. It allows to set metadata for the qlog trace.

    The trace will be written to the provided writer in the [JSON-SEQ format] defined in the qlog spec.

    diff --git a/pr/255/docs/iroh_quinn_proto/struct.QlogFileFactory.html b/pr/255/docs/iroh_quinn_proto/struct.QlogFileFactory.html index edeeb554a..baa30a4d4 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.QlogFileFactory.html +++ b/pr/255/docs/iroh_quinn_proto/struct.QlogFileFactory.html @@ -1,4 +1,4 @@ -QlogFileFactory in iroh_quinn_proto - Rust

    QlogFileFactory

    Struct QlogFileFactory 

    Source
    pub struct QlogFileFactory { /* private fields */ }
    Expand description

    Enables writing qlog traces to a directory.

    +QlogFileFactory in iroh_quinn_proto - Rust

    QlogFileFactory

    Struct QlogFileFactory 

    Source
    pub struct QlogFileFactory { /* private fields */ }
    Expand description

    Enables writing qlog traces to a directory.

    Implementations§

    Source§

    impl QlogFileFactory

    Source

    pub fn new(dir: PathBuf) -> Self

    Creates a new qlog factory that writes files into the specified directory.

    Source

    pub fn from_env() -> Self

    Creates a new qlog factory that writes files into QLOGDIR, if set.

    If the environment variable QLOGDIR is set, qlog traces for all connections handled diff --git a/pr/255/docs/iroh_quinn_proto/struct.RandomConnectionIdGenerator.html b/pr/255/docs/iroh_quinn_proto/struct.RandomConnectionIdGenerator.html index c2385a7ba..9a84ceec7 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.RandomConnectionIdGenerator.html +++ b/pr/255/docs/iroh_quinn_proto/struct.RandomConnectionIdGenerator.html @@ -1,4 +1,4 @@ -RandomConnectionIdGenerator in iroh_quinn_proto - Rust

    RandomConnectionIdGenerator

    Struct RandomConnectionIdGenerator 

    Source
    pub struct RandomConnectionIdGenerator { /* private fields */ }
    Expand description

    Generates purely random connection IDs of a specified length

    +RandomConnectionIdGenerator in iroh_quinn_proto - Rust

    RandomConnectionIdGenerator

    Struct RandomConnectionIdGenerator 

    Source
    pub struct RandomConnectionIdGenerator { /* private fields */ }
    Expand description

    Generates purely random connection IDs of a specified length

    Random CIDs can be smaller than those produced by HashedConnectionIdGenerator, but cannot be usefully validated.

    Implementations§

    Source§

    impl RandomConnectionIdGenerator

    Source

    pub fn new(cid_len: usize) -> Self

    Initialize Random CID generator with a fixed CID length

    diff --git a/pr/255/docs/iroh_quinn_proto/struct.RecvStream.html b/pr/255/docs/iroh_quinn_proto/struct.RecvStream.html index 2292e2fdd..93efa71e4 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.RecvStream.html +++ b/pr/255/docs/iroh_quinn_proto/struct.RecvStream.html @@ -1,4 +1,4 @@ -RecvStream in iroh_quinn_proto - Rust

    RecvStream

    Struct RecvStream 

    Source
    pub struct RecvStream<'a> { /* private fields */ }
    Expand description

    Access to streams

    +RecvStream in iroh_quinn_proto - Rust

    RecvStream

    Struct RecvStream 

    Source
    pub struct RecvStream<'a> { /* private fields */ }
    Expand description

    Access to streams

    Implementations§

    Source§

    impl RecvStream<'_>

    Source

    pub fn read(&mut self, ordered: bool) -> Result<Chunks<'_>, ReadableError>

    Read from the given recv stream

    max_length limits the maximum size of the returned Bytes value; passing usize::MAX will yield the best performance. ordered will make sure the returned chunk’s offset will diff --git a/pr/255/docs/iroh_quinn_proto/struct.RetryError.html b/pr/255/docs/iroh_quinn_proto/struct.RetryError.html index 0352a119d..109e951de 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.RetryError.html +++ b/pr/255/docs/iroh_quinn_proto/struct.RetryError.html @@ -1,4 +1,4 @@ -RetryError in iroh_quinn_proto - Rust

    RetryError

    Struct RetryError 

    Source
    pub struct RetryError(/* private fields */);
    Expand description

    Error for attempting to retry an Incoming which already bears a token from a previous retry

    +RetryError in iroh_quinn_proto - Rust

    RetryError

    Struct RetryError 

    Source
    pub struct RetryError(/* private fields */);
    Expand description

    Error for attempting to retry an Incoming which already bears a token from a previous retry

    Implementations§

    Trait Implementations§

    Source§

    impl Debug for RetryError

    Source§

    fn fmt(&self, f: &mut Formatter<'_>) -> Result

    Formats the value using the given formatter. Read more
    Source§

    impl Display for RetryError

    Source§

    fn fmt(&self, __formatter: &mut Formatter<'_>) -> Result

    Formats the value using the given formatter. Read more
    Source§

    impl Error for RetryError

    1.30.0 · Source§

    fn source(&self) -> Option<&(dyn Error + 'static)>

    Returns the lower-level source of this error, if any. Read more
    1.0.0 · Source§

    fn description(&self) -> &str

    👎Deprecated since 1.42.0: use the Display impl or to_string()
    1.0.0 · Source§

    fn cause(&self) -> Option<&dyn Error>

    👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
    Source§

    fn provide<'a>(&'a self, request: &mut Request<'a>)

    🔬This is a nightly-only experimental API. (error_generic_member_access)
    Provides type-based access to context intended for error reports. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Source§

    impl<T> Any for T
    where T: 'static + ?Sized,

    Source§

    fn type_id(&self) -> TypeId

    Gets the TypeId of self. Read more
    Source§

    impl<T> Borrow<T> for T
    where diff --git a/pr/255/docs/iroh_quinn_proto/struct.RttEstimator.html b/pr/255/docs/iroh_quinn_proto/struct.RttEstimator.html index 614452d5d..5f8ac009d 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.RttEstimator.html +++ b/pr/255/docs/iroh_quinn_proto/struct.RttEstimator.html @@ -1,4 +1,4 @@ -RttEstimator in iroh_quinn_proto - Rust

    RttEstimator

    Struct RttEstimator 

    Source
    pub struct RttEstimator { /* private fields */ }
    Expand description

    RTT estimation for a particular network path

    +RttEstimator in iroh_quinn_proto - Rust

    RttEstimator

    Struct RttEstimator 

    Source
    pub struct RttEstimator { /* private fields */ }
    Expand description

    RTT estimation for a particular network path

    Implementations§

    Source§

    impl RttEstimator

    Source

    pub fn get(&self) -> Duration

    The current best RTT estimation.

    Source

    pub fn conservative(&self) -> Duration

    Conservative estimate of RTT

    Takes the maximum of smoothed and latest RTT, as recommended diff --git a/pr/255/docs/iroh_quinn_proto/struct.SendStream.html b/pr/255/docs/iroh_quinn_proto/struct.SendStream.html index 1a6c79db1..74b09e18c 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.SendStream.html +++ b/pr/255/docs/iroh_quinn_proto/struct.SendStream.html @@ -1,5 +1,5 @@ -SendStream in iroh_quinn_proto - Rust

    SendStream

    Struct SendStream 

    Source
    pub struct SendStream<'a> { /* private fields */ }
    Expand description

    Access to streams

    -

    Implementations§

    Source§

    impl<'a> SendStream<'a>

    Source

    pub fn write(&mut self, data: &[u8]) -> Result<usize, WriteError>

    Send data on the given stream

    +SendStream in iroh_quinn_proto - Rust

    SendStream

    Struct SendStream 

    Source
    pub struct SendStream<'a> { /* private fields */ }
    Expand description

    Access to streams

    +

    Implementations§

    Source§

    impl<'a> SendStream<'a>

    Source

    pub fn write(&mut self, data: &[u8]) -> Result<usize, WriteError>

    Send data on the given stream

    Returns the number of bytes successfully written.

    Source

    pub fn write_chunks( &mut self, @@ -9,20 +9,20 @@ Note that this method might also write a partial chunk. In this case Written::chunks will not count this chunk as fully written. However the chunk will be advanced and contain only non-written data after the call.

    -

    Source

    pub fn stopped(&self) -> Result<Option<VarInt>, ClosedStream>

    Check if this stream was stopped, get the reason if it was

    -
    Source

    pub fn finish(&mut self) -> Result<(), FinishError>

    Finish a send stream, signalling that no more data will be sent.

    +
    Source

    pub fn stopped(&self) -> Result<Option<VarInt>, ClosedStream>

    Check if this stream was stopped, get the reason if it was

    +
    Source

    pub fn finish(&mut self) -> Result<(), FinishError>

    Finish a send stream, signalling that no more data will be sent.

    If this fails, no StreamEvent::Finished will be generated.

    -
    Source

    pub fn reset(&mut self, error_code: VarInt) -> Result<(), ClosedStream>

    Abandon transmitting data on a stream

    +
    Source

    pub fn reset(&mut self, error_code: VarInt) -> Result<(), ClosedStream>

    Abandon transmitting data on a stream

    §Panics
    • when applied to a receive stream
    -
    Source

    pub fn set_priority(&mut self, priority: i32) -> Result<(), ClosedStream>

    Set the priority of a stream

    +
    Source

    pub fn set_priority(&mut self, priority: i32) -> Result<(), ClosedStream>

    Set the priority of a stream

    §Panics
    • when applied to a receive stream
    -
    Source

    pub fn priority(&self) -> Result<i32, ClosedStream>

    Get the priority of a stream

    +
    Source

    pub fn priority(&self) -> Result<i32, ClosedStream>

    Get the priority of a stream

    §Panics
    • when applied to a receive stream
    • diff --git a/pr/255/docs/iroh_quinn_proto/struct.ServerConfig.html b/pr/255/docs/iroh_quinn_proto/struct.ServerConfig.html index 22c1eca09..772c7ab04 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.ServerConfig.html +++ b/pr/255/docs/iroh_quinn_proto/struct.ServerConfig.html @@ -1,4 +1,4 @@ -ServerConfig in iroh_quinn_proto - Rust

      ServerConfig

      Struct ServerConfig 

      Source
      pub struct ServerConfig {
      +ServerConfig in iroh_quinn_proto - Rust

      ServerConfig

      Struct ServerConfig 

      Source
      pub struct ServerConfig {
           pub transport: Arc<TransportConfig>,
           pub crypto: Arc<dyn ServerConfig>,
           pub validation_token: ValidationTokenConfig,
      diff --git a/pr/255/docs/iroh_quinn_proto/struct.ShouldTransmit.html b/pr/255/docs/iroh_quinn_proto/struct.ShouldTransmit.html
      index 4f1561520..84b71890f 100644
      --- a/pr/255/docs/iroh_quinn_proto/struct.ShouldTransmit.html
      +++ b/pr/255/docs/iroh_quinn_proto/struct.ShouldTransmit.html
      @@ -1,9 +1,9 @@
      -ShouldTransmit in iroh_quinn_proto - Rust

      ShouldTransmit

      Struct ShouldTransmit 

      Source
      pub struct ShouldTransmit(/* private fields */);
      Expand description

      Indicates whether a frame needs to be transmitted

      +ShouldTransmit in iroh_quinn_proto - Rust

      ShouldTransmit

      Struct ShouldTransmit 

      Source
      pub struct ShouldTransmit(/* private fields */);
      Expand description

      Indicates whether a frame needs to be transmitted

      This type wraps around bool and uses the #[must_use] attribute in order to prevent accidental loss of the frame transmission requirement.

      -

      Implementations§

      Source§

      impl ShouldTransmit

      Source

      pub fn should_transmit(self) -> bool

      Returns whether a frame should be transmitted

      -

      Trait Implementations§

      Source§

      impl Clone for ShouldTransmit

      Source§

      fn clone(&self) -> ShouldTransmit

      Returns a duplicate of the value. Read more
      1.0.0 · Source§

      fn clone_from(&mut self, source: &Self)

      Performs copy-assignment from source. Read more
      Source§

      impl Debug for ShouldTransmit

      Source§

      fn fmt(&self, f: &mut Formatter<'_>) -> Result

      Formats the value using the given formatter. Read more
      Source§

      impl Default for ShouldTransmit

      Source§

      fn default() -> ShouldTransmit

      Returns the “default value” for a type. Read more
      Source§

      impl PartialEq for ShouldTransmit

      Source§

      fn eq(&self, other: &ShouldTransmit) -> bool

      Tests for self and other values to be equal, and is used by ==.
      1.0.0 · Source§

      fn ne(&self, other: &Rhs) -> bool

      Tests for !=. The default implementation is almost always sufficient, -and should not be overridden without very good reason.
      Source§

      impl Copy for ShouldTransmit

      Source§

      impl Eq for ShouldTransmit

      Source§

      impl StructuralPartialEq for ShouldTransmit

      Auto Trait Implementations§

      Blanket Implementations§

      Source§

      impl<T> Any for T
      where +

      Implementations§

      Source§

      impl ShouldTransmit

      Source

      pub fn should_transmit(self) -> bool

      Returns whether a frame should be transmitted

      +

      Trait Implementations§

      Source§

      impl Clone for ShouldTransmit

      Source§

      fn clone(&self) -> ShouldTransmit

      Returns a duplicate of the value. Read more
      1.0.0 · Source§

      fn clone_from(&mut self, source: &Self)

      Performs copy-assignment from source. Read more
      Source§

      impl Debug for ShouldTransmit

      Source§

      fn fmt(&self, f: &mut Formatter<'_>) -> Result

      Formats the value using the given formatter. Read more
      Source§

      impl Default for ShouldTransmit

      Source§

      fn default() -> ShouldTransmit

      Returns the “default value” for a type. Read more
      Source§

      impl PartialEq for ShouldTransmit

      Source§

      fn eq(&self, other: &ShouldTransmit) -> bool

      Tests for self and other values to be equal, and is used by ==.
      1.0.0 · Source§

      fn ne(&self, other: &Rhs) -> bool

      Tests for !=. The default implementation is almost always sufficient, +and should not be overridden without very good reason.
      Source§

      impl Copy for ShouldTransmit

      Source§

      impl Eq for ShouldTransmit

      Source§

      impl StructuralPartialEq for ShouldTransmit

      Auto Trait Implementations§

      Blanket Implementations§

      Source§

      impl<T> Any for T
      where T: 'static + ?Sized,

      Source§

      fn type_id(&self) -> TypeId

      Gets the TypeId of self. Read more
      Source§

      impl<T> Borrow<T> for T
      where T: ?Sized,

      Source§

      fn borrow(&self) -> &T

      Immutably borrows from an owned value. Read more
      Source§

      impl<T> BorrowMut<T> for T
      where T: ?Sized,

      Source§

      fn borrow_mut(&mut self) -> &mut T

      Mutably borrows from an owned value. Read more
      Source§

      impl<T> CloneToUninit for T
      where diff --git a/pr/255/docs/iroh_quinn_proto/struct.StdSystemTime.html b/pr/255/docs/iroh_quinn_proto/struct.StdSystemTime.html index 4d4721e26..6f84e29b1 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.StdSystemTime.html +++ b/pr/255/docs/iroh_quinn_proto/struct.StdSystemTime.html @@ -1,4 +1,4 @@ -StdSystemTime in iroh_quinn_proto - Rust

      StdSystemTime

      Struct StdSystemTime 

      Source
      pub struct StdSystemTime;
      Expand description

      Default implementation of TimeSource

      +StdSystemTime in iroh_quinn_proto - Rust

      StdSystemTime

      Struct StdSystemTime 

      Source
      pub struct StdSystemTime;
      Expand description

      Default implementation of TimeSource

      Implements now by calling SystemTime::now().

      Trait Implementations§

      Source§

      impl TimeSource for StdSystemTime

      Source§

      fn now(&self) -> SystemTime

      Get SystemTime::now() or the mocked equivalent

      Auto Trait Implementations§

      Blanket Implementations§

      Source§

      impl<T> Any for T
      where T: 'static + ?Sized,

      Source§

      fn type_id(&self) -> TypeId

      Gets the TypeId of self. Read more
      Source§

      impl<T> Borrow<T> for T
      where diff --git a/pr/255/docs/iroh_quinn_proto/struct.StreamId.html b/pr/255/docs/iroh_quinn_proto/struct.StreamId.html index c3cb92a08..a80e12039 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.StreamId.html +++ b/pr/255/docs/iroh_quinn_proto/struct.StreamId.html @@ -1,4 +1,4 @@ -StreamId in iroh_quinn_proto - Rust

      StreamId

      Struct StreamId 

      Source
      pub struct StreamId(/* private fields */);
      Expand description

      Identifier for a stream within a particular connection

      +StreamId in iroh_quinn_proto - Rust

      StreamId

      Struct StreamId 

      Source
      pub struct StreamId(/* private fields */);
      Expand description

      Identifier for a stream within a particular connection

      Implementations§

      Source§

      impl StreamId

      Source

      pub fn new(initiator: Side, dir: Dir, index: u64) -> Self

      Create a new StreamId

      Source

      pub fn initiator(self) -> Side

      Which side of a connection initiated the stream

      Source

      pub fn dir(self) -> Dir

      Which directions data flows in

      diff --git a/pr/255/docs/iroh_quinn_proto/struct.Streams.html b/pr/255/docs/iroh_quinn_proto/struct.Streams.html index e9c4634d6..c90088a38 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.Streams.html +++ b/pr/255/docs/iroh_quinn_proto/struct.Streams.html @@ -1,4 +1,4 @@ -Streams in iroh_quinn_proto - Rust

      Streams

      Struct Streams 

      Source
      pub struct Streams<'a> { /* private fields */ }
      Expand description

      Access to streams

      +Streams in iroh_quinn_proto - Rust

      Streams

      Struct Streams 

      Source
      pub struct Streams<'a> { /* private fields */ }
      Expand description

      Access to streams

      Implementations§

      Source§

      impl<'a> Streams<'a>

      Source

      pub fn open(&mut self, dir: Dir) -> Option<StreamId>

      Open a single stream if possible

      Returns None if the streams in the given direction are currently exhausted.

      Source

      pub fn accept(&mut self, dir: Dir) -> Option<StreamId>

      Accept a remotely initiated stream of a certain directionality, if possible

      diff --git a/pr/255/docs/iroh_quinn_proto/struct.TokenMemoryCache.html b/pr/255/docs/iroh_quinn_proto/struct.TokenMemoryCache.html index d826f700a..24baf7e19 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.TokenMemoryCache.html +++ b/pr/255/docs/iroh_quinn_proto/struct.TokenMemoryCache.html @@ -1,4 +1,4 @@ -TokenMemoryCache in iroh_quinn_proto - Rust

      TokenMemoryCache

      Struct TokenMemoryCache 

      Source
      pub struct TokenMemoryCache(/* private fields */);
      Expand description

      TokenStore implementation that stores up to N tokens per server name for up to a +TokenMemoryCache in iroh_quinn_proto - Rust

      TokenMemoryCache

      Struct TokenMemoryCache 

      Source
      pub struct TokenMemoryCache(/* private fields */);
      Expand description

      TokenStore implementation that stores up to N tokens per server name for up to a limited number of server names, in-memory

      Implementations§

      Source§

      impl TokenMemoryCache

      Source

      pub fn new(max_server_names: u32, max_tokens_per_server: usize) -> Self

      Construct empty

      Trait Implementations§

      Source§

      impl Debug for TokenMemoryCache

      Source§

      fn fmt(&self, f: &mut Formatter<'_>) -> Result

      Formats the value using the given formatter. Read more
      Source§

      impl Default for TokenMemoryCache

      Defaults to a maximum of 256 servers and 2 tokens per server

      diff --git a/pr/255/docs/iroh_quinn_proto/struct.TokenReuseError.html b/pr/255/docs/iroh_quinn_proto/struct.TokenReuseError.html index f9f3a3702..83675d7a1 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.TokenReuseError.html +++ b/pr/255/docs/iroh_quinn_proto/struct.TokenReuseError.html @@ -1,4 +1,4 @@ -TokenReuseError in iroh_quinn_proto - Rust

      TokenReuseError

      Struct TokenReuseError 

      Source
      pub struct TokenReuseError;
      Expand description

      Error for when a validation token may have been reused

      +TokenReuseError in iroh_quinn_proto - Rust

      TokenReuseError

      Struct TokenReuseError 

      Source
      pub struct TokenReuseError;
      Expand description

      Error for when a validation token may have been reused

      Auto Trait Implementations§

      Blanket Implementations§

      Source§

      impl<T> Any for T
      where T: 'static + ?Sized,

      Source§

      fn type_id(&self) -> TypeId

      Gets the TypeId of self. Read more
      Source§

      impl<T> Borrow<T> for T
      where T: ?Sized,

      Source§

      fn borrow(&self) -> &T

      Immutably borrows from an owned value. Read more
      Source§

      impl<T> BorrowMut<T> for T
      where diff --git a/pr/255/docs/iroh_quinn_proto/struct.Transmit.html b/pr/255/docs/iroh_quinn_proto/struct.Transmit.html index bd722850a..db16e71f7 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.Transmit.html +++ b/pr/255/docs/iroh_quinn_proto/struct.Transmit.html @@ -1,4 +1,4 @@ -Transmit in iroh_quinn_proto - Rust

      Transmit

      Struct Transmit 

      Source
      pub struct Transmit {
      +Transmit in iroh_quinn_proto - Rust

      Transmit

      Struct Transmit 

      Source
      pub struct Transmit {
           pub destination: SocketAddr,
           pub ecn: Option<EcnCodepoint>,
           pub size: usize,
      diff --git a/pr/255/docs/iroh_quinn_proto/struct.TransportConfig.html b/pr/255/docs/iroh_quinn_proto/struct.TransportConfig.html
      index 9a20088f7..7acfebb8c 100644
      --- a/pr/255/docs/iroh_quinn_proto/struct.TransportConfig.html
      +++ b/pr/255/docs/iroh_quinn_proto/struct.TransportConfig.html
      @@ -1,4 +1,4 @@
      -TransportConfig in iroh_quinn_proto - Rust

      TransportConfig

      Struct TransportConfig 

      Source
      pub struct TransportConfig { /* private fields */ }
      Expand description

      Parameters governing the core QUIC state machine

      +TransportConfig in iroh_quinn_proto - Rust

      TransportConfig

      Struct TransportConfig 

      Source
      pub struct TransportConfig { /* private fields */ }
      Expand description

      Parameters governing the core QUIC state machine

      Default values should be suitable for most internet applications. Applications protocols which forbid remotely-initiated streams should set max_concurrent_bidi_streams and max_concurrent_uni_streams to zero.

      diff --git a/pr/255/docs/iroh_quinn_proto/struct.TransportError.html b/pr/255/docs/iroh_quinn_proto/struct.TransportError.html index 88b89ea98..a881a3952 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.TransportError.html +++ b/pr/255/docs/iroh_quinn_proto/struct.TransportError.html @@ -1,4 +1,4 @@ -TransportError in iroh_quinn_proto - Rust

      TransportError

      Struct TransportError 

      Source
      #[non_exhaustive]
      pub struct TransportError { +TransportError in iroh_quinn_proto - Rust

      TransportError

      Struct TransportError 

      Source
      #[non_exhaustive]
      pub struct TransportError { pub code: Code, pub frame: MaybeFrame, pub reason: String, @@ -11,7 +11,7 @@
      §reason: String

      Human-readable explanation of the reason

      §crypto: Option<Arc<dyn Error + Send + Sync>>

      An underlying crypto (e.g. TLS) layer error

      Implementations§

      Source§

      impl Error

      Source

      pub fn new(code: Code, reason: String) -> Self

      Construct an error with a code and a reason

      -

      Trait Implementations§

      Source§

      impl Clone for Error

      Source§

      fn clone(&self) -> Error

      Returns a duplicate of the value. Read more
      1.0.0 · Source§

      fn clone_from(&mut self, source: &Self)

      Performs copy-assignment from source. Read more
      Source§

      impl Debug for Error

      Source§

      fn fmt(&self, f: &mut Formatter<'_>) -> Result

      Formats the value using the given formatter. Read more
      Source§

      impl Display for Error

      Source§

      fn fmt(&self, f: &mut Formatter<'_>) -> Result

      Formats the value using the given formatter. Read more
      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 more
      1.0.0 · Source§

      fn description(&self) -> &str

      👎Deprecated since 1.42.0: use the Display impl or to_string()
      1.0.0 · Source§

      fn cause(&self) -> Option<&dyn Error>

      👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
      Source§

      fn provide<'a>(&'a self, request: &mut Request<'a>)

      🔬This is a nightly-only experimental API. (error_generic_member_access)
      Provides type-based access to context intended for error reports. Read more
      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§

      fn from(e: Error) -> Self

      Converts to this type from the input type.
      Source§

      impl PartialEq for Error

      Source§

      fn eq(&self, other: &Self) -> bool

      Tests for self and other values to be equal, and is used by ==.
      1.0.0 · Source§

      fn ne(&self, other: &Rhs) -> bool

      Tests for !=. The default implementation is almost always sufficient, +

      Trait Implementations§

      Source§

      impl Clone for Error

      Source§

      fn clone(&self) -> Error

      Returns a duplicate of the value. Read more
      1.0.0 · Source§

      fn clone_from(&mut self, source: &Self)

      Performs copy-assignment from source. Read more
      Source§

      impl Debug for Error

      Source§

      fn fmt(&self, f: &mut Formatter<'_>) -> Result

      Formats the value using the given formatter. Read more
      Source§

      impl Display for Error

      Source§

      fn fmt(&self, f: &mut Formatter<'_>) -> Result

      Formats the value using the given formatter. Read more
      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 more
      1.0.0 · Source§

      fn description(&self) -> &str

      👎Deprecated since 1.42.0: use the Display impl or to_string()
      1.0.0 · Source§

      fn cause(&self) -> Option<&dyn Error>

      👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
      Source§

      fn provide<'a>(&'a self, request: &mut Request<'a>)

      🔬This is a nightly-only experimental API. (error_generic_member_access)
      Provides type-based access to context intended for error reports. Read more
      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§

      fn from(e: Error) -> Self

      Converts to this type from the input type.
      Source§

      impl PartialEq for Error

      Source§

      fn eq(&self, other: &Self) -> bool

      Tests for self and other values to be equal, and is used by ==.
      1.0.0 · Source§

      fn ne(&self, other: &Rhs) -> bool

      Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
      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> Any for T
      where T: 'static + ?Sized,

      Source§

      fn type_id(&self) -> TypeId

      Gets the TypeId of self. Read more
      Source§

      impl<T> Borrow<T> for T
      where T: ?Sized,

      Source§

      fn borrow(&self) -> &T

      Immutably borrows from an owned value. Read more
      Source§

      impl<T> BorrowMut<T> for T
      where diff --git a/pr/255/docs/iroh_quinn_proto/struct.TransportErrorCode.html b/pr/255/docs/iroh_quinn_proto/struct.TransportErrorCode.html index edb99b831..29037e6ae 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.TransportErrorCode.html +++ b/pr/255/docs/iroh_quinn_proto/struct.TransportErrorCode.html @@ -1,4 +1,4 @@ -TransportErrorCode in iroh_quinn_proto - Rust

      TransportErrorCode

      Struct TransportErrorCode 

      Source
      pub struct TransportErrorCode(/* private fields */);
      Expand description

      Transport-level error code

      +TransportErrorCode in iroh_quinn_proto - Rust

      TransportErrorCode

      Struct TransportErrorCode 

      Source
      pub struct TransportErrorCode(/* private fields */);
      Expand description

      Transport-level error code

      Implementations§

      Source§

      impl Code

      Source

      pub fn crypto(code: u8) -> Self

      Create QUIC error code from TLS alert code

      Source§

      impl Code

      Source

      pub const NO_ERROR: Self

      the connection is being closed abruptly in the absence of any error

      Source

      pub const INTERNAL_ERROR: Self

      the endpoint encountered an internal error and cannot continue with the connection

      diff --git a/pr/255/docs/iroh_quinn_proto/struct.UdpStats.html b/pr/255/docs/iroh_quinn_proto/struct.UdpStats.html index 01764d80a..cf2e64a6a 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.UdpStats.html +++ b/pr/255/docs/iroh_quinn_proto/struct.UdpStats.html @@ -1,4 +1,4 @@ -UdpStats in iroh_quinn_proto - Rust

      UdpStats

      Struct UdpStats 

      Source
      #[non_exhaustive]
      pub struct UdpStats { +UdpStats in iroh_quinn_proto - Rust

      UdpStats

      Struct UdpStats 

      Source
      #[non_exhaustive]
      pub struct UdpStats { pub datagrams: u64, pub bytes: u64, pub ios: u64, diff --git a/pr/255/docs/iroh_quinn_proto/struct.ValidationTokenConfig.html b/pr/255/docs/iroh_quinn_proto/struct.ValidationTokenConfig.html index 3622887b9..86e1276ca 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.ValidationTokenConfig.html +++ b/pr/255/docs/iroh_quinn_proto/struct.ValidationTokenConfig.html @@ -1,4 +1,4 @@ -ValidationTokenConfig in iroh_quinn_proto - Rust

      ValidationTokenConfig

      Struct ValidationTokenConfig 

      Source
      pub struct ValidationTokenConfig { /* private fields */ }
      Expand description

      Configuration for sending and handling validation tokens in incoming connections

      +ValidationTokenConfig in iroh_quinn_proto - Rust

      ValidationTokenConfig

      Struct ValidationTokenConfig 

      Source
      pub struct ValidationTokenConfig { /* private fields */ }
      Expand description

      Configuration for sending and handling validation tokens in incoming connections

      Default values should be suitable for most internet applications.

      §QUIC Tokens

      The QUIC protocol defines a concept of “address validation”. Essentially, one side of a diff --git a/pr/255/docs/iroh_quinn_proto/struct.VarInt.html b/pr/255/docs/iroh_quinn_proto/struct.VarInt.html index 4265325b3..816caf26b 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.VarInt.html +++ b/pr/255/docs/iroh_quinn_proto/struct.VarInt.html @@ -1,4 +1,4 @@ -VarInt in iroh_quinn_proto - Rust

      VarInt

      Struct VarInt 

      Source
      pub struct VarInt(/* private fields */);
      Expand description

      An integer less than 2^62

      +VarInt in iroh_quinn_proto - Rust

      VarInt

      Struct VarInt 

      Source
      pub struct VarInt(/* private fields */);
      Expand description

      An integer less than 2^62

      Values of this type are suitable for encoding as QUIC variable-length integer.

      Implementations§

      Source§

      impl VarInt

      Source

      pub const MAX: Self

      The largest representable value

      Source

      pub const MAX_SIZE: usize = 8usize

      The largest encoded value length

      diff --git a/pr/255/docs/iroh_quinn_proto/struct.VarIntBoundsExceeded.html b/pr/255/docs/iroh_quinn_proto/struct.VarIntBoundsExceeded.html index b70dd0785..26affd0ac 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.VarIntBoundsExceeded.html +++ b/pr/255/docs/iroh_quinn_proto/struct.VarIntBoundsExceeded.html @@ -1,4 +1,4 @@ -VarIntBoundsExceeded in iroh_quinn_proto - Rust

      VarIntBoundsExceeded

      Struct VarIntBoundsExceeded 

      Source
      pub struct VarIntBoundsExceeded;
      Expand description

      Error returned when constructing a VarInt from a value >= 2^62

      +VarIntBoundsExceeded in iroh_quinn_proto - Rust

      VarIntBoundsExceeded

      Struct VarIntBoundsExceeded 

      Source
      pub struct VarIntBoundsExceeded;
      Expand description

      Error returned when constructing a VarInt from a value >= 2^62

      Trait Implementations§

      Source§

      impl Clone for VarIntBoundsExceeded

      Source§

      fn clone(&self) -> VarIntBoundsExceeded

      Returns a duplicate of the value. Read more
      1.0.0 · Source§

      fn clone_from(&mut self, source: &Self)

      Performs copy-assignment from source. Read more
      Source§

      impl Debug for VarIntBoundsExceeded

      Source§

      fn fmt(&self, f: &mut Formatter<'_>) -> Result

      Formats the value using the given formatter. Read more
      Source§

      impl Display for VarIntBoundsExceeded

      Source§

      fn fmt(&self, __formatter: &mut Formatter<'_>) -> Result

      Formats the value using the given formatter. Read more
      Source§

      impl Error for VarIntBoundsExceeded

      1.30.0 · Source§

      fn source(&self) -> Option<&(dyn Error + 'static)>

      Returns the lower-level source of this error, if any. Read more
      1.0.0 · Source§

      fn description(&self) -> &str

      👎Deprecated since 1.42.0: use the Display impl or to_string()
      1.0.0 · Source§

      fn cause(&self) -> Option<&dyn Error>

      👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
      Source§

      fn provide<'a>(&'a self, request: &mut Request<'a>)

      🔬This is a nightly-only experimental API. (error_generic_member_access)
      Provides type-based access to context intended for error reports. Read more
      Source§

      impl From<VarIntBoundsExceeded> for ConfigError

      Source§

      fn from(_: VarIntBoundsExceeded) -> Self

      Converts to this type from the input type.
      Source§

      impl PartialEq for VarIntBoundsExceeded

      Source§

      fn eq(&self, other: &VarIntBoundsExceeded) -> bool

      Tests for self and other values to be equal, and is used by ==.
      1.0.0 · Source§

      fn ne(&self, other: &Rhs) -> bool

      Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
      Source§

      impl Copy for VarIntBoundsExceeded

      Source§

      impl Eq for VarIntBoundsExceeded

      Source§

      impl StructuralPartialEq for VarIntBoundsExceeded

      Auto Trait Implementations§

      Blanket Implementations§

      Source§

      impl<T> Any for T
      where T: 'static + ?Sized,

      Source§

      fn type_id(&self) -> TypeId

      Gets the TypeId of self. Read more
      Source§

      impl<T> Borrow<T> for T
      where diff --git a/pr/255/docs/iroh_quinn_proto/struct.Written.html b/pr/255/docs/iroh_quinn_proto/struct.Written.html index fb6ec6f22..5878e3e2a 100644 --- a/pr/255/docs/iroh_quinn_proto/struct.Written.html +++ b/pr/255/docs/iroh_quinn_proto/struct.Written.html @@ -1,12 +1,12 @@ -Written in iroh_quinn_proto - Rust

      Written

      Struct Written 

      Source
      pub struct Written {
      +Written in iroh_quinn_proto - Rust

      Written

      Struct Written 

      Source
      pub struct Written {
           pub bytes: usize,
           pub chunks: usize,
       }
      Expand description

      Indicates how many bytes and chunks had been transferred in a write operation

      Fields§

      §bytes: usize

      The amount of bytes which had been written

      §chunks: usize

      The amount of full chunks which had been written

      If a chunk was only partially written, it will not be counted by this field.

      -

      Trait Implementations§

      Source§

      impl Clone for Written

      Source§

      fn clone(&self) -> Written

      Returns a duplicate of the value. Read more
      1.0.0 · Source§

      fn clone_from(&mut self, source: &Self)

      Performs copy-assignment from source. Read more
      Source§

      impl Debug for Written

      Source§

      fn fmt(&self, f: &mut Formatter<'_>) -> Result

      Formats the value using the given formatter. Read more
      Source§

      impl Default for Written

      Source§

      fn default() -> Written

      Returns the “default value” for a type. Read more
      Source§

      impl PartialEq for Written

      Source§

      fn eq(&self, other: &Written) -> bool

      Tests for self and other values to be equal, and is used by ==.
      1.0.0 · Source§

      fn ne(&self, other: &Rhs) -> bool

      Tests for !=. The default implementation is almost always sufficient, -and should not be overridden without very good reason.
      Source§

      impl Copy for Written

      Source§

      impl Eq for Written

      Source§

      impl StructuralPartialEq for Written

      Auto Trait Implementations§

      Blanket Implementations§

      Source§

      impl<T> Any for T
      where +

      Trait Implementations§

      Source§

      impl Clone for Written

      Source§

      fn clone(&self) -> Written

      Returns a duplicate of the value. Read more
      1.0.0 · Source§

      fn clone_from(&mut self, source: &Self)

      Performs copy-assignment from source. Read more
      Source§

      impl Debug for Written

      Source§

      fn fmt(&self, f: &mut Formatter<'_>) -> Result

      Formats the value using the given formatter. Read more
      Source§

      impl Default for Written

      Source§

      fn default() -> Written

      Returns the “default value” for a type. Read more
      Source§

      impl PartialEq for Written

      Source§

      fn eq(&self, other: &Written) -> bool

      Tests for self and other values to be equal, and is used by ==.
      1.0.0 · Source§

      fn ne(&self, other: &Rhs) -> bool

      Tests for !=. The default implementation is almost always sufficient, +and should not be overridden without very good reason.
      Source§

      impl Copy for Written

      Source§

      impl Eq for Written

      Source§

      impl StructuralPartialEq for Written

      Auto Trait Implementations§

      Blanket Implementations§

      Source§

      impl<T> Any for T
      where T: 'static + ?Sized,

      Source§

      fn type_id(&self) -> TypeId

      Gets the TypeId of self. Read more
      Source§

      impl<T> Borrow<T> for T
      where T: ?Sized,

      Source§

      fn borrow(&self) -> &T

      Immutably borrows from an owned value. Read more
      Source§

      impl<T> BorrowMut<T> for T
      where T: ?Sized,

      Source§

      fn borrow_mut(&mut self) -> &mut T

      Mutably borrows from an owned value. Read more
      Source§

      impl<T> CloneToUninit for T
      where diff --git a/pr/255/docs/iroh_quinn_proto/trait.ConnectionIdGenerator.html b/pr/255/docs/iroh_quinn_proto/trait.ConnectionIdGenerator.html index 12479fd74..550af1f81 100644 --- a/pr/255/docs/iroh_quinn_proto/trait.ConnectionIdGenerator.html +++ b/pr/255/docs/iroh_quinn_proto/trait.ConnectionIdGenerator.html @@ -1,4 +1,4 @@ -ConnectionIdGenerator in iroh_quinn_proto - Rust

      ConnectionIdGenerator

      Trait ConnectionIdGenerator 

      Source
      pub trait ConnectionIdGenerator: Send + Sync {
      +ConnectionIdGenerator in iroh_quinn_proto - Rust

      ConnectionIdGenerator

      Trait ConnectionIdGenerator 

      Source
      pub trait ConnectionIdGenerator: Send + Sync {
           // Required methods
           fn generate_cid(&mut self) -> ConnectionId;
           fn cid_len(&self) -> usize;
      diff --git a/pr/255/docs/iroh_quinn_proto/trait.ConnectionIdParser.html b/pr/255/docs/iroh_quinn_proto/trait.ConnectionIdParser.html
      index 9503bd58a..e3357d299 100644
      --- a/pr/255/docs/iroh_quinn_proto/trait.ConnectionIdParser.html
      +++ b/pr/255/docs/iroh_quinn_proto/trait.ConnectionIdParser.html
      @@ -1,4 +1,4 @@
      -ConnectionIdParser in iroh_quinn_proto - Rust

      ConnectionIdParser

      Trait ConnectionIdParser 

      Source
      pub trait ConnectionIdParser {
      +ConnectionIdParser in iroh_quinn_proto - Rust

      ConnectionIdParser

      Trait ConnectionIdParser 

      Source
      pub trait ConnectionIdParser {
           // Required method
           fn parse(
               &self,
      diff --git a/pr/255/docs/iroh_quinn_proto/trait.QlogFactory.html b/pr/255/docs/iroh_quinn_proto/trait.QlogFactory.html
      index 2830f4fd3..3e26f98c0 100644
      --- a/pr/255/docs/iroh_quinn_proto/trait.QlogFactory.html
      +++ b/pr/255/docs/iroh_quinn_proto/trait.QlogFactory.html
      @@ -1,4 +1,4 @@
      -QlogFactory in iroh_quinn_proto - Rust

      QlogFactory

      Trait QlogFactory 

      Source
      pub trait QlogFactory:
      +QlogFactory in iroh_quinn_proto - Rust

      QlogFactory

      Trait QlogFactory 

      Source
      pub trait QlogFactory:
           Send
           + Sync
           + 'static {
      diff --git a/pr/255/docs/iroh_quinn_proto/trait.TimeSource.html b/pr/255/docs/iroh_quinn_proto/trait.TimeSource.html
      index ad97fe27d..009a32eb4 100644
      --- a/pr/255/docs/iroh_quinn_proto/trait.TimeSource.html
      +++ b/pr/255/docs/iroh_quinn_proto/trait.TimeSource.html
      @@ -1,4 +1,4 @@
      -TimeSource in iroh_quinn_proto - Rust

      TimeSource

      Trait TimeSource 

      Source
      pub trait TimeSource: Send + Sync {
      +TimeSource in iroh_quinn_proto - Rust

      TimeSource

      Trait TimeSource 

      Source
      pub trait TimeSource: Send + Sync {
           // Required method
           fn now(&self) -> SystemTime;
       }
      Expand description

      Object to get current SystemTime

      diff --git a/pr/255/docs/iroh_quinn_proto/trait.TokenLog.html b/pr/255/docs/iroh_quinn_proto/trait.TokenLog.html index 0a440a60d..51695e4a2 100644 --- a/pr/255/docs/iroh_quinn_proto/trait.TokenLog.html +++ b/pr/255/docs/iroh_quinn_proto/trait.TokenLog.html @@ -1,4 +1,4 @@ -TokenLog in iroh_quinn_proto - Rust

      TokenLog

      Trait TokenLog 

      Source
      pub trait TokenLog: Send + Sync {
      +TokenLog in iroh_quinn_proto - Rust

      TokenLog

      Trait TokenLog 

      Source
      pub trait TokenLog: Send + Sync {
           // Required method
           fn check_and_insert(
               &self,
      diff --git a/pr/255/docs/iroh_quinn_proto/trait.TokenStore.html b/pr/255/docs/iroh_quinn_proto/trait.TokenStore.html
      index af8cf71ba..60774f806 100644
      --- a/pr/255/docs/iroh_quinn_proto/trait.TokenStore.html
      +++ b/pr/255/docs/iroh_quinn_proto/trait.TokenStore.html
      @@ -1,4 +1,4 @@
      -TokenStore in iroh_quinn_proto - Rust

      TokenStore

      Trait TokenStore 

      Source
      pub trait TokenStore: Send + Sync {
      +TokenStore in iroh_quinn_proto - Rust

      TokenStore

      Trait TokenStore 

      Source
      pub trait TokenStore: Send + Sync {
           // Required methods
           fn insert(&self, server_name: &str, token: Bytes);
           fn take(&self, server_name: &str) -> Option<Bytes>;
      diff --git a/pr/255/docs/iroh_quinn_proto/transport_parameters/enum.Error.html b/pr/255/docs/iroh_quinn_proto/transport_parameters/enum.Error.html
      index a60d1a52d..473d608a5 100644
      --- a/pr/255/docs/iroh_quinn_proto/transport_parameters/enum.Error.html
      +++ b/pr/255/docs/iroh_quinn_proto/transport_parameters/enum.Error.html
      @@ -1,4 +1,4 @@
      -Error in iroh_quinn_proto::transport_parameters - Rust

      Error

      Enum Error 

      Source
      pub enum Error {
      +Error in iroh_quinn_proto::transport_parameters - Rust

      Error

      Enum Error 

      Source
      pub enum Error {
           IllegalValue,
           Malformed,
       }
      Expand description

      Errors encountered while decoding TransportParameters

      diff --git a/pr/255/docs/iroh_quinn_proto/transport_parameters/index.html b/pr/255/docs/iroh_quinn_proto/transport_parameters/index.html index b8239f12a..922be4498 100644 --- a/pr/255/docs/iroh_quinn_proto/transport_parameters/index.html +++ b/pr/255/docs/iroh_quinn_proto/transport_parameters/index.html @@ -1,4 +1,4 @@ -iroh_quinn_proto::transport_parameters - Rust

      Module transport_parameters

      Module transport_parameters 

      Source
      Expand description

      QUIC connection transport parameters

      +iroh_quinn_proto::transport_parameters - Rust

      Module transport_parameters

      Module transport_parameters 

      Source
      Expand description

      QUIC connection transport parameters

      The TransportParameters type is used to represent the transport parameters negotiated by peers while establishing a QUIC connection. This process happens as part of the establishment of the TLS session. As such, the types diff --git a/pr/255/docs/iroh_quinn_proto/transport_parameters/struct.TransportParameters.html b/pr/255/docs/iroh_quinn_proto/transport_parameters/struct.TransportParameters.html index 854345bff..e71df8b2f 100644 --- a/pr/255/docs/iroh_quinn_proto/transport_parameters/struct.TransportParameters.html +++ b/pr/255/docs/iroh_quinn_proto/transport_parameters/struct.TransportParameters.html @@ -1,4 +1,4 @@ -TransportParameters in iroh_quinn_proto::transport_parameters - Rust

      TransportParameters

      Struct TransportParameters 

      Source
      pub struct TransportParameters {
      +TransportParameters in iroh_quinn_proto::transport_parameters - Rust

      TransportParameters

      Struct TransportParameters 

      Source
      pub struct TransportParameters {
           pub max_remote_nat_traversal_addresses: Option<NonZeroU8>,
           /* private fields */
       }
      Expand description

      Transport parameters used to negotiate connection-level preferences between peers

      diff --git a/pr/255/docs/iroh_quinn_udp/all.html b/pr/255/docs/iroh_quinn_udp/all.html index bf279c3f6..7f86942ad 100644 --- a/pr/255/docs/iroh_quinn_udp/all.html +++ b/pr/255/docs/iroh_quinn_udp/all.html @@ -1 +1 @@ -List of all items in this crate

      All

      \ No newline at end of file +List of all items in this crate

      All

      \ No newline at end of file diff --git a/pr/255/docs/iroh_quinn_udp/constant.BATCH_SIZE.html b/pr/255/docs/iroh_quinn_udp/constant.BATCH_SIZE.html index aeff14292..614b84d17 100644 --- a/pr/255/docs/iroh_quinn_udp/constant.BATCH_SIZE.html +++ b/pr/255/docs/iroh_quinn_udp/constant.BATCH_SIZE.html @@ -1,2 +1,2 @@ -BATCH_SIZE in iroh_quinn_udp - Rust

      BATCH_SIZE

      Constant BATCH_SIZE 

      Source
      pub const BATCH_SIZE: usize = imp::BATCH_SIZE; // 32usize
      Expand description

      Number of UDP packets to send/receive at a time

      +BATCH_SIZE in iroh_quinn_udp - Rust

      BATCH_SIZE

      Constant BATCH_SIZE 

      Source
      pub const BATCH_SIZE: usize = imp::BATCH_SIZE; // 32usize
      Expand description

      Number of UDP packets to send/receive at a time

      \ No newline at end of file diff --git a/pr/255/docs/iroh_quinn_udp/enum.EcnCodepoint.html b/pr/255/docs/iroh_quinn_udp/enum.EcnCodepoint.html index c130f9df1..a7fa2b6bf 100644 --- a/pr/255/docs/iroh_quinn_udp/enum.EcnCodepoint.html +++ b/pr/255/docs/iroh_quinn_udp/enum.EcnCodepoint.html @@ -1,4 +1,4 @@ -EcnCodepoint in iroh_quinn_udp - Rust

      EcnCodepoint

      Enum EcnCodepoint 

      Source
      #[repr(u8)]
      pub enum EcnCodepoint { +EcnCodepoint in iroh_quinn_udp - Rust

      EcnCodepoint

      Enum EcnCodepoint 

      Source
      #[repr(u8)]
      pub enum EcnCodepoint { Ect0 = 2, Ect1 = 1, Ce = 3, diff --git a/pr/255/docs/iroh_quinn_udp/index.html b/pr/255/docs/iroh_quinn_udp/index.html index 189d8f7f7..249f5cb53 100644 --- a/pr/255/docs/iroh_quinn_udp/index.html +++ b/pr/255/docs/iroh_quinn_udp/index.html @@ -1,4 +1,4 @@ -iroh_quinn_udp - Rust

      Crate iroh_quinn_udp

      Crate iroh_quinn_udp 

      Source
      Expand description

      Uniform interface to send and receive UDP packets with advanced features useful for QUIC

      +iroh_quinn_udp - Rust

      Crate iroh_quinn_udp

      Crate iroh_quinn_udp 

      Source
      Expand description

      Uniform interface to send and receive UDP packets with advanced features useful for QUIC

      This crate exposes kernel UDP stack features available on most modern systems which are required for an efficient and conformant QUIC implementation. As of this writing, these are not available in std or major async runtimes, and their niche character and complexity are a barrier to adding diff --git a/pr/255/docs/iroh_quinn_udp/struct.RecvMeta.html b/pr/255/docs/iroh_quinn_udp/struct.RecvMeta.html index db917c321..1ca339258 100644 --- a/pr/255/docs/iroh_quinn_udp/struct.RecvMeta.html +++ b/pr/255/docs/iroh_quinn_udp/struct.RecvMeta.html @@ -1,4 +1,4 @@ -RecvMeta in iroh_quinn_udp - Rust

      RecvMeta

      Struct RecvMeta 

      Source
      #[non_exhaustive]
      pub struct RecvMeta { +RecvMeta in iroh_quinn_udp - Rust

      RecvMeta

      Struct RecvMeta 

      Source
      #[non_exhaustive]
      pub struct RecvMeta { pub addr: SocketAddr, pub len: usize, pub stride: usize, diff --git a/pr/255/docs/iroh_quinn_udp/struct.Transmit.html b/pr/255/docs/iroh_quinn_udp/struct.Transmit.html index b0cf49ba4..fd2d2d664 100644 --- a/pr/255/docs/iroh_quinn_udp/struct.Transmit.html +++ b/pr/255/docs/iroh_quinn_udp/struct.Transmit.html @@ -1,4 +1,4 @@ -Transmit in iroh_quinn_udp - Rust

      Transmit

      Struct Transmit 

      Source
      pub struct Transmit<'a> {
      +Transmit in iroh_quinn_udp - Rust

      Transmit

      Struct Transmit 

      Source
      pub struct Transmit<'a> {
           pub destination: SocketAddr,
           pub ecn: Option<EcnCodepoint>,
           pub contents: &'a [u8],
      diff --git a/pr/255/docs/iroh_quinn_udp/struct.UdpSockRef.html b/pr/255/docs/iroh_quinn_udp/struct.UdpSockRef.html
      index 046df30b2..80cd3bbb1 100644
      --- a/pr/255/docs/iroh_quinn_udp/struct.UdpSockRef.html
      +++ b/pr/255/docs/iroh_quinn_udp/struct.UdpSockRef.html
      @@ -1,4 +1,4 @@
      -UdpSockRef in iroh_quinn_udp - Rust

      UdpSockRef

      Struct UdpSockRef 

      Source
      pub struct UdpSockRef<'a>(/* private fields */);
      Expand description

      A borrowed UDP socket

      +UdpSockRef in iroh_quinn_udp - Rust

      UdpSockRef

      Struct UdpSockRef 

      Source
      pub struct UdpSockRef<'a>(/* private fields */);
      Expand description

      A borrowed UDP socket

      On Unix, constructible via From<T: AsFd>. On Windows, constructible via From<T: AsSocket>.

      Trait Implementations§

      Source§

      impl<'s, S> From<&'s S> for UdpSockRef<'s>
      where S: AsFd,

      Available on Unix only.
      Source§

      fn from(socket: &'s S) -> Self

      Converts to this type from the input type.

      Auto Trait Implementations§

      §

      impl<'a> Freeze for UdpSockRef<'a>

      §

      impl<'a> RefUnwindSafe for UdpSockRef<'a>

      §

      impl<'a> Send for UdpSockRef<'a>

      §

      impl<'a> Sync for UdpSockRef<'a>

      §

      impl<'a> Unpin for UdpSockRef<'a>

      §

      impl<'a> UnwindSafe for UdpSockRef<'a>

      Blanket Implementations§

      Source§

      impl<T> Any for T
      where diff --git a/pr/255/docs/iroh_quinn_udp/struct.UdpSocketState.html b/pr/255/docs/iroh_quinn_udp/struct.UdpSocketState.html index 0de55d35b..08b27feb1 100644 --- a/pr/255/docs/iroh_quinn_udp/struct.UdpSocketState.html +++ b/pr/255/docs/iroh_quinn_udp/struct.UdpSocketState.html @@ -1,4 +1,4 @@ -UdpSocketState in iroh_quinn_udp - Rust

      UdpSocketState

      Struct UdpSocketState 

      Source
      pub struct UdpSocketState { /* private fields */ }
      Expand description

      Tokio-compatible UDP socket with some useful specializations.

      +UdpSocketState in iroh_quinn_udp - Rust

      UdpSocketState

      Struct UdpSocketState 

      Source
      pub struct UdpSocketState { /* private fields */ }
      Expand description

      Tokio-compatible UDP socket with some useful specializations.

      Unlike a standard tokio UDP socket, this allows ECN bits to be read and written on some platforms.

      Implementations§

      Source§

      impl UdpSocketState

      Source

      pub fn new(sock: UdpSockRef<'_>) -> Result<Self>

      Source

      pub fn send( diff --git a/pr/255/docs/search.index/desc/a17424f36466.js b/pr/255/docs/search.index/desc/a17424f36466.js deleted file mode 100644 index 0c1886096..000000000 --- a/pr/255/docs/search.index/desc/a17424f36466.js +++ /dev/null @@ -1 +0,0 @@ -rd_("AmData flows in both directions0CdThe CE codepoint, signalling that congestion was \xe2\x80\xa600AjContains the success valueBeThe PathId of this path.AoGet the identity of this stream00AfWhich path is now openAjWhich path has been closedB`Which path had its state droppedBaPath for which the error occurredAmPath which has changed statusCfPath over which the observed address was reported, \xe2\x80\xa6AlWhich stream is now readableAlWhich stream is now writableAnWhich stream has been finishedAmWhich stream has been stoppedAnType of the Long header packetBcExperimental! Use at your own risk.0ClWhether a stream communicates data in both directions or \xe2\x80\xa60AhContains the error valueAoThe largest representable valueAlThe maximum path ID allowed.10ClConnects to a QUIC perf server and maintains a specified \xe2\x80\xa6BmData flows only from the stream\xe2\x80\x99s initiator0AnWhich directions data flows in0CaDirectionality for which streams have been openedCdDirectionality for which streams are newly availableCjExplicit congestion notification bits to set on the packet0CeThe Explicit Congestion Notification bits for the \xe2\x80\xa61B`The current best RTT estimation.BeThe amount of I/O operations executed0BcLength of QUIC packet being decodedAlLength of the packet payload0BmThe number of bytes the associated buffer hasBbSet a custom TokenLog0CaMinimum RTT registered so far for this estimator.ClConstruct with an approximate maximum memory usage and a \xe2\x80\xa6CjConstruct an endpoint with arbitrary configuration and \xe2\x80\xa6DiCreates a new QlogConfig that writes a qlog trace to the \xe2\x80\xa6CiCreates a new qlog factory that writes files into the \xe2\x80\xa6D`Create a default config with a particular reset_keyCmCreate a default config with a particular handshake token \xe2\x80\xa6CkCreate a default config with a particular cryptographic \xe2\x80\xa6AmConstruct cid from byte arrayoConstruct emptyAeCreate a new StreamIdDjConstruct a state using the given config and current time \xe2\x80\xa600:8AeCreate a new endpointDcCreate a new instance of FixedLengthConnectionIdParserBdCreate a generator with a random key:987DgBegin decoding a QUIC packet from bytes, returning any \xe2\x80\xa67BkConstruct an error with a code and a reasonCgInitialize Random CID generator with a fixed CID length87666CkGet SystemTime::now() or the mocked equivalentAhLook up the current time01ChCurrent best estimate of this connection\xe2\x80\x99s latency \xe2\x80\xa6000ChThe ECT(0) codepoint, indicating that an endpoint is \xe2\x80\xa600ChThe ECT(1) codepoint, indicating that an endpoint is \xe2\x80\xa600CaA complete set of keys for a certain packet space0CbA Long packet header, as used during the handshakeAcAn open (Multi)PathAb(Multi)Path eventsB`An error occurred during readingCeWhether an endpoint was the initiator of a connection0nThe 0 path id.0CaThe address observed by the remote over this pathCjThe source address of the datagram(s) contained in the \xe2\x80\xa6mType of errorBkCurrent congestion window of the connection0gPayloadAoReturns the argument unchanged.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000BaCalls U::from(self).000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000dNextCeMethod for opening a sealed message dataB`Open a single stream if possible1CgReturns the Path structure of an open pathBhPing the remote endpoint over this path.AhPing the remote endpointCkCheck whether the timer has expired, and register to be \xe2\x80\xa6BaReturns application-facing eventsBgRead data contiguously from the stream.AoRead from the given recv streamCcDecode TransportParameters from bufferBiReceive an unreliable, unordered datagramBlMethod for sealing message data0CiQueue an unreliable, unordered datagram for immediate \xe2\x80\xa6CbSends a Transmit on the given socket.CmNumber of address validation tokens sent to a client when \xe2\x80\xa60BmThe side of the connection (client or server)ChLook up whether we\xe2\x80\x99re the client or server of this \xe2\x80\xa6AlMethod for signing a message0CdAmount of data written to the caller-supplied buffer0hSpin bitAcStop accepting data0BoStop accepting data on the given receive streamCiTry to find and take a token that was stored with the \xe2\x80\xa60BgA chunk of data from the receive stream0CiThe RFC8312 congestion controller, as widely used for TCP0Borustls reports protocol errors using this type.0DbErrors encountered while decoding TransportParametersCdErrors that the nat traversal state might encounter.BeEvents of interest to the applicationCiEvent emitted when the client receives ADD_ADDRESS or \xe2\x80\xa6A`Any other error.0CcThe peer abandoned transmitting data on this streamCnThe peer is unable to continue processing this connection, \xe2\x80\xa6CdThe peer abandoned transmitting data on this stream.1AeA Retry packet headerCdA short packet header, as used during the data phaseBiConstruct a fresh Controller0AiThe contents of the chunkCiThe total amount of bytes which have been transferred \xe2\x80\xa6BjThe amount of bytes which had been written210BnUnderlying error describing reason for failureBaClose the connection immediately.CnClose all of this endpoint\xe2\x80\x99s connections immediately and \xe2\x80\xa6A`Closes this pathAnClose a connection immediatelyAgThe error that occurredBcFrame type that triggered the errorCcDistinguishes streams of the same initiator and \xe2\x80\xa60CjReturns whether the codepoint is a CE, signalling that \xe2\x80\xa60AgKey for encrypting data0BgParse a connection id from given bufferAhReturns all known paths.BlUpdate the timer to expire at iBbClose the send stream immediately.BeAbandon transmitting data on a streamCnRespond with a retry packet, requiring the client to retry \xe2\x80\xa60CiDrive future to completion in the backgroundCeShow connection stats the at the end of the benchmarkAmReturns connection statisticsBiReturns relevant stats from this Endpoint1BcTitle to record in the qlog capture0CmWrite a buffer into this stream, returning how many bytes \xe2\x80\xa6AmSend data on the given streamCcEncode TransportParameters into bufferC`Future produced by Endpoint::acceptClPaths marked as backup will only be used if there are no \xe2\x80\xa6CeChunks returned from RecvStream::read().AmThe initiator of a connection0AdRun as a perf clientAfA path has been closedCgAttempted to initiate NAT traversal on a closed, or \xe2\x80\xa6CcFuture produced by Connection::open_biAjA new path has been openedChOne or more new streams has been opened and might be \xe2\x80\xa6ChId representing different paths when using multipath \xe2\x80\xa60AbCoding result typeAlThe acceptor of a connection0AdRun as a perf servermStream eventsAiAn integer less than 2^620CfGet the next incoming connection attempt from a clientClAttempt to accept this incoming connection (an error may \xe2\x80\xa6CcAccept a remotely initiated stream of a certain \xe2\x80\xa61C`The amount of full chunks which had been written0BlAllows to configure the desired cipher suiteCiHelper to construct an endpoint for use with outgoing \xe2\x80\xa6CcWait for the connection to be closed for any reasonAfCoding related traits.BnAccess the configuration used by this endpointChTraits and implementations for the QUIC cryptography \xe2\x80\xa6BjCreate QUIC error code from TLS alert codeBoTLS configuration used for incoming connections210BkAn underlying crypto (e.g. TLS) layer errorCgDecode a plain header from given buffer, with given \xe2\x80\xa6DiDecode a Self from the provided buffer, if the buffer is \xe2\x80\xa6ChThe destination IP address which was encoded in this \xe2\x80\xa6D`Append the encoding of self to the provided buffer.CmNotify the peer that no more data will ever be written to \xe2\x80\xa6CnFinish a send stream, signalling that no more data will be \xe2\x80\xa6B`Process an incoming UDP datagramAfHeader protection keys0ClIgnore this incoming connection attempt, not sending any \xe2\x80\xa60C`Potentially store a token for later one-time use0CfPerform NSS-compatible TLS key logging to the file \xe2\x80\xa6AhThe offset in the stream0B`Packet deliveries were confirmed0AfPacket protection keys0lRandom valueBcHuman-readable reason for the close000BhHuman-readable explanation of the reasonBeReason that the connection was closedAjSwitch to a new UDP socketBgReject this incoming connection attempt0AgKey for decrypting dataAmThe remote side of this tuple1AmTLS interface based on rustls0CnHelper to construct an endpoint for use with both incoming \xe2\x80\xa6BkOptional source IP address for the datagram00CgThe current local PathStatus of this path.B`The new status set by the remoteCfThe size of a single datagram in the associated bufferCgStatistics about UDP datagrams received on a connection0CjStatistics about UDP datagrams transmitted on a connection0AnMethod for verifying a message0CcNumber of ack-eliciting bytes that may be in flight0CaA key for sealing data with AEAD-based algorithms0A`Send would blockCcNo more data is currently available on this stream.CjThe peer is not able to accept additional data, or the \xe2\x80\xa6BfA catch-all error for unlikely errors.0BlA key for signing with HMAC-based algorithms0AhAn Initial packet headerBnA pair of keys for bidirectional communication0BhA simple, standard congestion controller0CdFuture produced by Connection::open_uniCkAbstracts I/O and timer operations for runtime independenceBfA cryptographic session (commonly TLS)0CcThe peer is no longer accepting data on this streamClThe peer is no longer accepting data on this stream, and \xe2\x80\xa6CkThe peer is no longer accepting data on this stream. No \xe2\x80\xa6CgThe peer asked us to stop sending on an outgoing streamAaAccess to streamsCaThe stream is larger than the user-supplied limitClIndicates how many bytes and chunks had been transferred \xe2\x80\xa60l0-RTT packetCjReturns the length of a CID for connections created by \xe2\x80\xa60CdProvide the length of dst_cid in short header packetCcThe total number of clients which should be createdAlConnect to a remote endpointAeInitiate a connectionCgDecrypt the packet payload with the given packet numberBcDecrypt the given packet\xe2\x80\x99s header10ClConstructs a value with arbitrary fields, intended to be \xe2\x80\xa6DjConstruct an event that indicating that a Connection will \xe2\x80\xa6BkThe destination connection ID of the packetBkThe destination Connection ID of the packetAiDestination Connection ID00000CgEncrypt the packet payload with the given packet numberBcEncrypt the given packet\xe2\x80\x99s header10Abiroh NAT TraversalCbCheck if this stream has been opened during 0-RTT.0CmRetrieve implementation-specific metrics used to populate \xe2\x80\xa60CnThe maximum UDP payload size guaranteed to be supported by \xe2\x80\xa60BbOne or more packets were just sent0BmInitiate a new outgoing bidirectional stream.CaReturns the path ID of the new path being opened.AdSource Connection ID0000CiCompletes when the peer stops the stream or reads the \xe2\x80\xa6CjCheck if this stream was stopped, get the reason if it wasCcThe total number of streams which should be createdAlProvide control over streamsCeThe length of the AEAD tag appended to packets on \xe2\x80\xa60CdUpgrade the handle to a full ConnectionAkSet the QUIC version to use0lQUIC versionB`The version that was unsupported11CeFuture produced by Connection::accept_biAfAn unreliable datagramBdDatagram support is disabled locally0A`A QUIC endpoint.BcThe main entry point to the libraryChA finished stream has been fully acknowledged or stoppedCkAn incoming connection for which the server has not yet \xe2\x80\xa60BoLong packet types with uniform header structureB`The largest encoded value length0Cmthe connection is being closed abruptly in the absence of \xe2\x80\xa60CeFuture returned by Connection::on_closedClFuture produced by crate::Connection::open_pathCmA currently open stream likely has data or errors waiting \xe2\x80\xa6CkMetadata for a single buffer filled with bytes received \xe2\x80\xa6BkResponse generated directly by the endpointCfIdentifier for a stream within a particular connection0CnCommunication with the peer has lapsed for longer than the \xe2\x80\xa60ChResponsible for limiting clients\xe2\x80\x99 ability to reuse \xe2\x80\xa60ClThe datagram is larger than the connection can currently \xe2\x80\xa60AbAn outgoing packet00CmStatistics about UDP datagrams transmitted or received on \xe2\x80\xa60CnA formerly write-blocked stream might be ready for a write \xe2\x80\xa6AkCongestion algorithm to useAhContents of the datagramBoMark the read data as consumed from the stream.C`Statistics about frames received on a connection0CcStatistics about frames transmitted on a connection0DhConstructs cid by reading len bytes from a Buf0DkCreates a new qlog factory that writes files into QLOGDIR, \xe2\x80\xa60BfCreate a generator with a specific keyBjConstruct a VarInt infallibly0BeSucceeds iff x < 2^620AeWhat type we receivedAoWhat handshake type we received10CbWhether 0-RTT is/was possible during the handshakeCmSpecifies the time to wait after completing MTU discovery \xe2\x80\xa60CcReturns Self for use in down-casting to extract \xe2\x80\xa60EhReturns true if the Connection associated with this handle \xe2\x80\xa6CmDuration after an address validation token was issued for \xe2\x80\xa60CeThe local IP address which was used when the peer \xe2\x80\xa6000AmThe local side of this tuple.ClCompute the maximum size of datagrams that may be passed \xe2\x80\xa6BnInitiate a new outgoing unidirectional stream.BcGet the priority of the send streamAlGet the priority of a streamCfThe negotiated application protocol, if ALPN is in use0Aeqlog output directoryBbOptional response to transmit backCiOptional seed to be used internally for random number \xe2\x80\xa60AlSlow start threshold (bytes)0BeSucceeds iff x < 2^6200000DaSends a Transmit on the given socket without any \xe2\x80\xa6DkQuickly determine whether cid could have been generated by \xe2\x80\xa600BoAll remaining state for a path has been removedCfFuture produced by Connection::accept_uniCdPaths marked with as available will be used when \xe2\x80\xa6CnAt least one new stream of a certain directionality may be \xe2\x80\xa6ClConfiguration for the Bbr congestion controller0BkThe connection was successfully establishedAoAPI to control datagram trafficAlDecoding of QUIC primitives.BgInfallible encoding of QUIC primitives.CnIdentifies a network path by the combination of remote and \xe2\x80\xa6AaA QUIC frame type0A`Handshake packetBcKeys used to protect packet headers0CiCatch-all error for problems while decoding transport \xe2\x80\xa6CeNat traversal attempt failed due to a multipath errorBdKeys used to protect packet payloads0BmErrors that might trigger a path being closedAnApplication events about pathsBiStatistics related to a transmission path0AeA read error occurredBmErrors that arise from reading from a stream.C`Errors triggered when reading from a recv streamCiAn object for asynchronously writing to an associated \xe2\x80\xa6BmAccept the next incoming bidirectional streamBbDuplicate the controller\xe2\x80\x99s state0BdThe amount of UDP datagrams observedAaControl datagrams1BeCreate new object from the given bits00BoWhich side of a connection initiated the stream0CmConvert into a 0-RTT or 0.5-RTT connection at the cost of \xe2\x80\xa6BoShorthand for self == Side::Client0B`Whether the connection is closedBoShorthand for self == Side::Server0CbWhether it is legal to respond with a retry packet0CdWhether to allow clients to migrate to new addresses0CdConstruct a timer that will expire at iCjWait for the connection to be closed without keeping a \xe2\x80\xa6CjOpens an additional path if the multipath extension is \xe2\x80\xa6A`Opens a new pathBmPing the remote endpoint over a specific pathCiAttempts to read from the stream into the provided bufferCeReceive UDP datagrams, or register to be woken if \xe2\x80\xa6CkSend a UDP datagram, or register to be woken if sending \xe2\x80\xa6ClPrivate key used to send authenticated connection resets \xe2\x80\xa60BmGenerate the integrity tag for a retry packet0BgA stable identifier for this connectionCePrivate key used to authenticate data included in \xe2\x80\xa60BlThe position of a token in the packet bufferCgTransport configuration to use for incoming connections0CjWait for all connections on the endpoint to be cleanly \xe2\x80\xa6BoWrite a buffer into this stream in its entiretyCiAbstract implementation of an async timer for runtime \xe2\x80\xa6BoNumber of UDP packets to send/receive at a timeCkError indicating that a path has not been opened or has \xe2\x80\xa6BnThe path is already closed or was never opened1BeIn-progress connection attempt futureAbA QUIC connection.CeProtocol state and logic for a single QUIC connectionCeCommon interface for different congestion controllers0CkNumber of frames transmitted or received of each frame type0BoThe connection ID was not recognized by the \xe2\x80\xa6AnThe QUIC-MULTIPATH path statusBeConfiguration for qlog trace logging.0BnA stream that can only be used to receive dataAaAccess to streamsChErrors that arise while waiting for a stream to be resetDhError for attempting to retry an Incoming which already \xe2\x80\xa60BkA stream that can only be used to send data3BmObject to get current SystemTime0AdA rustls TLS session0CkResponsible for storing validation tokens received from \xe2\x80\xa60AeA borrowed UDP socketBjErrors that arise from writing to a streamBoErrors triggered while writing to a send streamBoAccept the next incoming uni-directional streamCkWhether the implementation is permitted to set the spin \xe2\x80\xa60BmCloses a path by sending a PATH_ABANDON frameCdLogic for controlling the rate at which data is sent0BfWhether to print connection statisticsBnClass of error as encoded in the specificationB`Application-specific reason code10BgError code supplied by the peer See \xe2\x80\xa6AoError code supplied by the peerBcType of frame that caused the close0AiExtract the integer value0BfQUIC transport protocol implementationCnWhether there is no longer any need to keep the connection \xe2\x80\xa6DkDetermine whether this is the last event a Connection will \xe2\x80\xa6CiLook up the local IP address and port used by this socketDgGet the local SocketAddr the underlying socket is bound toBeThe amount of bytes lost on this path0CjPad UDP datagrams carrying application data to current \xe2\x80\xa60AgReturns path statistics0CjThe final path stats, they are no longer available via \xe2\x80\xa6C`Attempt to write bytes from buf into the stream.AmRead the next segment of dataAoReads the next segment of data.CkRead an exact number of bytes contiguously from the stream.BnSets the PathStatus of this path.BoEpoch qlog event times are recorded relative to0ClError type for attempting to accept an IncomingBjErrors in the configuration of an endpoint0AeGeneric crypto errors0CnConfiguration for the Cubic congestion controller0CdReasons why attempting to finish a stream might failCnMaximum duration of inactivity to accept before timing out \xe2\x80\xa60AnValue exceeds supported bounds0D`Constructs a QlogConfig for individual connections.0AhA Quinn runtime for smolB`Application events about streamsCbAccept this incoming connection using a custom \xe2\x80\xa6CdLargest UDP payload size the path currently supportsClStorage size required for the largest packet that can be \xe2\x80\xa61BiDescription to record in the qlog capture0BjThe socket this datagram should be sent to00BkStarting guess for maximum UDP payload sizeCkThe initial value to be used as the maximum UDP payload \xe2\x80\xa60ChUDP payload size that the network must be capable of \xe2\x80\xa6BjThe RTT used before an RTT sample is taken0BfThe initial round-trip-time (in msecs)CeThe amount of concurrent streams which should be usedDdPackets are acked in batches, all with the same now \xe2\x80\xa60AdPacing rate (bits/s)0DiA broadcast receiver of PathEvents for all paths in this \xe2\x80\xa6DfGets the local PathStatus for a known PathIdAnRead the next segments of dataCkConvenience method to read all remaining data into a bufferAlProvide control over streamsBoThe sample size used for this key\xe2\x80\x99s algorithm01CiMaximum number of bytes to transmit to a peer without \xe2\x80\xa600BoThe server name specified by the client, if any0BmObject to get current SystemTime0BdSet a custom TokenStore0CaNumber of bytes to transmit from client to serverCnSpecifies the upper bound to the max UDP payload size that \xe2\x80\xa60ChReturns a weak reference to the inner connection struct.DgCreate a server config with the given crypto::ServerConfig0CeSets a prefix to the filename of the generated files.0DbWrite a single Bytes into this stream in its entiretyBbAn ADD_ADDRESS frame was received.BfConfiguration for outgoing connectionsCaClient-side configuration for the crypto protocol10CgThe stream has already been stopped, finished, or resetBmThe stream has already been finished or resetCmError indicating that a stream has not been opened or has \xe2\x80\xa6CjThe stream has not been opened or was already stopped, \xe2\x80\xa6CfThe stream has not been opened or has already been \xe2\x80\xa6CmThe stream has not been opened or was already finished or \xe2\x80\xa63CgErrors in the parameters being used to create a new \xe2\x80\xa60BkProtocol-level identifier for a connection.0CkWe couldn\xe2\x80\x99t decrypt a message. This is invariably fatal.0BjExplicit congestion notification codepoint00CnWe couldn\xe2\x80\x99t encrypt a message because it was larger than \xe2\x80\xa60BhParameters that are semantically invalidCaThis is the last path, which can not be abandonedAmIroh\xe2\x80\x99s nat traversal eventsDhNull implementation of TokenLog, which never accepts tokens0ClReceived an observation of our external address from the \xe2\x80\xa6CiFuture produced by Connection::read_datagramBiThe remote changed the status of the pathBlRTT estimation for a particular network pathCnFuture produced by Connection::send_datagram_waitBiParameters governing incoming connectionsCaServer-side configuration for the crypto protocol10CmErrors that arise while monitoring for a send stream stop \xe2\x80\xa6AiA Quinn runtime for TokioC`Returns the lifetime of generated Connection IDs0BlIf the connection is closed, the reason why.CjConnect to a remote endpoint using a custom configuration.AlConservative estimate of RTTBnGet the 0-RTT keys if available (clients only)0AgWhich types we expectedB`Which handshake type we expected10AcGenerates a new CID0ClThe number of segments to read when GRO is enabled. Used \xe2\x80\xa6DeProcess ConnectionEvents generated by the associated \xe2\x80\xa6EaProcess EndpointEvents emitted from related ConnectionsCgCreate the initial set of keys given the client\xe2\x80\x99s \xe2\x80\xa6000BgThe amount of packets lost on this path0DcMaximum number of Incoming to allow to exist at a time0CjWhether datagrams might get fragmented into multiple parts0CmWhether transmitted datagrams might get fragmented by the \xe2\x80\xa6CkReturns the path\xe2\x80\x99s network path represented as a 4-tuple.CkThe original destination CID when initiating the connectionCiThe original destination connection ID sent by the clientDhReturns the next time at which handle_timeout should be \xe2\x80\xa6D`Configures qlog capturing by setting a QlogFactory.0CkThe segment size if this transmission contains multiple \xe2\x80\xa600ChThe number of streams that may have unacknowledged data.BgThe amount of packets sent on this path0CbSet the lifetime of CIDs created by this generator0BcSet the priority of the send streamAlSet the priority of a streamCnInitialize a QUIC-compatible TLS client configuration with \xe2\x80\xa6000DgWrite a slice of Bytes into this stream, returning how \xe2\x80\xa6AmSend data on the given streamCkWe received a fatal alert. This means the peer is unhappy.0BhBloom filter-based TokenLog0CmThe connection could not be created because not enough of \xe2\x80\xa6000CaEvent resulting from processing a single datagramBlEvents sent from a Connection to an EndpointAoStatistics on Endpoint activityBnThe stream finished before all bytes were readBlAuthentication data for (rustls) TLS session0Ccreceived an invalid Retry Token in a client Initial0AlThe packet header is invalidBkThe local application closed the connectionAgPath was closed locally1DaThe datagram may result in starting a new ConnectionD`Configuration for the NewReno congestion controller0BjDecodes a QUIC packet\xe2\x80\x99s invariant headerCgErrors triggered when opening a recv stream for readingCaDefault implementation of TimeSource0CgError indicating that the provided buffer was too smallChFor clients, if the peer accepted the 0-RTT data packetsAbAck Frequency modeAfExports for benchmarksBoSupply a custom connection ID generator factory0DgCreate a UdpSender that can register a single task for \xe2\x80\xa6CaNumber of bytes to transmit from server to clientAmGet the Incoming0CnThe max_ack_delay we will request the peer to use0CgDisable packet encryption/decryption (for debugging \xe2\x80\xa6CkThe known MTU for the current network path has been updated0BbCryptographic identity of the peerBgGet the peer\xe2\x80\x99s identity, if availableDhFor the rustls TlsSession, the Any type is \xe2\x80\xa610CnAttempts to read from the stream into the provided buffer, \xe2\x80\xa6AkReturns packets to transmitDjConfigures qlog capturing through the QLOGDIR environment \xe2\x80\xa60AoReceive an application datagramDfTransmit data as an unreliable, unordered application \xe2\x80\xa6CmWhether to implement fair queuing for send streams having \xe2\x80\xa60BfLength of sign\xe2\x80\x99s output0BnStart a client session with this configurationBnStart a server session with this configuration10BdA REMOVE_ADDRESS frame was received.CgAbstract implementation of a UDP socket for runtime \xe2\x80\xa6BgErrors triggered when abandoning a pathAgThe connection was lost00000ChGlobal configuration for the endpoint, affecting all \xe2\x80\xa60Cithe endpoint encountered an internal error and cannot \xe2\x80\xa60FbBasic adapter to let Incoming be await-ed like a ConnectingCeThe peer sent us a TLS message with invalid contents.0Amno viable network path exists0DhNull implementation of TokenStore, which does not store \xe2\x80\xa60CiThe peer deviated from the standard TLS protocol. The \xe2\x80\xa60BmErrors that arise from reading from a stream.C`Errors from RecvStream::read_to_endCaIndicates whether a frame needs to be transmittedCmThe peer violated the QUIC specification as understood by \xe2\x80\xa60CiTransport-level errors occur when a peer violates the \xe2\x80\xa6C`Tokio-compatible UDP socket with some useful \xe2\x80\xa6AfDerive AEAD using hkdf0BnCreate a client endpoint and client connectionAgGet a session referenceDiReturns a QlogConfig for a connection, if logging should \xe2\x80\xa60AiProcess timer expirationsBjParameters negotiated during the handshake0CfGet data negotiated during the handshake, if available0AiInitial congestion windowCiDefault limit on the amount of outstanding data in bytes.001000BnConverts this stream into an unordered stream.CjUniform interface to send and receive UDP packets with \xe2\x80\xa6DdReturns true until the connection is fully established.CeWhether the connection is in the process of being \xe2\x80\xa61BfVerify the integrity of a retry packet0CnSpecifies the minimum MTU change to stop the MTU discovery \xe2\x80\xa60BdCompute keys for the next key update0BkConfigures qlog capturing into a directory.0AlRead bytes of handshake data0BeWhether to use the unordered read APIClMaximum number of bytes the peer may transmit across all \xe2\x80\xa600CkCompletes when the stream has been reset by the peer or \xe2\x80\xa60CiCheck whether this stream has been reset by the peer, \xe2\x80\xa6AjThe peer\xe2\x80\x99s UDP addressesAhThe peer\xe2\x80\x99s UDP address0BgThe peer\xe2\x80\x99s UDP address for this path.1CeSaturating integer addition. Computes self + rhs, \xe2\x80\xa6000ChSaturating integer subtraction. Computes self - rhs, \xe2\x80\xa60CkMaximum reordering in time space before time based loss \xe2\x80\xa60ChReason given by the transport for closing the connection0BfReasons why a connection might be lost0CiThe datagram is redirected to its ConnectionBlEvents sent from an Endpoint to a ConnectionAeConnection statistics0BiStatistics for the currently open streamsAcPlain packet headerBkEnables writing qlog traces to a directory.0CfError for when a validation token may have been reused0C`Parameters governing the core QUIC state machine0CbThe peer doesn\xe2\x80\x99t implement any supported version0CdFuture that completes when a connection is fully \xe2\x80\xa6CbThis was a 0-RTT stream and the server rejected it000CjAutomatically select an appropriate runtime from those \xe2\x80\xa6CkWhether to accept QUIC packets containing any value for \xe2\x80\xa60CdMaximum number of incoming packets that may fail \xe2\x80\xa60CnThe interface index of the interface on which the datagram \xe2\x80\xa6AjSwitch to a new UDP socketCiCreates a server endpoint which runs on the given runtimeD`Sets the PathStatus for a known PathIdCfSee proto::TransportConfig::send_window()BoSee TransportConfig::send_window()BmReturns whether a frame should be transmittedD`Convert t into the socket type used by this runtimeCdWrites handshake bytes into the given buffer and \xe2\x80\xa60CiReason given by an application for closing the connection0CbThe peer\xe2\x80\x99s QUIC stack aborted the connection \xe2\x80\xa60DjInternal identifier for a Connection currently associated \xe2\x80\xa6CdOne or more application datagrams have been receivedCaThe endpoint can no longer create new connections0Cnreceived a STREAM frame or a RESET_STREAM frame containing \xe2\x80\xa60ClSpecific failure cases from keys_match or a \xe2\x80\xa60A`key update error0CaCurrent limits do not allow us to open more pathsClThe peer doesn\xe2\x80\x99t support a protocol version/feature we \xe2\x80\xa60BjA QUIC-compatible TLS client configuration0BjA QUIC-compatible TLS server configuration0EfTokenStore implementation that stores up to N tokens per \xe2\x80\xa60CgAn endpoint (local or remote) tried to add too many \xe2\x80\xa6CaPath could not be validated and will be abandonedBcA Version Negotiation packet headerCiRecord that the token was used and, ideally, return a \xe2\x80\xa60CjCurrent state of the congestion control algorithm, for \xe2\x80\xa6CcCurrent state of this connection\xe2\x80\x99s congestion \xe2\x80\xa6BaUpdate traffic keys spontaneously0BoLow-level protocol logic for the QUIC protoocolCnThe maximum amount of segments which can be transmitted if \xe2\x80\xa6CnMaximum duration of inactivity to accept before timing out \xe2\x80\xa60CeGet the number of connections that are currently openBmNumber of connections that are currently openCiOpens a new path if no path exists yet for the remote \xe2\x80\xa6CmOpens a new path only if no path on the same network path \xe2\x80\xa6CiMaximum reordering in packet number space before FACK \xe2\x80\xa60CfGet the size of the socket receive bufferAlReceive buffer size in bytesCcGet the size of the socket send bufferAiSend buffer size in bytesBiSet a custom TransportConfig000ChConfiguration for sending and handling validation tokens0CnCreate a server config with the given certificate chain to \xe2\x80\xa60DdWrite a slice of Bytes into this stream in its entiretyCfthe application or application protocol caused the \xe2\x80\xa60AnThe peer closed the connection0B`Constructs controllers on demand0BdCommon congestion controller metrics0AlA pseudo random key for HKDF0BcThe given server name was malformed0AcPacket decode errorBmErrors that can arise when sending a datagram0CcThe peer does not support receiving datagram frames0BcCongestion events on the connection0AiCongestion window (bytes)0ClCompute the maximum size of datagrams that may be passed \xe2\x80\xa6BoBytes available in the outgoing datagram bufferClReplace the server configuration, affecting new incoming \xe2\x80\xa60Cmthe endpoint has reached the confidentiality or integrity \xe2\x80\xa60CkParameters for controlling the peer\xe2\x80\x99s acknowledgement \xe2\x80\xa60DjThe max_fragment_size value supplied in configuration was \xe2\x80\xa60Bmthe server refused to accept a new connection0BjParse connection id in short header packetCjOne or more application datagrams have been sent after \xe2\x80\xa6Ckreceived more data than permitted in advertised data limits0AoThe TLS handshake was confirmedBjThe connection\xe2\x80\x99s handshake data is readyCeAttempted an ordered read following an unordered readAnWe saw an invalid certificate.0BcParameters governing MTU discovery.0BnNot enough addresses to complete the operationCkdetected an error with protocol compliance that was not \xe2\x80\xa60Cjreceived a frame for a stream identifier that exceeded \xe2\x80\xa60Cnreceived a frame for a stream that was not in a state that \xe2\x80\xa60AnError from setting path statusAjTransport-level error code0ChThe local endpoint does not support the QUIC version \xe2\x80\xa6CkError indicating that the specified QUIC version is not \xe2\x80\xa61C`Packet uses a QUIC version that is not supported1CiMaximum quantity of out-of-order crypto layer data to \xe2\x80\xa60C`Create a VarInt without ensuring it\xe2\x80\x99s in range0ChCumulative number of Quic handshakes ignored on this \xe2\x80\xa6CiMinimum interval between outgoing stateless reset packets0CjConstruct with an approximate maximum memory usage and \xe2\x80\xa60ChCumulative number of Quic handshakes refused on this \xe2\x80\xa6AnReturns the remote path statusDfTransmit data as an unreliable, unordered application \xe2\x80\xa6CiSee proto::TransportConfig::receive_window()CbSee TransportConfig::receive_window()B`Override supported QUIC versions0CiOverride the instant relative to which all events are \xe2\x80\xa60BkNo remote CIDs available to open a new pathCkTransport parameters used to negotiate connection-level \xe2\x80\xa6CgA stream that can be used to receive data out-of-order.CmThe certificate verifier doesn\xe2\x80\x99t support the given type \xe2\x80\xa60CfThe operation is not allowed for this endpoint\xe2\x80\x99s \xe2\x80\xa6CiCumulative number of Quic handshakes accepted by this \xe2\x80\xa6CjSpecifies the amount of time that MTU discovery should \xe2\x80\xa60CiIf the 0-RTT-encrypted data has been accepted by the peer0BgWait for the handshake to be confirmed.CgPeriod of inactivity before sending a keep-alive packet0CiThe amount of PLPMTUD probe packets lost on this path \xe2\x80\xa60BlPackets were deemed lost or marked congested0CgCumulative number of Quic handshakes sent from this \xe2\x80\xa6CnThe number of remotely initiated open streams of a certain \xe2\x80\xa6AhBench fns for SendBufferCiThe amount of PLPMTUD probe packets sent on this path \xe2\x80\xa60Bireceived a frame that was badly formatted0CkThis function doesn\xe2\x80\x99t work until the TLS handshake is \xe2\x80\xa60CkWe received a TLS message that isn\xe2\x80\x99t valid right now. \xe2\x80\xa60CiThe remote SocketAddr supplied was malformedCkThe remote address for the path is not supported by the \xe2\x80\xa61ChThe initial cipher suite (AES-128-GCM-SHA256) is not \xe2\x80\xa60BdPaths can only be opened client-sideDmError returned when constructing a VarInt from a value >= \xe2\x80\xa60CeA handle to some connection internals, use with care.DkSpecifies the ACK frequency config (see AckFrequencyConfig \xe2\x80\xa60CiThe number of times a black hole was detected in the path0CgMaximum number of received bytes to buffer for each \xe2\x80\xa60AeIs multipath enabled?ClMaximum number of datagrams that might be described by a \xe2\x80\xa60CkMaximum UDP payload size accepted from peers (excluding \xe2\x80\xa60AmMax UDP payload size in bytesDkSpecifies the MTU discovery config (see MtuDiscoveryConfig \xe2\x80\xa60AmReturn endpoint-facing eventsCkThe preferred IPv4 address that will be communicated to \xe2\x80\xa60CkThe preferred IPv6 address that will be communicated to \xe2\x80\xa60ChThe reordering threshold we will request the peer to use0ClDuration after a retry token was issued for which it\xe2\x80\x99s \xe2\x80\xa60C`Sets the keep_alive_interval for a specific pathDfResize the receive buffer of socket to bytesDcResize the send buffer of socket to bytesBfThe peer\xe2\x80\x99s QUIC transport parametersBdQUIC connection transport parameters1CaGenerates connection IDs for incoming connections0CdAn incoming connection did not support any known \xe2\x80\xa60BjNo default client configuration was set up0BiPath abandoned due to unstable interfaces0ClConfiguration for sending and handling validation tokens \xe2\x80\xa60CmMaximum number of packets that may be sent using a single \xe2\x80\xa60CiCounter for the number of bytes currently used in the \xe2\x80\xa6CgReturns whether we think the other address probably \xe2\x80\xa6ChHandle a change in the local address, i.e. an active \xe2\x80\xa6CkReduction in congestion window when a new loss event is \xe2\x80\xa60DdMaximum number of datagrams that a Transmit may encode.0DjA broadcast receiver of iroh_hp::Events for updates about \xe2\x80\xa6CjGet the address observed by the remote over the given pathCiMaximum number of bytes the peer may transmit without \xe2\x80\xa600Chreceived more data in CRYPTO frames than can be buffered0B`The extension was not negotiatedCbWe failed to figure out what time it currently is.0CbWe failed to acquire random bytes from the system.0CnError indicating that this operation requires multipath to \xe2\x80\xa6BnThe extension was not negotiated with the peerBnHeader of an Initial packet, before decryptionCgDerive keying material from this connection\xe2\x80\x99s TLS \xe2\x80\xa6EdFill output with output.len() bytes of keying material \xe2\x80\xa60BnPathological case: many segments, get from endCfGet segments in the old way, using a loop of get callsClCurrent number of remotely initiated streams that may be \xe2\x80\xa6ClTrack changed on our external address as reported by the \xe2\x80\xa6ClTrack changes on our external address as reported by the \xe2\x80\xa6CnCreate a client configuration that trusts the platform\xe2\x80\x99s \xe2\x80\xa60CmCreate a client configuration that trusts specified trust \xe2\x80\xa60BkThe peer didn\xe2\x80\x99t give us any certificates.0BkThe peer sent an oversized record/fragment.0CkThe ack-eliciting threshold we will request the peer to use0BiWhether there are any pending retransmitsCdWhether the Multipath for QUIC extension is enabled.C`Sets the keep_alive_interval for a specific pathBoSet a custom ValidationTokenConfig0BmPath abandoned at the application\xe2\x80\x99s request0CjGet the current value of max_udp_payload_size0ChConfigure how to populate the destination CID of the \xe2\x80\xa60CjConstruct an endpoint with arbitrary configuration and \xe2\x80\xa6CfWhether the socket address that is initiating this \xe2\x80\xa60CmModify the number of open paths allowed when multipath is \xe2\x80\xa6Cmthe number of connection IDs provided by the peer exceeds \xe2\x80\xa60CbError returned by Session::export_keying_material.0CiA provided certificate revocation list (CRL) was invalid.0CmPath abandoned due to no available connection IDs for the \xe2\x80\xa60Clreceived transport parameters that were badly formatted, \xe2\x80\xa60CiRegisters one address at which this endpoint might be \xe2\x80\xa6ClAdd addresses the local endpoint considers are reachable \xe2\x80\xa6ClMaximum number of outgoing application datagram bytes to \xe2\x80\xa60CiSet the client configuration used by connectBmSets the max_idle_timeout for a specific pathBfThe QUIC protocol version implemented.BoBytes available in the outgoing datagram bufferDhMaximum number of received bytes to buffer for all Incoming0DaVariant of max_concurrent_bidi_streams affecting \xe2\x80\xa60ClModify the number of remotely initiated streams that may \xe2\x80\xa6CnCreate a client configuration that trusts the platform\xe2\x80\x99s \xe2\x80\xa60CkGenerates 8-byte connection IDs that can be efficiently \xe2\x80\xa6CkAn error occurred while handling Encrypted Client Hello \xe2\x80\xa60CkPath abandoned due to resource limitations in the transport0CiGenerates purely random connection IDs of a specified \xe2\x80\xa6ChWhether to use \xe2\x80\x9cGeneric Segmentation Offload\xe2\x80\x9d to \xe2\x80\xa60CmMaximum number of incoming bidirectional streams that may \xe2\x80\xa60BhUpdates this tuple\xe2\x80\x99s local address iffClMaximum number of incoming application datagram bytes to \xe2\x80\xa60BcInitiates a new nat traversal round0BdPackets were incorrectly deemed lost0CnRemoves one or more addresses from the set of addresses at \xe2\x80\xa6CgRemoves an address the endpoing no longer considers \xe2\x80\xa6C`Sets the keep_alive_interval for a specific pathDeA ConnectionIdParser implementation that assumes the \xe2\x80\xa6CjWe received a TLS handshake message that isn\xe2\x80\x99t valid \xe2\x80\xa60CiHow to construct new congestion::Controllers0BlSets a default per-path maximum idle timeout0BoThe key exchange group negotiated with the peer0CbWhether to send observed address reports to peers.0CiModify the number of remotely initiated bidirectional \xe2\x80\xa6BiEnables the Multipath Extension for QUIC.0CjModify the number of remotely initiated unidirectional \xe2\x80\xa6CeNumber of consecutive PTOs after which network is \xe2\x80\xa60BkSets a default per-path keep alive interval0CjWhether to receive observed address reports from other \xe2\x80\xa60BmGet the current local nat traversal addresses0CkGet the currently advertised nat traversal addresses by \xe2\x80\xa60AcNat traversal draftCkSets the maximum number of nat traversal addresses this \xe2\x80\xa60CjWhen multipath is required and has not been explicitly \xe2\x80\xa6") \ No newline at end of file diff --git a/pr/255/docs/search.index/desc/ee2830ff879e.js b/pr/255/docs/search.index/desc/ee2830ff879e.js new file mode 100644 index 000000000..06a657920 --- /dev/null +++ b/pr/255/docs/search.index/desc/ee2830ff879e.js @@ -0,0 +1 @@ +rd_("AmData flows in both directions0CdThe CE codepoint, signalling that congestion was \xe2\x80\xa600AjContains the success valueBeThe PathId of this path.AoGet the identity of this stream00AfWhich path is now openAjWhich path has been closedB`Which path had its state droppedBaPath for which the error occurredAmPath which has changed statusCfPath over which the observed address was reported, \xe2\x80\xa6AlWhich stream is now readableAlWhich stream is now writableAnWhich stream has been finishedAmWhich stream has been stoppedAnType of the Long header packetBcExperimental! Use at your own risk.0ClWhether a stream communicates data in both directions or \xe2\x80\xa60AhContains the error valueAoThe largest representable valueAlThe maximum path ID allowed.10ClConnects to a QUIC perf server and maintains a specified \xe2\x80\xa6BmData flows only from the stream\xe2\x80\x99s initiator0AnWhich directions data flows in0CaDirectionality for which streams have been openedCdDirectionality for which streams are newly availableCjExplicit congestion notification bits to set on the packet0CeThe Explicit Congestion Notification bits for the \xe2\x80\xa61B`The current best RTT estimation.BeThe amount of I/O operations executed0BcLength of QUIC packet being decodedAlLength of the packet payload0BmThe number of bytes the associated buffer hasBbSet a custom TokenLog0CaMinimum RTT registered so far for this estimator.ClConstruct with an approximate maximum memory usage and a \xe2\x80\xa6CjConstruct an endpoint with arbitrary configuration and \xe2\x80\xa6DiCreates a new QlogConfig that writes a qlog trace to the \xe2\x80\xa6CiCreates a new qlog factory that writes files into the \xe2\x80\xa6D`Create a default config with a particular reset_keyCmCreate a default config with a particular handshake token \xe2\x80\xa6CkCreate a default config with a particular cryptographic \xe2\x80\xa6AmConstruct cid from byte arrayoConstruct emptyAeCreate a new StreamIdDjConstruct a state using the given config and current time \xe2\x80\xa600:8AeCreate a new endpointDcCreate a new instance of FixedLengthConnectionIdParserBdCreate a generator with a random key:987DgBegin decoding a QUIC packet from bytes, returning any \xe2\x80\xa67BkConstruct an error with a code and a reasonCgInitialize Random CID generator with a fixed CID length87666CkGet SystemTime::now() or the mocked equivalentAhLook up the current time01ChCurrent best estimate of this connection\xe2\x80\x99s latency \xe2\x80\xa6000ChThe ECT(0) codepoint, indicating that an endpoint is \xe2\x80\xa600ChThe ECT(1) codepoint, indicating that an endpoint is \xe2\x80\xa600CaA complete set of keys for a certain packet space0CbA Long packet header, as used during the handshakeAcAn open (Multi)PathAb(Multi)Path eventsB`An error occurred during readingCeWhether an endpoint was the initiator of a connection0nThe 0 path id.0CaThe address observed by the remote over this pathCjThe source address of the datagram(s) contained in the \xe2\x80\xa6mType of errorBkCurrent congestion window of the connection0gPayloadAoReturns the argument unchanged.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000BaCalls U::from(self).000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000dNextCeMethod for opening a sealed message dataB`Open a single stream if possible1CgReturns the Path structure of an open pathBhPing the remote endpoint over this path.AhPing the remote endpointCkCheck whether the timer has expired, and register to be \xe2\x80\xa6BaReturns application-facing eventsBgRead data contiguously from the stream.AoRead from the given recv streamCcDecode TransportParameters from bufferBiReceive an unreliable, unordered datagramBlMethod for sealing message data0CiQueue an unreliable, unordered datagram for immediate \xe2\x80\xa6CbSends a Transmit on the given socket.CmNumber of address validation tokens sent to a client when \xe2\x80\xa60BmThe side of the connection (client or server)ChLook up whether we\xe2\x80\x99re the client or server of this \xe2\x80\xa6AlMethod for signing a message0CdAmount of data written to the caller-supplied buffer0hSpin bitAcStop accepting data0BoStop accepting data on the given receive streamCiTry to find and take a token that was stored with the \xe2\x80\xa60BgA chunk of data from the receive stream0CiThe RFC8312 congestion controller, as widely used for TCP0Borustls reports protocol errors using this type.0DbErrors encountered while decoding TransportParametersCdErrors that the nat traversal state might encounter.BeEvents of interest to the applicationCiEvent emitted when the client receives ADD_ADDRESS or \xe2\x80\xa6A`Any other error.0CcThe peer abandoned transmitting data on this streamCnThe peer is unable to continue processing this connection, \xe2\x80\xa6CdThe peer abandoned transmitting data on this stream.1AeA Retry packet headerCdA short packet header, as used during the data phaseBiConstruct a fresh Controller0AiThe contents of the chunkCiThe total amount of bytes which have been transferred \xe2\x80\xa6BjThe amount of bytes which had been written210BnUnderlying error describing reason for failureBaClose the connection immediately.CnClose all of this endpoint\xe2\x80\x99s connections immediately and \xe2\x80\xa6A`Closes this pathAnClose a connection immediatelyAgThe error that occurredBcFrame type that triggered the errorCcDistinguishes streams of the same initiator and \xe2\x80\xa60CjReturns whether the codepoint is a CE, signalling that \xe2\x80\xa60AgKey for encrypting data0BgParse a connection id from given bufferAhReturns all known paths.BlUpdate the timer to expire at iBbClose the send stream immediately.BeAbandon transmitting data on a streamCnRespond with a retry packet, requiring the client to retry \xe2\x80\xa60CiDrive future to completion in the backgroundCeShow connection stats the at the end of the benchmarkAmReturns connection statisticsBiReturns relevant stats from this Endpoint1BcTitle to record in the qlog capture0CmWrite a buffer into this stream, returning how many bytes \xe2\x80\xa6AmSend data on the given streamCcEncode TransportParameters into bufferC`Future produced by Endpoint::acceptClPaths marked as backup will only be used if there are no \xe2\x80\xa6CeChunks returned from RecvStream::read().AmThe initiator of a connection0AdRun as a perf clientAfA path has been closedCgAttempted to initiate NAT traversal on a closed, or \xe2\x80\xa6CcFuture produced by Connection::open_biAjA new path has been openedChOne or more new streams has been opened and might be \xe2\x80\xa6ChId representing different paths when using multipath \xe2\x80\xa60AbCoding result typeAlThe acceptor of a connection0AdRun as a perf servermStream eventsAiAn integer less than 2^620CfGet the next incoming connection attempt from a clientClAttempt to accept this incoming connection (an error may \xe2\x80\xa6CcAccept a remotely initiated stream of a certain \xe2\x80\xa61C`The amount of full chunks which had been written0BlAllows to configure the desired cipher suiteCiHelper to construct an endpoint for use with outgoing \xe2\x80\xa6CcWait for the connection to be closed for any reasonAfCoding related traits.BnAccess the configuration used by this endpointChTraits and implementations for the QUIC cryptography \xe2\x80\xa6BjCreate QUIC error code from TLS alert codeBoTLS configuration used for incoming connections210BkAn underlying crypto (e.g. TLS) layer errorCgDecode a plain header from given buffer, with given \xe2\x80\xa6DiDecode a Self from the provided buffer, if the buffer is \xe2\x80\xa6ChThe destination IP address which was encoded in this \xe2\x80\xa6D`Append the encoding of self to the provided buffer.CmNotify the peer that no more data will ever be written to \xe2\x80\xa6CnFinish a send stream, signalling that no more data will be \xe2\x80\xa6B`Process an incoming UDP datagramAfHeader protection keys0ClIgnore this incoming connection attempt, not sending any \xe2\x80\xa60C`Potentially store a token for later one-time use0CfPerform NSS-compatible TLS key logging to the file \xe2\x80\xa6AhThe offset in the stream0B`Packet deliveries were confirmed0AfPacket protection keys0lRandom valueBcHuman-readable reason for the close000BhHuman-readable explanation of the reasonBeReason that the connection was closedAjSwitch to a new UDP socketBgReject this incoming connection attempt0AgKey for decrypting dataAmThe remote side of this tuple1AmTLS interface based on rustls0CnHelper to construct an endpoint for use with both incoming \xe2\x80\xa6BkOptional source IP address for the datagram00CgThe current local PathStatus of this path.B`The new status set by the remoteCfThe size of a single datagram in the associated bufferCgStatistics about UDP datagrams received on a connection0CjStatistics about UDP datagrams transmitted on a connection0AnMethod for verifying a message0CcNumber of ack-eliciting bytes that may be in flight0CaA key for sealing data with AEAD-based algorithms0A`Send would blockCcNo more data is currently available on this stream.CjThe peer is not able to accept additional data, or the \xe2\x80\xa6BfA catch-all error for unlikely errors.0BlA key for signing with HMAC-based algorithms0AhAn Initial packet headerBnA pair of keys for bidirectional communication0BhA simple, standard congestion controller0CdFuture produced by Connection::open_uniCkAbstracts I/O and timer operations for runtime independenceBfA cryptographic session (commonly TLS)0CcThe peer is no longer accepting data on this streamClThe peer is no longer accepting data on this stream, and \xe2\x80\xa6CkThe peer is no longer accepting data on this stream. No \xe2\x80\xa6CgThe peer asked us to stop sending on an outgoing streamAaAccess to streamsCaThe stream is larger than the user-supplied limitClIndicates how many bytes and chunks had been transferred \xe2\x80\xa60l0-RTT packetCjReturns the length of a CID for connections created by \xe2\x80\xa60CdProvide the length of dst_cid in short header packetCcThe total number of clients which should be createdAlConnect to a remote endpointAeInitiate a connectionCgDecrypt the packet payload with the given packet numberBcDecrypt the given packet\xe2\x80\x99s header10ClConstructs a value with arbitrary fields, intended to be \xe2\x80\xa6DjConstruct an event that indicating that a Connection will \xe2\x80\xa6BkThe destination connection ID of the packetBkThe destination Connection ID of the packetAiDestination Connection ID00000CgEncrypt the packet payload with the given packet numberBcEncrypt the given packet\xe2\x80\x99s header10Abiroh NAT TraversalCbCheck if this stream has been opened during 0-RTT.0CmRetrieve implementation-specific metrics used to populate \xe2\x80\xa60CnThe maximum UDP payload size guaranteed to be supported by \xe2\x80\xa60BbOne or more packets were just sent0BmInitiate a new outgoing bidirectional stream.CaReturns the path ID of the new path being opened.AdSource Connection ID0000CiCompletes when the peer stops the stream or reads the \xe2\x80\xa6CjCheck if this stream was stopped, get the reason if it wasCcThe total number of streams which should be createdAlProvide control over streamsCeThe length of the AEAD tag appended to packets on \xe2\x80\xa60CdUpgrade the handle to a full ConnectionAkSet the QUIC version to use0lQUIC versionB`The version that was unsupported11CeFuture produced by Connection::accept_biAfAn unreliable datagramBdDatagram support is disabled locally0A`A QUIC endpoint.BcThe main entry point to the libraryChA finished stream has been fully acknowledged or stoppedCkAn incoming connection for which the server has not yet \xe2\x80\xa60BoLong packet types with uniform header structureB`The largest encoded value length0Cmthe connection is being closed abruptly in the absence of \xe2\x80\xa60CeFuture returned by Connection::on_closedClFuture produced by crate::Connection::open_pathCmA currently open stream likely has data or errors waiting \xe2\x80\xa6CkMetadata for a single buffer filled with bytes received \xe2\x80\xa6BkResponse generated directly by the endpointCfIdentifier for a stream within a particular connection0CnCommunication with the peer has lapsed for longer than the \xe2\x80\xa60ChResponsible for limiting clients\xe2\x80\x99 ability to reuse \xe2\x80\xa60ClThe datagram is larger than the connection can currently \xe2\x80\xa60AbAn outgoing packet00CmStatistics about UDP datagrams transmitted or received on \xe2\x80\xa60CnA formerly write-blocked stream might be ready for a write \xe2\x80\xa6AkCongestion algorithm to useAhContents of the datagramBoMark the read data as consumed from the stream.C`Statistics about frames received on a connection0CcStatistics about frames transmitted on a connection0DhConstructs cid by reading len bytes from a Buf0DkCreates a new qlog factory that writes files into QLOGDIR, \xe2\x80\xa60BfCreate a generator with a specific keyBjConstruct a VarInt infallibly0BeSucceeds iff x < 2^620AeWhat type we receivedAoWhat handshake type we received10CbWhether 0-RTT is/was possible during the handshakeCmSpecifies the time to wait after completing MTU discovery \xe2\x80\xa60CcReturns Self for use in down-casting to extract \xe2\x80\xa60EhReturns true if the Connection associated with this handle \xe2\x80\xa6CmDuration after an address validation token was issued for \xe2\x80\xa60CeThe local IP address which was used when the peer \xe2\x80\xa6000AmThe local side of this tuple.ClCompute the maximum size of datagrams that may be passed \xe2\x80\xa6BnInitiate a new outgoing unidirectional stream.BcGet the priority of the send streamAlGet the priority of a streamCfThe negotiated application protocol, if ALPN is in use0Aeqlog output directoryBbOptional response to transmit backCiOptional seed to be used internally for random number \xe2\x80\xa60AlSlow start threshold (bytes)0BeSucceeds iff x < 2^6200000DaSends a Transmit on the given socket without any \xe2\x80\xa6DkQuickly determine whether cid could have been generated by \xe2\x80\xa600BoAll remaining state for a path has been removedCfFuture produced by Connection::accept_uniCdPaths marked with as available will be used when \xe2\x80\xa6CnAt least one new stream of a certain directionality may be \xe2\x80\xa6ClConfiguration for the Bbr congestion controller0BkThe connection was successfully establishedAoAPI to control datagram trafficAlDecoding of QUIC primitives.BgInfallible encoding of QUIC primitives.CnIdentifies a network path by the combination of remote and \xe2\x80\xa6A`Handshake packetBcKeys used to protect packet headers0CiCatch-all error for problems while decoding transport \xe2\x80\xa6CeNat traversal attempt failed due to a multipath errorBdKeys used to protect packet payloads0BmErrors that might trigger a path being closedAnApplication events about pathsBiStatistics related to a transmission path0AeA read error occurredBmErrors that arise from reading from a stream.C`Errors triggered when reading from a recv streamCiAn object for asynchronously writing to an associated \xe2\x80\xa6BmAccept the next incoming bidirectional streamBbDuplicate the controller\xe2\x80\x99s state0BdThe amount of UDP datagrams observedAaControl datagrams1BeCreate new object from the given bits00BoWhich side of a connection initiated the stream0CmConvert into a 0-RTT or 0.5-RTT connection at the cost of \xe2\x80\xa6BoShorthand for self == Side::Client0B`Whether the connection is closedBoShorthand for self == Side::Server0CbWhether it is legal to respond with a retry packet0CdWhether to allow clients to migrate to new addresses0CdConstruct a timer that will expire at iCjWait for the connection to be closed without keeping a \xe2\x80\xa6CjOpens an additional path if the multipath extension is \xe2\x80\xa6A`Opens a new pathBmPing the remote endpoint over a specific pathCiAttempts to read from the stream into the provided bufferCeReceive UDP datagrams, or register to be woken if \xe2\x80\xa6CkSend a UDP datagram, or register to be woken if sending \xe2\x80\xa6ClPrivate key used to send authenticated connection resets \xe2\x80\xa60BmGenerate the integrity tag for a retry packet0BgA stable identifier for this connectionCePrivate key used to authenticate data included in \xe2\x80\xa60BlThe position of a token in the packet bufferCgTransport configuration to use for incoming connections0CjWait for all connections on the endpoint to be cleanly \xe2\x80\xa6BoWrite a buffer into this stream in its entiretyCiAbstract implementation of an async timer for runtime \xe2\x80\xa6BoNumber of UDP packets to send/receive at a timeCkError indicating that a path has not been opened or has \xe2\x80\xa6BnThe path is already closed or was never opened1BeIn-progress connection attempt futureAbA QUIC connection.CeProtocol state and logic for a single QUIC connectionCeCommon interface for different congestion controllers0CkNumber of frames transmitted or received of each frame type0BoThe connection ID was not recognized by the \xe2\x80\xa6AnThe QUIC-MULTIPATH path statusBeConfiguration for qlog trace logging.0BnA stream that can only be used to receive dataAaAccess to streamsChErrors that arise while waiting for a stream to be resetDhError for attempting to retry an Incoming which already \xe2\x80\xa60BkA stream that can only be used to send data3BmObject to get current SystemTime0AdA rustls TLS session0CkResponsible for storing validation tokens received from \xe2\x80\xa60AeA borrowed UDP socketBjErrors that arise from writing to a streamBoErrors triggered while writing to a send streamBoAccept the next incoming uni-directional streamCkWhether the implementation is permitted to set the spin \xe2\x80\xa60BmCloses a path by sending a PATH_ABANDON frameCdLogic for controlling the rate at which data is sent0BfWhether to print connection statisticsBnClass of error as encoded in the specificationB`Application-specific reason code10BgError code supplied by the peer See \xe2\x80\xa6AoError code supplied by the peerBcType of frame that caused the close0AiExtract the integer value0BfQUIC transport protocol implementationCnWhether there is no longer any need to keep the connection \xe2\x80\xa6DkDetermine whether this is the last event a Connection will \xe2\x80\xa6CiLook up the local IP address and port used by this socketDgGet the local SocketAddr the underlying socket is bound toBeThe amount of bytes lost on this path0CjPad UDP datagrams carrying application data to current \xe2\x80\xa60AgReturns path statistics0CjThe final path stats, they are no longer available via \xe2\x80\xa6C`Attempt to write bytes from buf into the stream.AmRead the next segment of dataAoReads the next segment of data.CkRead an exact number of bytes contiguously from the stream.BnSets the PathStatus of this path.BoEpoch qlog event times are recorded relative to0ClError type for attempting to accept an IncomingBjErrors in the configuration of an endpoint0AeGeneric crypto errors0CnConfiguration for the Cubic congestion controller0CdReasons why attempting to finish a stream might failCnMaximum duration of inactivity to accept before timing out \xe2\x80\xa60AnValue exceeds supported bounds0D`Constructs a QlogConfig for individual connections.0AhA Quinn runtime for smolB`Application events about streamsCbAccept this incoming connection using a custom \xe2\x80\xa6CdLargest UDP payload size the path currently supportsClStorage size required for the largest packet that can be \xe2\x80\xa61BiDescription to record in the qlog capture0BjThe socket this datagram should be sent to00BkStarting guess for maximum UDP payload sizeCkThe initial value to be used as the maximum UDP payload \xe2\x80\xa60ChUDP payload size that the network must be capable of \xe2\x80\xa6BjThe RTT used before an RTT sample is taken0BfThe initial round-trip-time (in msecs)CeThe amount of concurrent streams which should be usedDdPackets are acked in batches, all with the same now \xe2\x80\xa60AdPacing rate (bits/s)0DiA broadcast receiver of PathEvents for all paths in this \xe2\x80\xa6DfGets the local PathStatus for a known PathIdAnRead the next segments of dataCkConvenience method to read all remaining data into a bufferAlProvide control over streamsBoThe sample size used for this key\xe2\x80\x99s algorithm01CiMaximum number of bytes to transmit to a peer without \xe2\x80\xa600BoThe server name specified by the client, if any0BmObject to get current SystemTime0BdSet a custom TokenStore0CaNumber of bytes to transmit from client to serverCnSpecifies the upper bound to the max UDP payload size that \xe2\x80\xa60ChReturns a weak reference to the inner connection struct.DgCreate a server config with the given crypto::ServerConfig0CeSets a prefix to the filename of the generated files.0DbWrite a single Bytes into this stream in its entiretyBbAn ADD_ADDRESS frame was received.BfConfiguration for outgoing connectionsCaClient-side configuration for the crypto protocol10CgThe stream has already been stopped, finished, or resetBmThe stream has already been finished or resetCmError indicating that a stream has not been opened or has \xe2\x80\xa6CjThe stream has not been opened or was already stopped, \xe2\x80\xa6CfThe stream has not been opened or has already been \xe2\x80\xa6CmThe stream has not been opened or was already finished or \xe2\x80\xa63CgErrors in the parameters being used to create a new \xe2\x80\xa60BkProtocol-level identifier for a connection.0CkWe couldn\xe2\x80\x99t decrypt a message. This is invariably fatal.0BjExplicit congestion notification codepoint00CnWe couldn\xe2\x80\x99t encrypt a message because it was larger than \xe2\x80\xa60BhParameters that are semantically invalidCaThis is the last path, which can not be abandonedAmIroh\xe2\x80\x99s nat traversal eventsDhNull implementation of TokenLog, which never accepts tokens0ClReceived an observation of our external address from the \xe2\x80\xa6CiFuture produced by Connection::read_datagramBiThe remote changed the status of the pathBlRTT estimation for a particular network pathCnFuture produced by Connection::send_datagram_waitBiParameters governing incoming connectionsCaServer-side configuration for the crypto protocol10CmErrors that arise while monitoring for a send stream stop \xe2\x80\xa6AiA Quinn runtime for TokioC`Returns the lifetime of generated Connection IDs0BlIf the connection is closed, the reason why.CjConnect to a remote endpoint using a custom configuration.AlConservative estimate of RTTBnGet the 0-RTT keys if available (clients only)0AgWhich types we expectedB`Which handshake type we expected10AcGenerates a new CID0ClThe number of segments to read when GRO is enabled. Used \xe2\x80\xa6DeProcess ConnectionEvents generated by the associated \xe2\x80\xa6EaProcess EndpointEvents emitted from related ConnectionsCgCreate the initial set of keys given the client\xe2\x80\x99s \xe2\x80\xa6000BgThe amount of packets lost on this path0DcMaximum number of Incoming to allow to exist at a time0CjWhether datagrams might get fragmented into multiple parts0CmWhether transmitted datagrams might get fragmented by the \xe2\x80\xa6CkReturns the path\xe2\x80\x99s network path represented as a 4-tuple.CkThe original destination CID when initiating the connectionCiThe original destination connection ID sent by the clientDhReturns the next time at which handle_timeout should be \xe2\x80\xa6D`Configures qlog capturing by setting a QlogFactory.0CkThe segment size if this transmission contains multiple \xe2\x80\xa600ChThe number of streams that may have unacknowledged data.BgThe amount of packets sent on this path0CbSet the lifetime of CIDs created by this generator0BcSet the priority of the send streamAlSet the priority of a streamCnInitialize a QUIC-compatible TLS client configuration with \xe2\x80\xa6000DgWrite a slice of Bytes into this stream, returning how \xe2\x80\xa6AmSend data on the given streamCkWe received a fatal alert. This means the peer is unhappy.0BhBloom filter-based TokenLog0CmThe connection could not be created because not enough of \xe2\x80\xa6000CaEvent resulting from processing a single datagramBlEvents sent from a Connection to an EndpointAoStatistics on Endpoint activityBnThe stream finished before all bytes were readBlAuthentication data for (rustls) TLS session0Ccreceived an invalid Retry Token in a client Initial0AlThe packet header is invalidBkThe local application closed the connectionAgPath was closed locally1DaThe datagram may result in starting a new ConnectionD`Configuration for the NewReno congestion controller0BjDecodes a QUIC packet\xe2\x80\x99s invariant headerCgErrors triggered when opening a recv stream for readingCaDefault implementation of TimeSource0CgError indicating that the provided buffer was too smallChFor clients, if the peer accepted the 0-RTT data packetsAbAck Frequency modeAfExports for benchmarksBoSupply a custom connection ID generator factory0DgCreate a UdpSender that can register a single task for \xe2\x80\xa6CaNumber of bytes to transmit from server to clientAmGet the Incoming0CnThe max_ack_delay we will request the peer to use0CgDisable packet encryption/decryption (for debugging \xe2\x80\xa6CkThe known MTU for the current network path has been updated0BbCryptographic identity of the peerBgGet the peer\xe2\x80\x99s identity, if availableDhFor the rustls TlsSession, the Any type is \xe2\x80\xa610CnAttempts to read from the stream into the provided buffer, \xe2\x80\xa6AkReturns packets to transmitDjConfigures qlog capturing through the QLOGDIR environment \xe2\x80\xa60AoReceive an application datagramDfTransmit data as an unreliable, unordered application \xe2\x80\xa6CmWhether to implement fair queuing for send streams having \xe2\x80\xa60BfLength of sign\xe2\x80\x99s output0BnStart a client session with this configurationBnStart a server session with this configuration10BdA REMOVE_ADDRESS frame was received.CgAbstract implementation of a UDP socket for runtime \xe2\x80\xa6BgErrors triggered when abandoning a pathAgThe connection was lost00000ChGlobal configuration for the endpoint, affecting all \xe2\x80\xa60Cithe endpoint encountered an internal error and cannot \xe2\x80\xa60FbBasic adapter to let Incoming be await-ed like a ConnectingCeThe peer sent us a TLS message with invalid contents.0Amno viable network path exists0DhNull implementation of TokenStore, which does not store \xe2\x80\xa60CiThe peer deviated from the standard TLS protocol. The \xe2\x80\xa60BmErrors that arise from reading from a stream.C`Errors from RecvStream::read_to_endCaIndicates whether a frame needs to be transmittedCmThe peer violated the QUIC specification as understood by \xe2\x80\xa60CiTransport-level errors occur when a peer violates the \xe2\x80\xa6C`Tokio-compatible UDP socket with some useful \xe2\x80\xa6AfDerive AEAD using hkdf0BnCreate a client endpoint and client connectionAgGet a session referenceDiReturns a QlogConfig for a connection, if logging should \xe2\x80\xa60AiProcess timer expirationsBjParameters negotiated during the handshake0CfGet data negotiated during the handshake, if available0AiInitial congestion windowCiDefault limit on the amount of outstanding data in bytes.001000BnConverts this stream into an unordered stream.CjUniform interface to send and receive UDP packets with \xe2\x80\xa6DdReturns true until the connection is fully established.CeWhether the connection is in the process of being \xe2\x80\xa61BfVerify the integrity of a retry packet0CnSpecifies the minimum MTU change to stop the MTU discovery \xe2\x80\xa60BdCompute keys for the next key update0BkConfigures qlog capturing into a directory.0AlRead bytes of handshake data0BeWhether to use the unordered read APIClMaximum number of bytes the peer may transmit across all \xe2\x80\xa600CkCompletes when the stream has been reset by the peer or \xe2\x80\xa60CiCheck whether this stream has been reset by the peer, \xe2\x80\xa6AjThe peer\xe2\x80\x99s UDP addressesAhThe peer\xe2\x80\x99s UDP address0BgThe peer\xe2\x80\x99s UDP address for this path.1CeSaturating integer addition. Computes self + rhs, \xe2\x80\xa6000ChSaturating integer subtraction. Computes self - rhs, \xe2\x80\xa60CkMaximum reordering in time space before time based loss \xe2\x80\xa60ChReason given by the transport for closing the connection0BfReasons why a connection might be lost0CiThe datagram is redirected to its ConnectionBlEvents sent from an Endpoint to a ConnectionAeConnection statistics0BiStatistics for the currently open streamsAcPlain packet headerBkEnables writing qlog traces to a directory.0CfError for when a validation token may have been reused0C`Parameters governing the core QUIC state machine0CbThe peer doesn\xe2\x80\x99t implement any supported version0CdFuture that completes when a connection is fully \xe2\x80\xa6CbThis was a 0-RTT stream and the server rejected it000CjAutomatically select an appropriate runtime from those \xe2\x80\xa6CkWhether to accept QUIC packets containing any value for \xe2\x80\xa60CdMaximum number of incoming packets that may fail \xe2\x80\xa60CnThe interface index of the interface on which the datagram \xe2\x80\xa6AjSwitch to a new UDP socketCiCreates a server endpoint which runs on the given runtimeD`Sets the PathStatus for a known PathIdCfSee proto::TransportConfig::send_window()BoSee TransportConfig::send_window()BmReturns whether a frame should be transmittedD`Convert t into the socket type used by this runtimeCdWrites handshake bytes into the given buffer and \xe2\x80\xa60CiReason given by an application for closing the connection0CbThe peer\xe2\x80\x99s QUIC stack aborted the connection \xe2\x80\xa60DjInternal identifier for a Connection currently associated \xe2\x80\xa6CdOne or more application datagrams have been receivedCaThe endpoint can no longer create new connections0Cnreceived a STREAM frame or a RESET_STREAM frame containing \xe2\x80\xa60ClSpecific failure cases from keys_match or a \xe2\x80\xa60A`key update error0CaCurrent limits do not allow us to open more pathsClThe peer doesn\xe2\x80\x99t support a protocol version/feature we \xe2\x80\xa60BjA QUIC-compatible TLS client configuration0BjA QUIC-compatible TLS server configuration0EfTokenStore implementation that stores up to N tokens per \xe2\x80\xa60CgAn endpoint (local or remote) tried to add too many \xe2\x80\xa6CaPath could not be validated and will be abandonedBcA Version Negotiation packet headerCiRecord that the token was used and, ideally, return a \xe2\x80\xa60CjCurrent state of the congestion control algorithm, for \xe2\x80\xa6CcCurrent state of this connection\xe2\x80\x99s congestion \xe2\x80\xa6BaUpdate traffic keys spontaneously0BoLow-level protocol logic for the QUIC protoocolCnThe maximum amount of segments which can be transmitted if \xe2\x80\xa6CnMaximum duration of inactivity to accept before timing out \xe2\x80\xa60CeGet the number of connections that are currently openBmNumber of connections that are currently openCiOpens a new path if no path exists yet for the remote \xe2\x80\xa6CmOpens a new path only if no path on the same network path \xe2\x80\xa6CiMaximum reordering in packet number space before FACK \xe2\x80\xa60CfGet the size of the socket receive bufferAlReceive buffer size in bytesCcGet the size of the socket send bufferAiSend buffer size in bytesBiSet a custom TransportConfig000ChConfiguration for sending and handling validation tokens0CnCreate a server config with the given certificate chain to \xe2\x80\xa60DdWrite a slice of Bytes into this stream in its entiretyCfthe application or application protocol caused the \xe2\x80\xa60AnThe peer closed the connection0B`Constructs controllers on demand0BdCommon congestion controller metrics0AlA pseudo random key for HKDF0BcThe given server name was malformed0AcPacket decode errorBmErrors that can arise when sending a datagram0CcThe peer does not support receiving datagram frames0BcCongestion events on the connection0AiCongestion window (bytes)0ClCompute the maximum size of datagrams that may be passed \xe2\x80\xa6BoBytes available in the outgoing datagram bufferClReplace the server configuration, affecting new incoming \xe2\x80\xa60Cmthe endpoint has reached the confidentiality or integrity \xe2\x80\xa60CkParameters for controlling the peer\xe2\x80\x99s acknowledgement \xe2\x80\xa60DjThe max_fragment_size value supplied in configuration was \xe2\x80\xa60Bmthe server refused to accept a new connection0BjParse connection id in short header packetCjOne or more application datagrams have been sent after \xe2\x80\xa6Ckreceived more data than permitted in advertised data limits0AoThe TLS handshake was confirmedBjThe connection\xe2\x80\x99s handshake data is readyCeAttempted an ordered read following an unordered readAnWe saw an invalid certificate.0BcParameters governing MTU discovery.0BnNot enough addresses to complete the operationCkdetected an error with protocol compliance that was not \xe2\x80\xa60Cjreceived a frame for a stream identifier that exceeded \xe2\x80\xa60Cnreceived a frame for a stream that was not in a state that \xe2\x80\xa60AnError from setting path statusAjTransport-level error code0ChThe local endpoint does not support the QUIC version \xe2\x80\xa6CkError indicating that the specified QUIC version is not \xe2\x80\xa61C`Packet uses a QUIC version that is not supported1CiMaximum quantity of out-of-order crypto layer data to \xe2\x80\xa60C`Create a VarInt without ensuring it\xe2\x80\x99s in range0ChCumulative number of Quic handshakes ignored on this \xe2\x80\xa6CiMinimum interval between outgoing stateless reset packets0CjConstruct with an approximate maximum memory usage and \xe2\x80\xa60ChCumulative number of Quic handshakes refused on this \xe2\x80\xa6AnReturns the remote path statusDfTransmit data as an unreliable, unordered application \xe2\x80\xa6CiSee proto::TransportConfig::receive_window()CbSee TransportConfig::receive_window()B`Override supported QUIC versions0CiOverride the instant relative to which all events are \xe2\x80\xa60BkNo remote CIDs available to open a new pathCkTransport parameters used to negotiate connection-level \xe2\x80\xa6CgA stream that can be used to receive data out-of-order.CmThe certificate verifier doesn\xe2\x80\x99t support the given type \xe2\x80\xa60CfThe operation is not allowed for this endpoint\xe2\x80\x99s \xe2\x80\xa6CiCumulative number of Quic handshakes accepted by this \xe2\x80\xa6CjSpecifies the amount of time that MTU discovery should \xe2\x80\xa60CiIf the 0-RTT-encrypted data has been accepted by the peer0BgWait for the handshake to be confirmed.CgPeriod of inactivity before sending a keep-alive packet0CiThe amount of PLPMTUD probe packets lost on this path \xe2\x80\xa60BlPackets were deemed lost or marked congested0CgCumulative number of Quic handshakes sent from this \xe2\x80\xa6CnThe number of remotely initiated open streams of a certain \xe2\x80\xa6AhBench fns for SendBufferCiThe amount of PLPMTUD probe packets sent on this path \xe2\x80\xa60Bireceived a frame that was badly formatted0CkThis function doesn\xe2\x80\x99t work until the TLS handshake is \xe2\x80\xa60CkWe received a TLS message that isn\xe2\x80\x99t valid right now. \xe2\x80\xa60CiThe remote SocketAddr supplied was malformedCkThe remote address for the path is not supported by the \xe2\x80\xa61ChThe initial cipher suite (AES-128-GCM-SHA256) is not \xe2\x80\xa60BdPaths can only be opened client-sideDmError returned when constructing a VarInt from a value >= \xe2\x80\xa60CeA handle to some connection internals, use with care.DkSpecifies the ACK frequency config (see AckFrequencyConfig \xe2\x80\xa60CiThe number of times a black hole was detected in the path0CgMaximum number of received bytes to buffer for each \xe2\x80\xa60AeIs multipath enabled?ClMaximum number of datagrams that might be described by a \xe2\x80\xa60CkMaximum UDP payload size accepted from peers (excluding \xe2\x80\xa60AmMax UDP payload size in bytesDkSpecifies the MTU discovery config (see MtuDiscoveryConfig \xe2\x80\xa60AmReturn endpoint-facing eventsCkThe preferred IPv4 address that will be communicated to \xe2\x80\xa60CkThe preferred IPv6 address that will be communicated to \xe2\x80\xa60ChThe reordering threshold we will request the peer to use0ClDuration after a retry token was issued for which it\xe2\x80\x99s \xe2\x80\xa60C`Sets the keep_alive_interval for a specific pathDfResize the receive buffer of socket to bytesDcResize the send buffer of socket to bytesBfThe peer\xe2\x80\x99s QUIC transport parametersBdQUIC connection transport parameters1CaGenerates connection IDs for incoming connections0CdAn incoming connection did not support any known \xe2\x80\xa60BjNo default client configuration was set up0BiPath abandoned due to unstable interfaces0ClConfiguration for sending and handling validation tokens \xe2\x80\xa60CmMaximum number of packets that may be sent using a single \xe2\x80\xa60CiCounter for the number of bytes currently used in the \xe2\x80\xa6CgReturns whether we think the other address probably \xe2\x80\xa6ChHandle a change in the local address, i.e. an active \xe2\x80\xa6CkReduction in congestion window when a new loss event is \xe2\x80\xa60DdMaximum number of datagrams that a Transmit may encode.0DjA broadcast receiver of iroh_hp::Events for updates about \xe2\x80\xa6CjGet the address observed by the remote over the given pathCiMaximum number of bytes the peer may transmit without \xe2\x80\xa600Chreceived more data in CRYPTO frames than can be buffered0B`The extension was not negotiatedCbWe failed to figure out what time it currently is.0CbWe failed to acquire random bytes from the system.0CnError indicating that this operation requires multipath to \xe2\x80\xa6BnThe extension was not negotiated with the peerBnHeader of an Initial packet, before decryptionCgDerive keying material from this connection\xe2\x80\x99s TLS \xe2\x80\xa6EdFill output with output.len() bytes of keying material \xe2\x80\xa60BnPathological case: many segments, get from endCfGet segments in the old way, using a loop of get callsClCurrent number of remotely initiated streams that may be \xe2\x80\xa6ClTrack changed on our external address as reported by the \xe2\x80\xa6ClTrack changes on our external address as reported by the \xe2\x80\xa6CnCreate a client configuration that trusts the platform\xe2\x80\x99s \xe2\x80\xa60CmCreate a client configuration that trusts specified trust \xe2\x80\xa60BkThe peer didn\xe2\x80\x99t give us any certificates.0BkThe peer sent an oversized record/fragment.0CkThe ack-eliciting threshold we will request the peer to use0BiWhether there are any pending retransmitsCdWhether the Multipath for QUIC extension is enabled.C`Sets the keep_alive_interval for a specific pathBoSet a custom ValidationTokenConfig0BmPath abandoned at the application\xe2\x80\x99s request0CjGet the current value of max_udp_payload_size0ChConfigure how to populate the destination CID of the \xe2\x80\xa60CjConstruct an endpoint with arbitrary configuration and \xe2\x80\xa6CfWhether the socket address that is initiating this \xe2\x80\xa60CmModify the number of open paths allowed when multipath is \xe2\x80\xa6Cmthe number of connection IDs provided by the peer exceeds \xe2\x80\xa60CbError returned by Session::export_keying_material.0CiA provided certificate revocation list (CRL) was invalid.0CmPath abandoned due to no available connection IDs for the \xe2\x80\xa60Clreceived transport parameters that were badly formatted, \xe2\x80\xa60CiRegisters one address at which this endpoint might be \xe2\x80\xa6ClAdd addresses the local endpoint considers are reachable \xe2\x80\xa6ClMaximum number of outgoing application datagram bytes to \xe2\x80\xa60CiSet the client configuration used by connectBmSets the max_idle_timeout for a specific pathBfThe QUIC protocol version implemented.BoBytes available in the outgoing datagram bufferDhMaximum number of received bytes to buffer for all Incoming0DaVariant of max_concurrent_bidi_streams affecting \xe2\x80\xa60ClModify the number of remotely initiated streams that may \xe2\x80\xa6CnCreate a client configuration that trusts the platform\xe2\x80\x99s \xe2\x80\xa60CkGenerates 8-byte connection IDs that can be efficiently \xe2\x80\xa6CkAn error occurred while handling Encrypted Client Hello \xe2\x80\xa60CkPath abandoned due to resource limitations in the transport0CiGenerates purely random connection IDs of a specified \xe2\x80\xa6ChWhether to use \xe2\x80\x9cGeneric Segmentation Offload\xe2\x80\x9d to \xe2\x80\xa60CmMaximum number of incoming bidirectional streams that may \xe2\x80\xa60BhUpdates this tuple\xe2\x80\x99s local address iffClMaximum number of incoming application datagram bytes to \xe2\x80\xa60BcInitiates a new nat traversal round0BdPackets were incorrectly deemed lost0CnRemoves one or more addresses from the set of addresses at \xe2\x80\xa6CgRemoves an address the endpoing no longer considers \xe2\x80\xa6C`Sets the keep_alive_interval for a specific pathDeA ConnectionIdParser implementation that assumes the \xe2\x80\xa6CjWe received a TLS handshake message that isn\xe2\x80\x99t valid \xe2\x80\xa60CiHow to construct new congestion::Controllers0BlSets a default per-path maximum idle timeout0BoThe key exchange group negotiated with the peer0CbWhether to send observed address reports to peers.0CiModify the number of remotely initiated bidirectional \xe2\x80\xa6BiEnables the Multipath Extension for QUIC.0CjModify the number of remotely initiated unidirectional \xe2\x80\xa6CeNumber of consecutive PTOs after which network is \xe2\x80\xa60BkSets a default per-path keep alive interval0CjWhether to receive observed address reports from other \xe2\x80\xa60BmGet the current local nat traversal addresses0CkGet the currently advertised nat traversal addresses by \xe2\x80\xa60AcNat traversal draftCkSets the maximum number of nat traversal addresses this \xe2\x80\xa60CjWhen multipath is required and has not been explicitly \xe2\x80\xa6") \ No newline at end of file diff --git a/pr/255/docs/search.index/root.js b/pr/255/docs/search.index/root.js index 0d4764c97..169f35e33 100644 --- a/pr/255/docs/search.index/root.js +++ b/pr/255/docs/search.index/root.js @@ -1 +1 @@ -rr_('{"normalizedName":{"I":"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","N":"ACJj","E":"OjAAAAAAAAA=","H":"R52VM/3R"},"crateNames":{"N":"j","E":"OjAAAAAAAAA=","H":"ijgfzyvU"},"name":{"N":"ACJj","E":"OjAAAAAAAAA=","H":"gmOgDEyK"},"path":{"N":"B@j","E":"OzAAAAEAAJ8RsAACAAQACQAAAAsAWQBmAAEAbAAAAHIABAB9AAEAgQAbAJ8A1QB3AQgAgQEyALgBAAC8AQUAyAEAAMsBAgDPAQAA1QEFAN0BFwL2AwAA+AMRAAsEAgAPBAMAFAQKACAECQAsBNAABQUAABcFAQAaBQMAHwUAACEFAAApBYoAtQUBALgFAAC6BQgAxAUIAM4FAgDUBQcA4AUCAOQFBADsBQIA8AUDAPsFAQAHBgUAEQbcAO8GBAD1BgAA9wYAAPoGOgA2Bw4ARwcDAEwHAwBRBxQAZwcJAHMHAgB7BwEAfwcAAIQHAQCIBwAAigcDAJYHAwCcBwAAoQdmAAkIEgAeCAYAJgjhAAoJAAAMCQEAEAkBABcJAAAcCQUAJgkAACoJAAAtCQEAMgkBADsJBQBDCRgAXQkUAHMJTgLDCwAAyQsBAM8LAADYCwAA3AsDAOkLAADwCwkA+wsHAAQMJQArDEgAdQwDAH0MAAB/DAEAlgwBALIMUAEFDgIACg7eAOoOEgD+DgcABw8AABIPAQAYDwMAHg8DACMPAQAqDwMALw8/AHAPAgB1DxUAkQ8BAJQPAgCeDwEAow8HAK8PBAC2DwAAxQ8xAPgPHwAaEAMAIhAAACUQAQAoEAIALBAHADgQAQA9EAEAQxADAEgQAABKEAIAThA4AI0QBQCWEAEAmhAFAKMQBQCtEAEAsRAhANQQMAAGEQAAChEAAA8RAQASEQEAIBEBACMRAwAoEZIAvBEAAL8RAQDCEQQAyBEKANQRAQDcEQEA3xETAPQRHQAYEgEAHhIRADESAgA2EgMAOxIHAEUSAwBKEgUAVBIBAFkSAABbEgEAXhIWAHYSAgB7EgQAghIfAKQSCwCyEgQAuRIAAL8SJQDmEgQA7hIFAPYSGgATExIAKBMXAEITCgBQEwUAVxMTAGwTAwBxExcAjBMdAA==","H":"jwNIbELx"},"entry":{"N":"ABJf","E":"OjAAAAEAAAAAAAMBEAAAAAAAAQAHAAgACgBlAGgAaQBtAG4AdwB7AHwAfwCAAJ0AngB1AXYBgAG0AbUBtgG3AbkBugG7AcIBwwHEAccByQHOAdAB0wHUAdsB9QMKBA4EEwQfBCoEKwT9BP4EAQUCBQYFBwUIBQkFCgULBQwFDQUOBQ8FFAUZBR4FIAUiBSUFJgUnBbQFtwW5BcMFzQXRBdIF0wXcBd0F3gXfBekF6gXvBfQF9QX2BfcF+QX6Bf0F/gUBBgIGAwYEBgUGDQYOBu4G9Ab2BvgG+QY1B0UHRgdLB1AHZgd2B3cHeAd5B3oHgAeDB44HjweQB5EHlQebB50HngcICBwIHQglCAkJDwkSCRMJFgkaCSQJJQknCSgJLwk5CToJQQlCCVwJcgnCC8ULxgvHC8gLzQvQC9QL2wviC+QL5QvsC+4L7wv6CwMMKgx0DHkMewx8DH4MggyEDIkMigyNDI4MkAyRDJIMkwyUDJUMmAycDKIMpQymDKcMqAwDDgQOCA4JDgoPDQ8XDyUPKQ9vD3MPdA+LD4wPmA+bD6sPrg+1D7cPug+7D8APwQ/ED/cPHhAnECsQNhA6EDsQPxBHEEkQiBCJEIsQjBCVEJkQohAOERQRGBEZERwRHxEnEb4RxxHTEd4RGhJJElASURJSElgSdRJ6EqISoxKwErESuhK9EuUS7RImEycTTRNWE4oTixM=","H":"6/FXEJon"},"desc":{"N":"FIm","E":"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","H":"oXQk82Rm"},"function":{"N":"A@Df","E":"OzAAAAEAAGMDVwAAAAoAZQAbAJ0AAQB1AQEAgAEAALQBIgDbAQEA9QMAAPcDAAAKBAAADgQAABMEAAAfBAAAKgQBAP0EKwC0BQAAtwUAALkFAADDBQAAzQUAANEFAwDZBQAA3AUDAOMFLQDuBgAA8QYAAPQGAgD4BgIA/gYAADUHAABFBwYATgcAAFAHAABmBwAAcQcwAAgIAQAcCAEAJQgAAAgJMwBBCQEAXAkAAHIJAADCCy0A+gsAAAMMAAAqDAAAdAwAAHkMAwB+DDMAAw4DAAgOAQDpDgAA/Q4AAAYPAAAIDxcAIg8HAC4PAABvDwAAcw8BAIgPHwCpDxsA9w8BABYQLABHEAIATRAAAIIQLgDTEAAABBEjALoRJQDzEQAADhIVADASAAAyEhMARxIWAHUSAAB5EgsAohICAKwSEgDlEgAA6BIAAOsSCgAGEwwAJhMFAD4TAwBLEwsAaxMFAIkTBAA=","H":"4L0CD+5+"},"type":{"N":"AIn","E":"OzAAAAEAAAsSkgACAAQACQAAAAsAWQBmAAEAbAAAAHIABQB7AAAAfQABAIAAHACfANUAdgEJAIEBMgC4AQEAuwEIAMgBAADLAQIAzwEAANQBBgDcAU0CLATQAAEFAAAFBQIADAUBABQFAAAXBQEAGgUDAB8FAAAhBQAAKAWkAM4FDwDgBQIA5AUFAOwFAgDwBQMA+wUBAAcGBQARBl8BcwcCAHgHBAB/BwAAhAcBAIgHAACKBwMAlgcDAJsHAwChB3oAHQjqAAoJAAAMCQEADwkCABcJAAAaCQAAHAkFACYJAAAqCQAALQkBADIJAQA7CYYCwwsAAMULAgDJCwEAzQsAAM8LAADYCwAA3AsDAOILAADkCwAA6QsAAOwLAADvCzoAKwxNAHsMAgB/DAEAggwAAIkMAQCNDAAAlQwCAKcMAACyDFMCBw8AABIPAQAXDwQAHg8DACMPAgAqD2AAkQ8BAJQPAgCeDwEAow8HAK8PBAC2DwAAxQ9SABoQBAAiEAAAJRABACgQAgAsEAcAOBABAD0QAQBDEEMAixAAAI0QBQCVEAIAmhAFAKMQBQCtEAEAsRBTAAYRAAAKEQAADxEBABIRAgAgEQEAIxGXALwRAAC/EQEAwhEEAMgRCgDUEQEA3BEBAN8RMgAYEgIAHhIVADYSAwA7EgcARRIDAEoSBQBREgAAVBIBAFkSAABbEgEAXhIaAHsSBACCEi0AshIEALkSAAC/EisA7hIFAPYSGgATExIAKBMXAEITCgBQEwUAVxMTAGwTAwBxExcAjBMdAA==","H":"I7Zgg8Ac"},"alias":{"N":"`","E":"OzAAAAEAAKkTAQAAAKkT","H":"p2IVDFMs"},"generic_inverted_index":{"N":"b","E":"OjAAAAAAAAA=","H":"dwUQgl4C"}}') \ No newline at end of file +rr_('{"normalizedName":{"I":"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","N":"ACJj","E":"OjAAAAAAAAA=","H":"R52VM/3R"},"crateNames":{"N":"j","E":"OjAAAAAAAAA=","H":"ijgfzyvU"},"name":{"N":"ACJj","E":"OjAAAAAAAAA=","H":"gmOgDEyK"},"path":{"N":"B@j","E":"OzAAAAEAAJ8RsAACAAQACQAAAAsAWQBmAAEAbAAAAHIABAB9AAEAgQAbAJ8A1QB3AQgAgQEyALgBAAC8AQUAyAEAAMsBAgDPAQAA1QEFAN0BFwL2AwAA+AMRAAsEAgAPBAMAFAQKACAECQAsBNAABQUAABcFAQAaBQMAHwUAACEFAAApBYoAtQUBALgFAAC6BQgAxAUIAM4FAgDUBQcA4AUCAOQFBADsBQIA8AUDAPsFAQAHBgUAEQbcAO8GBAD1BgAA9wYAAPoGOgA2Bw4ARwcDAEwHAwBRBxQAZwcJAHMHAgB7BwEAfwcAAIQHAQCIBwAAigcDAJYHAwCcBwAAoQdmAAkIEgAeCAYAJgjhAAoJAAAMCQEAEAkBABcJAAAcCQUAJgkAACoJAAAtCQEAMgkBADsJBQBDCRgAXQkUAHMJTgLDCwAAyQsBAM8LAADYCwAA3AsDAOkLAADwCwkA+wsHAAQMJQArDEgAdQwDAH0MAAB/DAEAlgwBALIMUAEFDgIACg7eAOoOEgD+DgcABw8AABIPAQAYDwMAHg8DACMPAQAqDwMALw8/AHAPAgB1DxUAkQ8BAJQPAgCeDwEAow8HAK8PBAC2DwAAxQ8xAPgPHwAaEAMAIhAAACUQAQAoEAIALBAHADgQAQA9EAEAQxADAEgQAABKEAIAThA4AI0QBQCWEAEAmhAFAKMQBQCtEAEAsRAhANQQMAAGEQAAChEAAA8RAQASEQEAIBEBACMRAwAoEZIAvBEAAL8RAQDCEQQAyBEKANQRAQDcEQEA3xETAPQRHQAYEgEAHhIRADESAgA2EgMAOxIHAEUSAwBKEgUAVBIBAFkSAABbEgEAXhIWAHYSAgB7EgQAghIfAKQSCwCyEgQAuRIAAL8SJQDmEgQA7hIFAPYSGgATExIAKBMXAEITCgBQEwUAVxMTAGwTAwBxExcAjBMdAA==","H":"jwNIbELx"},"entry":{"N":"ABJf","E":"OjAAAAEAAAAAAAMBEAAAAAAAAQAHAAgACgBlAGgAaQBtAG4AdwB7AHwAfwCAAJ0AngB1AXYBgAG0AbUBtgG3AbkBugG7AcIBwwHEAccByQHOAdAB0wHUAdsB9QMKBA4EEwQfBCoEKwT9BP4EAQUCBQYFBwUIBQkFCgULBQwFDQUOBQ8FFAUZBR4FIAUiBSUFJgUnBbQFtwW5BcMFzQXRBdIF0wXcBd0F3gXfBekF6gXvBfQF9QX2BfcF+QX6Bf0F/gUBBgIGAwYEBgUGDQYOBu4G9Ab2BvgG+QY1B0UHRgdLB1AHZgd2B3cHeAd5B3oHgAeDB44HjweQB5EHlQebB50HngcICBwIHQglCAkJDwkSCRMJFgkaCSQJJQknCSgJLwk5CToJQQlCCVwJcgnCC8ULxgvHC8gLzQvQC9QL2wviC+QL5QvsC+4L7wv6CwMMKgx0DHkMewx8DH4MggyEDIkMigyNDI4MkAyRDJIMkwyUDJUMmAycDKIMpQymDKcMqAwDDgQOCA4JDgoPDQ8XDyUPKQ9vD3MPdA+LD4wPmA+bD6sPrg+1D7cPug+7D8APwQ/ED/cPHhAnECsQNhA6EDsQPxBHEEkQiBCJEIsQjBCVEJkQohAOERQRGBEZERwRHxEnEb4RxxHTEd4RGhJJElASURJSElgSdRJ6EqISoxKwErESuhK9EuUS7RImEycTTRNWE4oTixM=","H":"6/FXEJon"},"desc":{"N":"FIk","E":"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","H":"7igw/4ee"},"function":{"N":"A@Df","E":"OzAAAAEAAGMDVwAAAAoAZQAbAJ0AAQB1AQEAgAEAALQBIgDbAQEA9QMAAPcDAAAKBAAADgQAABMEAAAfBAAAKgQBAP0EKwC0BQAAtwUAALkFAADDBQAAzQUAANEFAwDZBQAA3AUDAOMFLQDuBgAA8QYAAPQGAgD4BgIA/gYAADUHAABFBwYATgcAAFAHAABmBwAAcQcwAAgIAQAcCAEAJQgAAAgJMwBBCQEAXAkAAHIJAADCCy0A+gsAAAMMAAAqDAAAdAwAAHkMAwB+DDMAAw4DAAgOAQDpDgAA/Q4AAAYPAAAIDxcAIg8HAC4PAABvDwAAcw8BAIgPHwCpDxsA9w8BABYQLABHEAIATRAAAIIQLgDTEAAABBEjALoRJQDzEQAADhIVADASAAAyEhMARxIWAHUSAAB5EgsAohICAKwSEgDlEgAA6BIAAOsSCgAGEwwAJhMFAD4TAwBLEwsAaxMFAIkTBAA=","H":"4L0CD+5+"},"type":{"N":"AIn","E":"OzAAAAEAAAsSkgACAAQACQAAAAsAWQBmAAEAbAAAAHIABQB7AAAAfQABAIAAHACfANUAdgEJAIEBMgC4AQEAuwEIAMgBAADLAQIAzwEAANQBBgDcAU0CLATQAAEFAAAFBQIADAUBABQFAAAXBQEAGgUDAB8FAAAhBQAAKAWkAM4FDwDgBQIA5AUFAOwFAgDwBQMA+wUBAAcGBQARBl8BcwcCAHgHBAB/BwAAhAcBAIgHAACKBwMAlgcDAJsHAwChB3oAHQjqAAoJAAAMCQEADwkCABcJAAAaCQAAHAkFACYJAAAqCQAALQkBADIJAQA7CYYCwwsAAMULAgDJCwEAzQsAAM8LAADYCwAA3AsDAOILAADkCwAA6QsAAOwLAADvCzoAKwxNAHsMAgB/DAEAggwAAIkMAQCNDAAAlQwCAKcMAACyDFMCBw8AABIPAQAXDwQAHg8DACMPAgAqD2AAkQ8BAJQPAgCeDwEAow8HAK8PBAC2DwAAxQ9SABoQBAAiEAAAJRABACgQAgAsEAcAOBABAD0QAQBDEEMAixAAAI0QBQCVEAIAmhAFAKMQBQCtEAEAsRBTAAYRAAAKEQAADxEBABIRAgAgEQEAIxGXALwRAAC/EQEAwhEEAMgRCgDUEQEA3BEBAN8RMgAYEgIAHhIVADYSAwA7EgcARRIDAEoSBQBREgAAVBIBAFkSAABbEgEAXhIaAHsSBACCEi0AshIEALkSAAC/EisA7hIFAPYSGgATExIAKBMXAEITCgBQEwUAVxMTAGwTAwBxExcAjBMdAA==","H":"I7Zgg8Ac"},"alias":{"N":"`","E":"OzAAAAEAAKkTAQAAAKkT","H":"p2IVDFMs"},"generic_inverted_index":{"N":"b","E":"OjAAAAAAAAA=","H":"dwUQgl4C"}}') \ No newline at end of file diff --git a/pr/255/docs/src/iroh_quinn/connection.rs.html b/pr/255/docs/src/iroh_quinn/connection.rs.html index d52b89625..a209854c2 100644 --- a/pr/255/docs/src/iroh_quinn/connection.rs.html +++ b/pr/255/docs/src/iroh_quinn/connection.rs.html @@ -53,7 +53,7 @@ 53 let (on_handshake_data_send, on_handshake_data_recv) = oneshot::channel(); 54 let (on_connected_send, on_connected_recv) = oneshot::channel(); 55 -56 let conn = ConnectionRef(Arc::new(ConnectionInner { +56 let conn = ConnectionRef(Arc::new(Arc::new(ConnectionInner { 57 state: Mutex::new(State::new( 58 conn, 59 handle, @@ -65,7 +65,7 @@ 65 runtime.clone(), 66 )), 67 shared: Shared::default(), -68 })); +68 }))); 69 70 let driver = ConnectionDriver(conn.clone()); 71 runtime.spawn(Box::pin( @@ -1222,538 +1222,540 @@ 1222} 1223 1224#[derive(Debug)] -1225pub(crate) struct ConnectionRef(Arc<ConnectionInner>); -1226 -1227impl ConnectionRef { -1228 fn from_arc(inner: Arc<ConnectionInner>) -> Self { -1229 inner.state.lock("from_arc").ref_count += 1; -1230 Self(inner) -1231 } -1232 -1233 fn stable_id(&self) -> usize { -1234 &*self.0 as *const _ as usize -1235 } -1236} -1237 -1238impl Clone for ConnectionRef { -1239 fn clone(&self) -> Self { -1240 Self::from_arc(Arc::clone(&self.0)) -1241 } -1242} -1243 -1244impl Drop for ConnectionRef { -1245 fn drop(&mut self) { -1246 let conn = &mut *self.state.lock("drop"); -1247 if let Some(x) = conn.ref_count.checked_sub(1) { -1248 conn.ref_count = x; -1249 if x == 0 && !conn.inner.is_closed() { -1250 // If the driver is alive, it's just it and us, so we'd better shut it down. If it's -1251 // not, we can't do any harm. If there were any streams being opened, then either -1252 // the connection will be closed for an unrelated reason or a fresh reference will -1253 // be constructed for the newly opened stream. -1254 conn.implicit_close(&self.shared); -1255 } -1256 } -1257 } -1258} -1259 -1260impl std::ops::Deref for ConnectionRef { -1261 type Target = ConnectionInner; -1262 fn deref(&self) -> &Self::Target { -1263 &self.0 -1264 } -1265} -1266 -1267#[derive(Debug)] -1268pub(crate) struct ConnectionInner { -1269 pub(crate) state: Mutex<State>, -1270 pub(crate) shared: Shared, -1271} -1272 -1273/// A handle to some connection internals, use with care. -1274/// -1275/// This contains a weak reference to the connection so will not itself keep the connection -1276/// alive. -1277#[derive(Debug, Clone)] -1278pub struct WeakConnectionHandle(Weak<ConnectionInner>); -1279 -1280impl WeakConnectionHandle { -1281 /// Returns `true` if the [`Connection`] associated with this handle is still alive. -1282 pub fn is_alive(&self) -> bool { -1283 self.0.upgrade().is_some() -1284 } -1285 -1286 /// Upgrade the handle to a full `Connection` -1287 pub fn upgrade(&self) -> Option<Connection> { -1288 self.0 -1289 .upgrade() -1290 .map(|inner| Connection(ConnectionRef::from_arc(inner))) -1291 } -1292} -1293 -1294#[derive(Debug, Default)] -1295pub(crate) struct Shared { -1296 handshake_confirmed: Notify, -1297 /// Notified when new streams may be locally initiated due to an increase in stream ID flow -1298 /// control budget -1299 stream_budget_available: [Notify; 2], -1300 /// Notified when the peer has initiated a new stream -1301 stream_incoming: [Notify; 2], -1302 datagram_received: Notify, -1303 datagrams_unblocked: Notify, -1304 closed: Notify, -1305} -1306 -1307pub(crate) struct State { -1308 pub(crate) inner: proto::Connection, -1309 driver: Option<Waker>, -1310 handle: ConnectionHandle, -1311 on_handshake_data: Option<oneshot::Sender<()>>, -1312 on_connected: Option<oneshot::Sender<bool>>, -1313 connected: bool, -1314 handshake_confirmed: bool, -1315 timer: Option<Pin<Box<dyn AsyncTimer>>>, -1316 timer_deadline: Option<Instant>, -1317 conn_events: mpsc::UnboundedReceiver<ConnectionEvent>, -1318 endpoint_events: mpsc::UnboundedSender<(ConnectionHandle, EndpointEvent)>, -1319 pub(crate) blocked_writers: FxHashMap<StreamId, Waker>, -1320 pub(crate) blocked_readers: FxHashMap<StreamId, Waker>, -1321 pub(crate) stopped: FxHashMap<StreamId, Arc<Notify>>, -1322 /// Always set to Some before the connection becomes drained -1323 pub(crate) error: Option<ConnectionError>, -1324 /// Tracks paths being opened -1325 open_path: FxHashMap<PathId, watch::Sender<Result<(), PathError>>>, -1326 /// Tracks paths being closed -1327 pub(crate) close_path: FxHashMap<PathId, oneshot::Sender<VarInt>>, -1328 pub(crate) path_events: tokio::sync::broadcast::Sender<PathEvent>, -1329 /// Number of live handles that can be used to initiate or handle I/O; excludes the driver -1330 ref_count: usize, -1331 sender: Pin<Box<dyn UdpSender>>, -1332 pub(crate) runtime: Arc<dyn Runtime>, -1333 send_buffer: Vec<u8>, -1334 /// We buffer a transmit when the underlying I/O would block -1335 buffered_transmit: Option<proto::Transmit>, -1336 /// Our last external address reported by the peer. When multipath is enabled, this will be the -1337 /// last report across all paths. -1338 pub(crate) observed_external_addr: watch::Sender<Option<SocketAddr>>, -1339 pub(crate) nat_traversal_updates: tokio::sync::broadcast::Sender<iroh_hp::Event>, -1340 on_closed: Vec<oneshot::Sender<(ConnectionError, ConnectionStats)>>, -1341} -1342 -1343impl State { -1344 #[allow(clippy::too_many_arguments)] -1345 fn new( -1346 inner: proto::Connection, -1347 handle: ConnectionHandle, -1348 endpoint_events: mpsc::UnboundedSender<(ConnectionHandle, EndpointEvent)>, -1349 conn_events: mpsc::UnboundedReceiver<ConnectionEvent>, -1350 on_handshake_data: oneshot::Sender<()>, -1351 on_connected: oneshot::Sender<bool>, -1352 sender: Pin<Box<dyn UdpSender>>, -1353 runtime: Arc<dyn Runtime>, -1354 ) -> Self { -1355 Self { -1356 inner, -1357 driver: None, -1358 handle, -1359 on_handshake_data: Some(on_handshake_data), -1360 on_connected: Some(on_connected), -1361 connected: false, -1362 handshake_confirmed: false, -1363 timer: None, -1364 timer_deadline: None, -1365 conn_events, -1366 endpoint_events, -1367 blocked_writers: FxHashMap::default(), -1368 blocked_readers: FxHashMap::default(), -1369 stopped: FxHashMap::default(), -1370 open_path: FxHashMap::default(), -1371 close_path: FxHashMap::default(), -1372 error: None, -1373 ref_count: 0, -1374 sender, -1375 runtime, -1376 send_buffer: Vec::new(), -1377 buffered_transmit: None, -1378 path_events: tokio::sync::broadcast::channel(32).0, -1379 observed_external_addr: watch::Sender::new(None), -1380 nat_traversal_updates: tokio::sync::broadcast::channel(32).0, -1381 on_closed: Vec::new(), -1382 } -1383 } -1384 -1385 fn drive_transmit(&mut self, cx: &mut Context) -> io::Result<bool> { -1386 let now = self.runtime.now(); -1387 let mut transmits = 0; -1388 -1389 let max_datagrams = self -1390 .sender -1391 .max_transmit_segments() -1392 .min(MAX_TRANSMIT_SEGMENTS); -1393 -1394 loop { -1395 // Retry the last transmit, or get a new one. -1396 let t = match self.buffered_transmit.take() { -1397 Some(t) => t, -1398 None => { -1399 self.send_buffer.clear(); -1400 match self -1401 .inner -1402 .poll_transmit(now, max_datagrams, &mut self.send_buffer) -1403 { -1404 Some(t) => { -1405 transmits += match t.segment_size { -1406 None => 1, -1407 Some(s) => t.size.div_ceil(s), // round up -1408 }; -1409 t -1410 } -1411 None => break, -1412 } -1413 } -1414 }; -1415 -1416 let len = t.size; -1417 match self -1418 .sender -1419 .as_mut() -1420 .poll_send(&udp_transmit(&t, &self.send_buffer[..len]), cx) -1421 { -1422 Poll::Pending => { -1423 self.buffered_transmit = Some(t); -1424 return Ok(false); -1425 } -1426 Poll::Ready(Err(e)) => return Err(e), -1427 Poll::Ready(Ok(())) => {} -1428 } -1429 -1430 if transmits >= MAX_TRANSMIT_DATAGRAMS { -1431 // TODO: What isn't ideal here yet is that if we don't poll all -1432 // datagrams that could be sent we don't go into the `app_limited` -1433 // state and CWND continues to grow until we get here the next time. -1434 // See https://github.com/quinn-rs/quinn/issues/1126 -1435 return Ok(true); -1436 } -1437 } -1438 -1439 Ok(false) -1440 } -1441 -1442 fn forward_endpoint_events(&mut self) { -1443 while let Some(event) = self.inner.poll_endpoint_events() { -1444 // If the endpoint driver is gone, noop. -1445 let _ = self.endpoint_events.send((self.handle, event)); -1446 } -1447 } -1448 -1449 /// If this returns `Err`, the endpoint is dead, so the driver should exit immediately. -1450 fn process_conn_events( -1451 &mut self, -1452 shared: &Shared, -1453 cx: &mut Context, -1454 ) -> Result<(), ConnectionError> { -1455 loop { -1456 match self.conn_events.poll_recv(cx) { -1457 Poll::Ready(Some(ConnectionEvent::Rebind(sender))) => { -1458 self.sender = sender; -1459 self.inner.local_address_changed(); -1460 } -1461 Poll::Ready(Some(ConnectionEvent::Proto(event))) => { -1462 self.inner.handle_event(event); -1463 } -1464 Poll::Ready(Some(ConnectionEvent::Close { reason, error_code })) => { -1465 self.close(error_code, reason, shared); -1466 } -1467 Poll::Ready(None) => { -1468 return Err(ConnectionError::TransportError(TransportError::new( -1469 TransportErrorCode::INTERNAL_ERROR, -1470 "endpoint driver future was dropped".to_string(), -1471 ))); -1472 } -1473 Poll::Pending => { -1474 return Ok(()); -1475 } -1476 } -1477 } -1478 } -1479 -1480 fn forward_app_events(&mut self, shared: &Shared) { -1481 while let Some(event) = self.inner.poll() { -1482 use proto::Event::*; -1483 match event { -1484 HandshakeDataReady => { -1485 if let Some(x) = self.on_handshake_data.take() { -1486 let _ = x.send(()); -1487 } -1488 } -1489 Connected => { -1490 self.connected = true; -1491 if let Some(x) = self.on_connected.take() { -1492 // We don't care if the on-connected future was dropped -1493 let _ = x.send(self.inner.accepted_0rtt()); -1494 } -1495 if self.inner.side().is_client() && !self.inner.accepted_0rtt() { -1496 // Wake up rejected 0-RTT streams so they can fail immediately with -1497 // `ZeroRttRejected` errors. -1498 wake_all(&mut self.blocked_writers); -1499 wake_all(&mut self.blocked_readers); -1500 wake_all_notify(&mut self.stopped); -1501 } -1502 } -1503 HandshakeConfirmed => { -1504 self.handshake_confirmed = true; -1505 shared.handshake_confirmed.notify_waiters(); -1506 } -1507 ConnectionLost { reason } => { -1508 self.terminate(reason, shared); -1509 } -1510 Stream(StreamEvent::Writable { id }) => wake_stream(id, &mut self.blocked_writers), -1511 Stream(StreamEvent::Opened { dir: Dir::Uni }) => { -1512 shared.stream_incoming[Dir::Uni as usize].notify_waiters(); -1513 } -1514 Stream(StreamEvent::Opened { dir: Dir::Bi }) => { -1515 shared.stream_incoming[Dir::Bi as usize].notify_waiters(); -1516 } -1517 DatagramReceived => { -1518 shared.datagram_received.notify_waiters(); -1519 } -1520 DatagramsUnblocked => { -1521 shared.datagrams_unblocked.notify_waiters(); -1522 } -1523 Stream(StreamEvent::Readable { id }) => wake_stream(id, &mut self.blocked_readers), -1524 Stream(StreamEvent::Available { dir }) => { -1525 // Might mean any number of streams are ready, so we wake up everyone -1526 shared.stream_budget_available[dir as usize].notify_waiters(); -1527 } -1528 Stream(StreamEvent::Finished { id }) => wake_stream_notify(id, &mut self.stopped), -1529 Stream(StreamEvent::Stopped { id, .. }) => { -1530 wake_stream_notify(id, &mut self.stopped); -1531 wake_stream(id, &mut self.blocked_writers); -1532 } -1533 Path(ref evt @ PathEvent::ObservedAddr { addr: observed, .. }) => { -1534 self.path_events.send(evt.clone()).ok(); -1535 self.observed_external_addr.send_if_modified(|addr| { -1536 let old = addr.replace(observed); -1537 old != *addr -1538 }); -1539 } -1540 Path(ref evt @ PathEvent::Opened { id }) => { -1541 self.path_events.send(evt.clone()).ok(); -1542 if let Some(sender) = self.open_path.remove(&id) { -1543 sender.send_modify(|value| *value = Ok(())); -1544 } -1545 } -1546 Path(ref evt @ PathEvent::Closed { id, error_code }) => { -1547 self.path_events.send(evt.clone()).ok(); -1548 if let Some(sender) = self.close_path.remove(&id) { -1549 let _ = sender.send(error_code); -1550 } -1551 } -1552 Path(evt @ PathEvent::Abandoned { .. }) => { -1553 self.path_events.send(evt).ok(); -1554 } -1555 Path(ref evt @ PathEvent::LocallyClosed { id, error }) => { -1556 self.path_events.send(evt.clone()).ok(); -1557 if let Some(sender) = self.open_path.remove(&id) { -1558 sender.send_modify(|value| *value = Err(error)); -1559 } -1560 // this will happen also for already opened paths -1561 } -1562 Path(evt @ PathEvent::RemoteStatus { .. }) => { -1563 self.path_events.send(evt).ok(); -1564 } -1565 NatTraversal(update) => { -1566 self.nat_traversal_updates.send(update).ok(); -1567 } -1568 } -1569 } -1570 } -1571 -1572 fn drive_timer(&mut self, cx: &mut Context) -> bool { -1573 // Check whether we need to (re)set the timer. If so, we must poll again to ensure the -1574 // timer is registered with the runtime (and check whether it's already -1575 // expired). -1576 match self.inner.poll_timeout() { -1577 Some(deadline) => { -1578 if let Some(delay) = &mut self.timer { -1579 // There is no need to reset the tokio timer if the deadline -1580 // did not change -1581 if self -1582 .timer_deadline -1583 .map(|current_deadline| current_deadline != deadline) -1584 .unwrap_or(true) -1585 { -1586 delay.as_mut().reset(deadline); -1587 } -1588 } else { -1589 self.timer = Some(self.runtime.new_timer(deadline)); -1590 } -1591 // Store the actual expiration time of the timer -1592 self.timer_deadline = Some(deadline); -1593 } -1594 None => { -1595 self.timer_deadline = None; -1596 return false; -1597 } -1598 } -1599 -1600 if self.timer_deadline.is_none() { -1601 return false; -1602 } -1603 -1604 let delay = self -1605 .timer -1606 .as_mut() -1607 .expect("timer must exist in this state") -1608 .as_mut(); -1609 if delay.poll(cx).is_pending() { -1610 // Since there wasn't a timeout event, there is nothing new -1611 // for the connection to do -1612 return false; -1613 } -1614 -1615 // A timer expired, so the caller needs to check for -1616 // new transmits, which might cause new timers to be set. -1617 self.inner.handle_timeout(self.runtime.now()); -1618 self.timer_deadline = None; -1619 true -1620 } -1621 -1622 /// Wake up a blocked `Driver` task to process I/O -1623 pub(crate) fn wake(&mut self) { -1624 if let Some(x) = self.driver.take() { -1625 x.wake(); -1626 } -1627 } -1628 -1629 /// Used to wake up all blocked futures when the connection becomes closed for any reason -1630 fn terminate(&mut self, reason: ConnectionError, shared: &Shared) { -1631 self.error = Some(reason.clone()); -1632 if let Some(x) = self.on_handshake_data.take() { -1633 let _ = x.send(()); -1634 } -1635 wake_all(&mut self.blocked_writers); -1636 wake_all(&mut self.blocked_readers); -1637 shared.stream_budget_available[Dir::Uni as usize].notify_waiters(); -1638 shared.stream_budget_available[Dir::Bi as usize].notify_waiters(); -1639 shared.stream_incoming[Dir::Uni as usize].notify_waiters(); -1640 shared.stream_incoming[Dir::Bi as usize].notify_waiters(); -1641 shared.datagram_received.notify_waiters(); -1642 shared.datagrams_unblocked.notify_waiters(); -1643 if let Some(x) = self.on_connected.take() { -1644 let _ = x.send(false); -1645 } -1646 shared.handshake_confirmed.notify_waiters(); -1647 wake_all_notify(&mut self.stopped); -1648 shared.closed.notify_waiters(); -1649 -1650 // Send to the registered on_closed futures. -1651 let stats = self.inner.stats(); -1652 for tx in self.on_closed.drain(..) { -1653 tx.send((reason.clone(), stats.clone())).ok(); -1654 } -1655 } -1656 -1657 fn close(&mut self, error_code: VarInt, reason: Bytes, shared: &Shared) { -1658 self.inner.close(self.runtime.now(), error_code, reason); -1659 self.terminate(ConnectionError::LocallyClosed, shared); -1660 self.wake(); -1661 } -1662 -1663 /// Close for a reason other than the application's explicit request -1664 pub(crate) fn implicit_close(&mut self, shared: &Shared) { -1665 self.close(0u32.into(), Bytes::new(), shared); -1666 } -1667 -1668 pub(crate) fn check_0rtt(&self) -> Result<(), ()> { -1669 if self.inner.is_handshaking() -1670 || self.inner.accepted_0rtt() -1671 || self.inner.side().is_server() -1672 { -1673 Ok(()) -1674 } else { -1675 Err(()) -1676 } -1677 } -1678} -1679 -1680impl Drop for State { -1681 fn drop(&mut self) { -1682 if !self.inner.is_drained() { -1683 // Ensure the endpoint can tidy up -1684 let _ = self -1685 .endpoint_events -1686 .send((self.handle, proto::EndpointEvent::drained())); -1687 } -1688 -1689 if !self.on_closed.is_empty() { -1690 // Ensure that all on_closed oneshot senders are triggered before dropping. -1691 let reason = self.error.as_ref().expect("closed without error reason"); -1692 let stats = self.inner.stats(); -1693 for tx in self.on_closed.drain(..) { -1694 tx.send((reason.clone(), stats.clone())).ok(); -1695 } -1696 } -1697 } -1698} -1699 -1700impl fmt::Debug for State { -1701 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { -1702 f.debug_struct("State").field("inner", &self.inner).finish() -1703 } -1704} -1705 -1706fn wake_stream(stream_id: StreamId, wakers: &mut FxHashMap<StreamId, Waker>) { -1707 if let Some(waker) = wakers.remove(&stream_id) { -1708 waker.wake(); -1709 } -1710} -1711 -1712fn wake_all(wakers: &mut FxHashMap<StreamId, Waker>) { -1713 wakers.drain().for_each(|(_, waker)| waker.wake()) -1714} -1715 -1716fn wake_stream_notify(stream_id: StreamId, wakers: &mut FxHashMap<StreamId, Arc<Notify>>) { -1717 if let Some(notify) = wakers.remove(&stream_id) { -1718 notify.notify_waiters() -1719 } -1720} -1721 -1722fn wake_all_notify(wakers: &mut FxHashMap<StreamId, Arc<Notify>>) { -1723 wakers -1724 .drain() -1725 .for_each(|(_, notify)| notify.notify_waiters()) -1726} -1727 -1728/// Errors that can arise when sending a datagram -1729#[derive(Debug, Error, Clone, Eq, PartialEq)] -1730pub enum SendDatagramError { -1731 /// The peer does not support receiving datagram frames -1732 #[error("datagrams not supported by peer")] -1733 UnsupportedByPeer, -1734 /// Datagram support is disabled locally -1735 #[error("datagram support disabled")] -1736 Disabled, -1737 /// The datagram is larger than the connection can currently accommodate -1738 /// -1739 /// Indicates that the path MTU minus overhead or the limit advertised by the peer has been -1740 /// exceeded. -1741 #[error("datagram too large")] -1742 TooLarge, -1743 /// The connection was lost -1744 #[error("connection lost")] -1745 ConnectionLost(#[from] ConnectionError), -1746} -1747 -1748/// The maximum amount of datagrams which will be produced in a single `drive_transmit` call -1749/// -1750/// This limits the amount of CPU resources consumed by datagram generation, -1751/// and allows other tasks (like receiving ACKs) to run in between. -1752const MAX_TRANSMIT_DATAGRAMS: usize = 20; -1753 -1754/// The maximum amount of datagrams that are sent in a single transmit -1755/// -1756/// This can be lower than the maximum platform capabilities, to avoid excessive -1757/// memory allocations when calling `poll_transmit()`. Benchmarks have shown -1758/// that numbers around 10 are a good compromise. -1759const MAX_TRANSMIT_SEGMENTS: NonZeroUsize = NonZeroUsize::new(10).expect("known");

      \ No newline at end of file +1225#[allow(clippy::redundant_allocation)] +1226pub(crate) struct ConnectionRef(Arc<Arc<ConnectionInner>>); +1227 +1228impl ConnectionRef { +1229 #[allow(clippy::redundant_allocation)] +1230 fn from_arc(inner: Arc<Arc<ConnectionInner>>) -> Self { +1231 inner.state.lock("from_arc").ref_count += 1; +1232 Self(inner) +1233 } +1234 +1235 fn stable_id(&self) -> usize { +1236 &*self.0 as *const _ as usize +1237 } +1238} +1239 +1240impl Clone for ConnectionRef { +1241 fn clone(&self) -> Self { +1242 Self::from_arc(Arc::clone(&self.0)) +1243 } +1244} +1245 +1246impl Drop for ConnectionRef { +1247 fn drop(&mut self) { +1248 let conn = &mut *self.state.lock("drop"); +1249 if let Some(x) = conn.ref_count.checked_sub(1) { +1250 conn.ref_count = x; +1251 if x == 0 && !conn.inner.is_closed() { +1252 // If the driver is alive, it's just it and us, so we'd better shut it down. If it's +1253 // not, we can't do any harm. If there were any streams being opened, then either +1254 // the connection will be closed for an unrelated reason or a fresh reference will +1255 // be constructed for the newly opened stream. +1256 conn.implicit_close(&self.shared); +1257 } +1258 } +1259 } +1260} +1261 +1262impl std::ops::Deref for ConnectionRef { +1263 type Target = ConnectionInner; +1264 fn deref(&self) -> &Self::Target { +1265 &self.0 +1266 } +1267} +1268 +1269#[derive(Debug)] +1270pub(crate) struct ConnectionInner { +1271 pub(crate) state: Mutex<State>, +1272 pub(crate) shared: Shared, +1273} +1274 +1275/// A handle to some connection internals, use with care. +1276/// +1277/// This contains a weak reference to the connection so will not itself keep the connection +1278/// alive. +1279#[derive(Debug, Clone)] +1280pub struct WeakConnectionHandle(Weak<Arc<ConnectionInner>>); +1281 +1282impl WeakConnectionHandle { +1283 /// Returns `true` if the [`Connection`] associated with this handle is still alive. +1284 pub fn is_alive(&self) -> bool { +1285 self.0.upgrade().is_some() +1286 } +1287 +1288 /// Upgrade the handle to a full `Connection` +1289 pub fn upgrade(&self) -> Option<Connection> { +1290 self.0 +1291 .upgrade() +1292 .map(|inner| Connection(ConnectionRef::from_arc(inner))) +1293 } +1294} +1295 +1296#[derive(Debug, Default)] +1297pub(crate) struct Shared { +1298 handshake_confirmed: Notify, +1299 /// Notified when new streams may be locally initiated due to an increase in stream ID flow +1300 /// control budget +1301 stream_budget_available: [Notify; 2], +1302 /// Notified when the peer has initiated a new stream +1303 stream_incoming: [Notify; 2], +1304 datagram_received: Notify, +1305 datagrams_unblocked: Notify, +1306 closed: Notify, +1307} +1308 +1309pub(crate) struct State { +1310 pub(crate) inner: proto::Connection, +1311 driver: Option<Waker>, +1312 handle: ConnectionHandle, +1313 on_handshake_data: Option<oneshot::Sender<()>>, +1314 on_connected: Option<oneshot::Sender<bool>>, +1315 connected: bool, +1316 handshake_confirmed: bool, +1317 timer: Option<Pin<Box<dyn AsyncTimer>>>, +1318 timer_deadline: Option<Instant>, +1319 conn_events: mpsc::UnboundedReceiver<ConnectionEvent>, +1320 endpoint_events: mpsc::UnboundedSender<(ConnectionHandle, EndpointEvent)>, +1321 pub(crate) blocked_writers: FxHashMap<StreamId, Waker>, +1322 pub(crate) blocked_readers: FxHashMap<StreamId, Waker>, +1323 pub(crate) stopped: FxHashMap<StreamId, Arc<Notify>>, +1324 /// Always set to Some before the connection becomes drained +1325 pub(crate) error: Option<ConnectionError>, +1326 /// Tracks paths being opened +1327 open_path: FxHashMap<PathId, watch::Sender<Result<(), PathError>>>, +1328 /// Tracks paths being closed +1329 pub(crate) close_path: FxHashMap<PathId, oneshot::Sender<VarInt>>, +1330 pub(crate) path_events: tokio::sync::broadcast::Sender<PathEvent>, +1331 /// Number of live handles that can be used to initiate or handle I/O; excludes the driver +1332 ref_count: usize, +1333 sender: Pin<Box<dyn UdpSender>>, +1334 pub(crate) runtime: Arc<dyn Runtime>, +1335 send_buffer: Vec<u8>, +1336 /// We buffer a transmit when the underlying I/O would block +1337 buffered_transmit: Option<proto::Transmit>, +1338 /// Our last external address reported by the peer. When multipath is enabled, this will be the +1339 /// last report across all paths. +1340 pub(crate) observed_external_addr: watch::Sender<Option<SocketAddr>>, +1341 pub(crate) nat_traversal_updates: tokio::sync::broadcast::Sender<iroh_hp::Event>, +1342 on_closed: Vec<oneshot::Sender<(ConnectionError, ConnectionStats)>>, +1343} +1344 +1345impl State { +1346 #[allow(clippy::too_many_arguments)] +1347 fn new( +1348 inner: proto::Connection, +1349 handle: ConnectionHandle, +1350 endpoint_events: mpsc::UnboundedSender<(ConnectionHandle, EndpointEvent)>, +1351 conn_events: mpsc::UnboundedReceiver<ConnectionEvent>, +1352 on_handshake_data: oneshot::Sender<()>, +1353 on_connected: oneshot::Sender<bool>, +1354 sender: Pin<Box<dyn UdpSender>>, +1355 runtime: Arc<dyn Runtime>, +1356 ) -> Self { +1357 Self { +1358 inner, +1359 driver: None, +1360 handle, +1361 on_handshake_data: Some(on_handshake_data), +1362 on_connected: Some(on_connected), +1363 connected: false, +1364 handshake_confirmed: false, +1365 timer: None, +1366 timer_deadline: None, +1367 conn_events, +1368 endpoint_events, +1369 blocked_writers: FxHashMap::default(), +1370 blocked_readers: FxHashMap::default(), +1371 stopped: FxHashMap::default(), +1372 open_path: FxHashMap::default(), +1373 close_path: FxHashMap::default(), +1374 error: None, +1375 ref_count: 0, +1376 sender, +1377 runtime, +1378 send_buffer: Vec::new(), +1379 buffered_transmit: None, +1380 path_events: tokio::sync::broadcast::channel(32).0, +1381 observed_external_addr: watch::Sender::new(None), +1382 nat_traversal_updates: tokio::sync::broadcast::channel(32).0, +1383 on_closed: Vec::new(), +1384 } +1385 } +1386 +1387 fn drive_transmit(&mut self, cx: &mut Context) -> io::Result<bool> { +1388 let now = self.runtime.now(); +1389 let mut transmits = 0; +1390 +1391 let max_datagrams = self +1392 .sender +1393 .max_transmit_segments() +1394 .min(MAX_TRANSMIT_SEGMENTS); +1395 +1396 loop { +1397 // Retry the last transmit, or get a new one. +1398 let t = match self.buffered_transmit.take() { +1399 Some(t) => t, +1400 None => { +1401 self.send_buffer.clear(); +1402 match self +1403 .inner +1404 .poll_transmit(now, max_datagrams, &mut self.send_buffer) +1405 { +1406 Some(t) => { +1407 transmits += match t.segment_size { +1408 None => 1, +1409 Some(s) => t.size.div_ceil(s), // round up +1410 }; +1411 t +1412 } +1413 None => break, +1414 } +1415 } +1416 }; +1417 +1418 let len = t.size; +1419 match self +1420 .sender +1421 .as_mut() +1422 .poll_send(&udp_transmit(&t, &self.send_buffer[..len]), cx) +1423 { +1424 Poll::Pending => { +1425 self.buffered_transmit = Some(t); +1426 return Ok(false); +1427 } +1428 Poll::Ready(Err(e)) => return Err(e), +1429 Poll::Ready(Ok(())) => {} +1430 } +1431 +1432 if transmits >= MAX_TRANSMIT_DATAGRAMS { +1433 // TODO: What isn't ideal here yet is that if we don't poll all +1434 // datagrams that could be sent we don't go into the `app_limited` +1435 // state and CWND continues to grow until we get here the next time. +1436 // See https://github.com/quinn-rs/quinn/issues/1126 +1437 return Ok(true); +1438 } +1439 } +1440 +1441 Ok(false) +1442 } +1443 +1444 fn forward_endpoint_events(&mut self) { +1445 while let Some(event) = self.inner.poll_endpoint_events() { +1446 // If the endpoint driver is gone, noop. +1447 let _ = self.endpoint_events.send((self.handle, event)); +1448 } +1449 } +1450 +1451 /// If this returns `Err`, the endpoint is dead, so the driver should exit immediately. +1452 fn process_conn_events( +1453 &mut self, +1454 shared: &Shared, +1455 cx: &mut Context, +1456 ) -> Result<(), ConnectionError> { +1457 loop { +1458 match self.conn_events.poll_recv(cx) { +1459 Poll::Ready(Some(ConnectionEvent::Rebind(sender))) => { +1460 self.sender = sender; +1461 self.inner.local_address_changed(); +1462 } +1463 Poll::Ready(Some(ConnectionEvent::Proto(event))) => { +1464 self.inner.handle_event(event); +1465 } +1466 Poll::Ready(Some(ConnectionEvent::Close { reason, error_code })) => { +1467 self.close(error_code, reason, shared); +1468 } +1469 Poll::Ready(None) => { +1470 return Err(ConnectionError::TransportError(TransportError::new( +1471 TransportErrorCode::INTERNAL_ERROR, +1472 "endpoint driver future was dropped".to_string(), +1473 ))); +1474 } +1475 Poll::Pending => { +1476 return Ok(()); +1477 } +1478 } +1479 } +1480 } +1481 +1482 fn forward_app_events(&mut self, shared: &Shared) { +1483 while let Some(event) = self.inner.poll() { +1484 use proto::Event::*; +1485 match event { +1486 HandshakeDataReady => { +1487 if let Some(x) = self.on_handshake_data.take() { +1488 let _ = x.send(()); +1489 } +1490 } +1491 Connected => { +1492 self.connected = true; +1493 if let Some(x) = self.on_connected.take() { +1494 // We don't care if the on-connected future was dropped +1495 let _ = x.send(self.inner.accepted_0rtt()); +1496 } +1497 if self.inner.side().is_client() && !self.inner.accepted_0rtt() { +1498 // Wake up rejected 0-RTT streams so they can fail immediately with +1499 // `ZeroRttRejected` errors. +1500 wake_all(&mut self.blocked_writers); +1501 wake_all(&mut self.blocked_readers); +1502 wake_all_notify(&mut self.stopped); +1503 } +1504 } +1505 HandshakeConfirmed => { +1506 self.handshake_confirmed = true; +1507 shared.handshake_confirmed.notify_waiters(); +1508 } +1509 ConnectionLost { reason } => { +1510 self.terminate(reason, shared); +1511 } +1512 Stream(StreamEvent::Writable { id }) => wake_stream(id, &mut self.blocked_writers), +1513 Stream(StreamEvent::Opened { dir: Dir::Uni }) => { +1514 shared.stream_incoming[Dir::Uni as usize].notify_waiters(); +1515 } +1516 Stream(StreamEvent::Opened { dir: Dir::Bi }) => { +1517 shared.stream_incoming[Dir::Bi as usize].notify_waiters(); +1518 } +1519 DatagramReceived => { +1520 shared.datagram_received.notify_waiters(); +1521 } +1522 DatagramsUnblocked => { +1523 shared.datagrams_unblocked.notify_waiters(); +1524 } +1525 Stream(StreamEvent::Readable { id }) => wake_stream(id, &mut self.blocked_readers), +1526 Stream(StreamEvent::Available { dir }) => { +1527 // Might mean any number of streams are ready, so we wake up everyone +1528 shared.stream_budget_available[dir as usize].notify_waiters(); +1529 } +1530 Stream(StreamEvent::Finished { id }) => wake_stream_notify(id, &mut self.stopped), +1531 Stream(StreamEvent::Stopped { id, .. }) => { +1532 wake_stream_notify(id, &mut self.stopped); +1533 wake_stream(id, &mut self.blocked_writers); +1534 } +1535 Path(ref evt @ PathEvent::ObservedAddr { addr: observed, .. }) => { +1536 self.path_events.send(evt.clone()).ok(); +1537 self.observed_external_addr.send_if_modified(|addr| { +1538 let old = addr.replace(observed); +1539 old != *addr +1540 }); +1541 } +1542 Path(ref evt @ PathEvent::Opened { id }) => { +1543 self.path_events.send(evt.clone()).ok(); +1544 if let Some(sender) = self.open_path.remove(&id) { +1545 sender.send_modify(|value| *value = Ok(())); +1546 } +1547 } +1548 Path(ref evt @ PathEvent::Closed { id, error_code }) => { +1549 self.path_events.send(evt.clone()).ok(); +1550 if let Some(sender) = self.close_path.remove(&id) { +1551 let _ = sender.send(error_code); +1552 } +1553 } +1554 Path(evt @ PathEvent::Abandoned { .. }) => { +1555 self.path_events.send(evt).ok(); +1556 } +1557 Path(ref evt @ PathEvent::LocallyClosed { id, error }) => { +1558 self.path_events.send(evt.clone()).ok(); +1559 if let Some(sender) = self.open_path.remove(&id) { +1560 sender.send_modify(|value| *value = Err(error)); +1561 } +1562 // this will happen also for already opened paths +1563 } +1564 Path(evt @ PathEvent::RemoteStatus { .. }) => { +1565 self.path_events.send(evt).ok(); +1566 } +1567 NatTraversal(update) => { +1568 self.nat_traversal_updates.send(update).ok(); +1569 } +1570 } +1571 } +1572 } +1573 +1574 fn drive_timer(&mut self, cx: &mut Context) -> bool { +1575 // Check whether we need to (re)set the timer. If so, we must poll again to ensure the +1576 // timer is registered with the runtime (and check whether it's already +1577 // expired). +1578 match self.inner.poll_timeout() { +1579 Some(deadline) => { +1580 if let Some(delay) = &mut self.timer { +1581 // There is no need to reset the tokio timer if the deadline +1582 // did not change +1583 if self +1584 .timer_deadline +1585 .map(|current_deadline| current_deadline != deadline) +1586 .unwrap_or(true) +1587 { +1588 delay.as_mut().reset(deadline); +1589 } +1590 } else { +1591 self.timer = Some(self.runtime.new_timer(deadline)); +1592 } +1593 // Store the actual expiration time of the timer +1594 self.timer_deadline = Some(deadline); +1595 } +1596 None => { +1597 self.timer_deadline = None; +1598 return false; +1599 } +1600 } +1601 +1602 if self.timer_deadline.is_none() { +1603 return false; +1604 } +1605 +1606 let delay = self +1607 .timer +1608 .as_mut() +1609 .expect("timer must exist in this state") +1610 .as_mut(); +1611 if delay.poll(cx).is_pending() { +1612 // Since there wasn't a timeout event, there is nothing new +1613 // for the connection to do +1614 return false; +1615 } +1616 +1617 // A timer expired, so the caller needs to check for +1618 // new transmits, which might cause new timers to be set. +1619 self.inner.handle_timeout(self.runtime.now()); +1620 self.timer_deadline = None; +1621 true +1622 } +1623 +1624 /// Wake up a blocked `Driver` task to process I/O +1625 pub(crate) fn wake(&mut self) { +1626 if let Some(x) = self.driver.take() { +1627 x.wake(); +1628 } +1629 } +1630 +1631 /// Used to wake up all blocked futures when the connection becomes closed for any reason +1632 fn terminate(&mut self, reason: ConnectionError, shared: &Shared) { +1633 self.error = Some(reason.clone()); +1634 if let Some(x) = self.on_handshake_data.take() { +1635 let _ = x.send(()); +1636 } +1637 wake_all(&mut self.blocked_writers); +1638 wake_all(&mut self.blocked_readers); +1639 shared.stream_budget_available[Dir::Uni as usize].notify_waiters(); +1640 shared.stream_budget_available[Dir::Bi as usize].notify_waiters(); +1641 shared.stream_incoming[Dir::Uni as usize].notify_waiters(); +1642 shared.stream_incoming[Dir::Bi as usize].notify_waiters(); +1643 shared.datagram_received.notify_waiters(); +1644 shared.datagrams_unblocked.notify_waiters(); +1645 if let Some(x) = self.on_connected.take() { +1646 let _ = x.send(false); +1647 } +1648 shared.handshake_confirmed.notify_waiters(); +1649 wake_all_notify(&mut self.stopped); +1650 shared.closed.notify_waiters(); +1651 +1652 // Send to the registered on_closed futures. +1653 let stats = self.inner.stats(); +1654 for tx in self.on_closed.drain(..) { +1655 tx.send((reason.clone(), stats.clone())).ok(); +1656 } +1657 } +1658 +1659 fn close(&mut self, error_code: VarInt, reason: Bytes, shared: &Shared) { +1660 self.inner.close(self.runtime.now(), error_code, reason); +1661 self.terminate(ConnectionError::LocallyClosed, shared); +1662 self.wake(); +1663 } +1664 +1665 /// Close for a reason other than the application's explicit request +1666 pub(crate) fn implicit_close(&mut self, shared: &Shared) { +1667 self.close(0u32.into(), Bytes::new(), shared); +1668 } +1669 +1670 pub(crate) fn check_0rtt(&self) -> Result<(), ()> { +1671 if self.inner.is_handshaking() +1672 || self.inner.accepted_0rtt() +1673 || self.inner.side().is_server() +1674 { +1675 Ok(()) +1676 } else { +1677 Err(()) +1678 } +1679 } +1680} +1681 +1682impl Drop for State { +1683 fn drop(&mut self) { +1684 if !self.inner.is_drained() { +1685 // Ensure the endpoint can tidy up +1686 let _ = self +1687 .endpoint_events +1688 .send((self.handle, proto::EndpointEvent::drained())); +1689 } +1690 +1691 if !self.on_closed.is_empty() { +1692 // Ensure that all on_closed oneshot senders are triggered before dropping. +1693 let reason = self.error.as_ref().expect("closed without error reason"); +1694 let stats = self.inner.stats(); +1695 for tx in self.on_closed.drain(..) { +1696 tx.send((reason.clone(), stats.clone())).ok(); +1697 } +1698 } +1699 } +1700} +1701 +1702impl fmt::Debug for State { +1703 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +1704 f.debug_struct("State").field("inner", &self.inner).finish() +1705 } +1706} +1707 +1708fn wake_stream(stream_id: StreamId, wakers: &mut FxHashMap<StreamId, Waker>) { +1709 if let Some(waker) = wakers.remove(&stream_id) { +1710 waker.wake(); +1711 } +1712} +1713 +1714fn wake_all(wakers: &mut FxHashMap<StreamId, Waker>) { +1715 wakers.drain().for_each(|(_, waker)| waker.wake()) +1716} +1717 +1718fn wake_stream_notify(stream_id: StreamId, wakers: &mut FxHashMap<StreamId, Arc<Notify>>) { +1719 if let Some(notify) = wakers.remove(&stream_id) { +1720 notify.notify_waiters() +1721 } +1722} +1723 +1724fn wake_all_notify(wakers: &mut FxHashMap<StreamId, Arc<Notify>>) { +1725 wakers +1726 .drain() +1727 .for_each(|(_, notify)| notify.notify_waiters()) +1728} +1729 +1730/// Errors that can arise when sending a datagram +1731#[derive(Debug, Error, Clone, Eq, PartialEq)] +1732pub enum SendDatagramError { +1733 /// The peer does not support receiving datagram frames +1734 #[error("datagrams not supported by peer")] +1735 UnsupportedByPeer, +1736 /// Datagram support is disabled locally +1737 #[error("datagram support disabled")] +1738 Disabled, +1739 /// The datagram is larger than the connection can currently accommodate +1740 /// +1741 /// Indicates that the path MTU minus overhead or the limit advertised by the peer has been +1742 /// exceeded. +1743 #[error("datagram too large")] +1744 TooLarge, +1745 /// The connection was lost +1746 #[error("connection lost")] +1747 ConnectionLost(#[from] ConnectionError), +1748} +1749 +1750/// The maximum amount of datagrams which will be produced in a single `drive_transmit` call +1751/// +1752/// This limits the amount of CPU resources consumed by datagram generation, +1753/// and allows other tasks (like receiving ACKs) to run in between. +1754const MAX_TRANSMIT_DATAGRAMS: usize = 20; +1755 +1756/// The maximum amount of datagrams that are sent in a single transmit +1757/// +1758/// This can be lower than the maximum platform capabilities, to avoid excessive +1759/// memory allocations when calling `poll_transmit()`. Benchmarks have shown +1760/// that numbers around 10 are a good compromise. +1761const MAX_TRANSMIT_SEGMENTS: NonZeroUsize = NonZeroUsize::new(10).expect("known");
      \ No newline at end of file diff --git a/pr/255/docs/src/iroh_quinn_proto/connection/send_buffer.rs.html b/pr/255/docs/src/iroh_quinn_proto/connection/send_buffer.rs.html index 3261a3202..d5f3a5762 100644 --- a/pr/255/docs/src/iroh_quinn_proto/connection/send_buffer.rs.html +++ b/pr/255/docs/src/iroh_quinn_proto/connection/send_buffer.rs.html @@ -2,7 +2,7 @@ 2 3use bytes::{Buf, BufMut, Bytes, BytesMut}; 4 -5use crate::{VarInt, range_set::ArrayRangeSet}; +5use crate::{VarInt, connection::streams::BytesOrSlice, range_set::ArrayRangeSet}; 6 7/// Buffer of outgoing retransmittable stream data 8#[derive(Default, Debug)] @@ -67,686 +67,696 @@ 67 } 68 69 /// Append data to the end of the buffer -70 fn append(&mut self, data: Bytes) { +70 fn append<'a>(&'a mut self, data: impl BytesOrSlice<'a>) { 71 self.len += data.len(); 72 if data.len() > MAX_COMBINE { 73 // use in place 74 if !self.last_segment.is_empty() { 75 self.segments.push_back(self.last_segment.split().freeze()); 76 } -77 self.segments.push_back(data); +77 self.segments.push_back(data.into_bytes()); 78 } else { 79 // copy -80 if self.last_segment.len() + data.len() > MAX_COMBINE && !self.last_segment.is_empty() { -81 self.segments.push_back(self.last_segment.split().freeze()); -82 } -83 self.last_segment.extend_from_slice(&data); -84 } -85 } -86 -87 /// Discard data from the front of the buffer -88 /// -89 /// Calling this with n > len() is allowed and will simply clear the buffer. -90 fn pop_front(&mut self, n: usize) { -91 let mut n = n.min(self.len); -92 self.len -= n; -93 self.offset += n as u64; -94 while n > 0 { -95 // segments is empty, which leaves only last_segment -96 let Some(front) = self.segments.front_mut() else { -97 break; -98 }; -99 if front.len() <= n { -100 // Remove the whole front segment -101 n -= front.len(); -102 self.segments.pop_front(); -103 } else { -104 // Advance within the front segment -105 front.advance(n); -106 n = 0; -107 } -108 } -109 // the rest has to be in the last segment -110 self.last_segment.advance(n); -111 // shrink segments if we have a lot of unused capacity -112 if self.segments.len() * 4 < self.segments.capacity() { -113 self.segments.shrink_to_fit(); -114 } -115 } -116 -117 /// Iterator over all segments in order -118 /// -119 /// Concatenates `segments` and `last_segment` so they can be handled uniformly -120 fn segments_iter(&self) -> impl Iterator<Item = &[u8]> { -121 self.segments -122 .iter() -123 .map(|x| x.as_ref()) -124 .chain(std::iter::once(self.last_segment.as_ref())) +80 let rest = if self.last_segment.len() + data.len() > MAX_COMBINE +81 && !self.last_segment.is_empty() +82 { +83 // fill up last_segment up to MAX_COMBINE and flush +84 let capacity = MAX_COMBINE.saturating_sub(self.last_segment.len()); +85 let (curr, rest) = data.as_ref().split_at(capacity); +86 self.last_segment.put_slice(curr); +87 self.segments.push_back(self.last_segment.split().freeze()); +88 rest +89 } else { +90 data.as_ref() +91 }; +92 // copy the rest into the now empty last_segment +93 self.last_segment.extend_from_slice(rest); +94 } +95 } +96 +97 /// Discard data from the front of the buffer +98 /// +99 /// Calling this with n > len() is allowed and will simply clear the buffer. +100 fn pop_front(&mut self, n: usize) { +101 let mut n = n.min(self.len); +102 self.len -= n; +103 self.offset += n as u64; +104 while n > 0 { +105 // segments is empty, which leaves only last_segment +106 let Some(front) = self.segments.front_mut() else { +107 break; +108 }; +109 if front.len() <= n { +110 // Remove the whole front segment +111 n -= front.len(); +112 self.segments.pop_front(); +113 } else { +114 // Advance within the front segment +115 front.advance(n); +116 n = 0; +117 } +118 } +119 // the rest has to be in the last segment +120 self.last_segment.advance(n); +121 // shrink segments if we have a lot of unused capacity +122 if self.segments.len() * 4 < self.segments.capacity() { +123 self.segments.shrink_to_fit(); +124 } 125 } 126 -127 /// Returns data which is associated with a range +127 /// Iterator over all segments in order 128 /// -129 /// Requesting a range outside of the buffered data will panic. -130 #[cfg(any(test, feature = "bench"))] -131 fn get(&self, offsets: Range<u64>) -> &[u8] { -132 assert!( -133 offsets.start >= self.range().start && offsets.end <= self.range().end, -134 "Requested range is outside of buffered data" -135 ); -136 // translate to segment-relative offsets and usize -137 let offsets = Range { -138 start: (offsets.start - self.offset) as usize, -139 end: (offsets.end - self.offset) as usize, -140 }; -141 let mut segment_offset = 0; -142 for segment in self.segments_iter() { -143 if offsets.start >= segment_offset && offsets.start < segment_offset + segment.len() { -144 let start = offsets.start - segment_offset; -145 let end = offsets.end - segment_offset; -146 -147 return &segment[start..end.min(segment.len())]; -148 } -149 segment_offset += segment.len(); -150 } -151 -152 unreachable!("impossible if segments and range are consistent"); -153 } -154 -155 fn get_into(&self, offsets: Range<u64>, buf: &mut impl BufMut) { -156 assert!( -157 offsets.start >= self.range().start && offsets.end <= self.range().end, -158 "Requested range is outside of buffered data" -159 ); -160 // translate to segment-relative offsets and usize -161 let offsets = Range { -162 start: (offsets.start - self.offset) as usize, -163 end: (offsets.end - self.offset) as usize, -164 }; -165 let mut segment_offset = 0; -166 for segment in self.segments_iter() { -167 // intersect segment range with requested range -168 let start = segment_offset.max(offsets.start); -169 let end = (segment_offset + segment.len()).min(offsets.end); -170 if start < end { -171 // slice range intersects with requested range -172 buf.put_slice(&segment[start - segment_offset..end - segment_offset]); -173 } -174 segment_offset += segment.len(); -175 if segment_offset >= offsets.end { -176 // we are beyond the requested range -177 break; -178 } -179 } -180 } -181 -182 #[cfg(test)] -183 fn to_vec(&self) -> Vec<u8> { -184 let mut result = Vec::with_capacity(self.len); -185 for segment in self.segments_iter() { -186 result.extend_from_slice(segment); -187 } -188 result -189 } -190} +129 /// Concatenates `segments` and `last_segment` so they can be handled uniformly +130 fn segments_iter(&self) -> impl Iterator<Item = &[u8]> { +131 self.segments +132 .iter() +133 .map(|x| x.as_ref()) +134 .chain(std::iter::once(self.last_segment.as_ref())) +135 } +136 +137 /// Returns data which is associated with a range +138 /// +139 /// Requesting a range outside of the buffered data will panic. +140 #[cfg(any(test, feature = "bench"))] +141 fn get(&self, offsets: Range<u64>) -> &[u8] { +142 assert!( +143 offsets.start >= self.range().start && offsets.end <= self.range().end, +144 "Requested range is outside of buffered data" +145 ); +146 // translate to segment-relative offsets and usize +147 let offsets = Range { +148 start: (offsets.start - self.offset) as usize, +149 end: (offsets.end - self.offset) as usize, +150 }; +151 let mut segment_offset = 0; +152 for segment in self.segments_iter() { +153 if offsets.start >= segment_offset && offsets.start < segment_offset + segment.len() { +154 let start = offsets.start - segment_offset; +155 let end = offsets.end - segment_offset; +156 +157 return &segment[start..end.min(segment.len())]; +158 } +159 segment_offset += segment.len(); +160 } +161 +162 unreachable!("impossible if segments and range are consistent"); +163 } +164 +165 fn get_into(&self, offsets: Range<u64>, buf: &mut impl BufMut) { +166 assert!( +167 offsets.start >= self.range().start && offsets.end <= self.range().end, +168 "Requested range is outside of buffered data" +169 ); +170 // translate to segment-relative offsets and usize +171 let offsets = Range { +172 start: (offsets.start - self.offset) as usize, +173 end: (offsets.end - self.offset) as usize, +174 }; +175 let mut segment_offset = 0; +176 for segment in self.segments_iter() { +177 // intersect segment range with requested range +178 let start = segment_offset.max(offsets.start); +179 let end = (segment_offset + segment.len()).min(offsets.end); +180 if start < end { +181 // slice range intersects with requested range +182 buf.put_slice(&segment[start - segment_offset..end - segment_offset]); +183 } +184 segment_offset += segment.len(); +185 if segment_offset >= offsets.end { +186 // we are beyond the requested range +187 break; +188 } +189 } +190 } 191 -192impl SendBuffer { -193 /// Construct an empty buffer at the initial offset -194 pub(super) fn new() -> Self { -195 Self::default() -196 } -197 -198 /// Append application data to the end of the stream -199 pub(super) fn write(&mut self, data: Bytes) { -200 self.data.append(data); -201 } -202 -203 /// Discard a range of acknowledged stream data -204 pub(super) fn ack(&mut self, mut range: Range<u64>) { -205 // Clamp the range to data which is still tracked -206 let base_offset = self.fully_acked_offset(); -207 range.start = base_offset.max(range.start); -208 range.end = base_offset.max(range.end); -209 -210 self.acks.insert(range); -211 -212 while self.acks.min() == Some(self.fully_acked_offset()) { -213 let prefix = self.acks.pop_min().unwrap(); -214 let to_advance = (prefix.end - prefix.start) as usize; -215 self.data.pop_front(to_advance); -216 } -217 -218 // Remove retransmit ranges which have been acknowledged -219 // -220 // We have to do this since we have just dropped the data, and asking -221 // for non-present data would be an error. -222 self.retransmits.remove(0..self.fully_acked_offset()); -223 } -224 -225 /// Compute the next range to transmit on this stream and update state to account for that -226 /// transmission. -227 /// -228 /// `max_len` here includes the space which is available to transmit the -229 /// offset and length of the data to send. The caller has to guarantee that -230 /// there is at least enough space available to write maximum-sized metadata -231 /// (8 byte offset + 8 byte length). -232 /// -233 /// The method returns a tuple: -234 /// - The first return value indicates the range of data to send -235 /// - The second return value indicates whether the length needs to be encoded -236 /// in the STREAM frames metadata (`true`), or whether it can be omitted -237 /// since the selected range will fill the whole packet. -238 pub(super) fn poll_transmit(&mut self, mut max_len: usize) -> (Range<u64>, bool) { -239 debug_assert!(max_len >= 8 + 8); -240 let mut encode_length = false; -241 -242 if let Some(range) = self.retransmits.pop_min() { -243 // Retransmit sent data -244 -245 // When the offset is known, we know how many bytes are required to encode it. -246 // Offset 0 requires no space -247 if range.start != 0 { -248 max_len -= VarInt::size(unsafe { VarInt::from_u64_unchecked(range.start) }); -249 } -250 if range.end - range.start < max_len as u64 { -251 encode_length = true; -252 max_len -= 8; -253 } +192 #[cfg(test)] +193 fn to_vec(&self) -> Vec<u8> { +194 let mut result = Vec::with_capacity(self.len); +195 for segment in self.segments_iter() { +196 result.extend_from_slice(segment); +197 } +198 result +199 } +200} +201 +202impl SendBuffer { +203 /// Construct an empty buffer at the initial offset +204 pub(super) fn new() -> Self { +205 Self::default() +206 } +207 +208 /// Append application data to the end of the stream +209 pub(super) fn write<'a>(&'a mut self, data: impl BytesOrSlice<'a>) { +210 self.data.append(data); +211 } +212 +213 /// Discard a range of acknowledged stream data +214 pub(super) fn ack(&mut self, mut range: Range<u64>) { +215 // Clamp the range to data which is still tracked +216 let base_offset = self.fully_acked_offset(); +217 range.start = base_offset.max(range.start); +218 range.end = base_offset.max(range.end); +219 +220 self.acks.insert(range); +221 +222 while self.acks.min() == Some(self.fully_acked_offset()) { +223 let prefix = self.acks.pop_min().unwrap(); +224 let to_advance = (prefix.end - prefix.start) as usize; +225 self.data.pop_front(to_advance); +226 } +227 +228 // Remove retransmit ranges which have been acknowledged +229 // +230 // We have to do this since we have just dropped the data, and asking +231 // for non-present data would be an error. +232 self.retransmits.remove(0..self.fully_acked_offset()); +233 } +234 +235 /// Compute the next range to transmit on this stream and update state to account for that +236 /// transmission. +237 /// +238 /// `max_len` here includes the space which is available to transmit the +239 /// offset and length of the data to send. The caller has to guarantee that +240 /// there is at least enough space available to write maximum-sized metadata +241 /// (8 byte offset + 8 byte length). +242 /// +243 /// The method returns a tuple: +244 /// - The first return value indicates the range of data to send +245 /// - The second return value indicates whether the length needs to be encoded +246 /// in the STREAM frames metadata (`true`), or whether it can be omitted +247 /// since the selected range will fill the whole packet. +248 pub(super) fn poll_transmit(&mut self, mut max_len: usize) -> (Range<u64>, bool) { +249 debug_assert!(max_len >= 8 + 8); +250 let mut encode_length = false; +251 +252 if let Some(range) = self.retransmits.pop_min() { +253 // Retransmit sent data 254 -255 let end = range.end.min((max_len as u64).saturating_add(range.start)); -256 if end != range.end { -257 self.retransmits.insert(end..range.end); -258 } -259 return (range.start..end, encode_length); -260 } -261 -262 // Transmit new data -263 -264 // When the offset is known, we know how many bytes are required to encode it. -265 // Offset 0 requires no space -266 if self.unsent != 0 { -267 max_len -= VarInt::size(unsafe { VarInt::from_u64_unchecked(self.unsent) }); -268 } -269 if self.offset() - self.unsent < max_len as u64 { -270 encode_length = true; -271 max_len -= 8; -272 } +255 // When the offset is known, we know how many bytes are required to encode it. +256 // Offset 0 requires no space +257 if range.start != 0 { +258 max_len -= VarInt::size(unsafe { VarInt::from_u64_unchecked(range.start) }); +259 } +260 if range.end - range.start < max_len as u64 { +261 encode_length = true; +262 max_len -= 8; +263 } +264 +265 let end = range.end.min((max_len as u64).saturating_add(range.start)); +266 if end != range.end { +267 self.retransmits.insert(end..range.end); +268 } +269 return (range.start..end, encode_length); +270 } +271 +272 // Transmit new data 273 -274 let end = self -275 .offset() -276 .min((max_len as u64).saturating_add(self.unsent)); -277 let result = self.unsent..end; -278 self.unsent = end; -279 (result, encode_length) -280 } -281 -282 /// Returns data which is associated with a range -283 /// -284 /// This function can return a subset of the range, if the data is stored -285 /// in noncontiguous fashion in the send buffer. In this case callers -286 /// should call the function again with an incremented start offset to -287 /// retrieve more data. -288 #[cfg(any(test, feature = "bench"))] -289 pub(super) fn get(&self, offsets: Range<u64>) -> &[u8] { -290 self.data.get(offsets) -291 } -292 -293 pub(super) fn get_into(&self, offsets: Range<u64>, buf: &mut impl BufMut) { -294 self.data.get_into(offsets, buf) -295 } -296 -297 /// Queue a range of sent but unacknowledged data to be retransmitted -298 pub(super) fn retransmit(&mut self, mut range: Range<u64>) { -299 debug_assert!(range.end <= self.unsent, "unsent data can't be lost"); -300 // don't allow retransmitting data that has already been fully acknowledged, -301 // since we don't have it anymore. -302 // -303 // Note that we do allow retransmitting data that has been acknowledged -304 // for simplicity. Not doing so would require clipping the range against -305 // all acknowledged ranges. -306 range.start = range.start.max(self.fully_acked_offset()); -307 self.retransmits.insert(range); -308 } -309 -310 pub(super) fn retransmit_all_for_0rtt(&mut self) { -311 // check that we still got all data - we didn't get any acks. -312 debug_assert_eq!(self.fully_acked_offset(), 0); -313 self.unsent = 0; -314 } -315 -316 /// Offset up to which all data has been acknowledged -317 fn fully_acked_offset(&self) -> u64 { -318 self.data.range().start -319 } -320 -321 /// First stream offset unwritten by the application, i.e. the offset that the next write will -322 /// begin at -323 pub(super) fn offset(&self) -> u64 { -324 self.data.range().end -325 } -326 -327 /// Whether all sent data has been acknowledged -328 pub(super) fn is_fully_acked(&self) -> bool { -329 self.data.len() == 0 -330 } -331 -332 /// Whether there's data to send -333 /// -334 /// There may be sent unacknowledged data even when this is false. -335 pub(super) fn has_unsent_data(&self) -> bool { -336 self.unsent != self.offset() || !self.retransmits.is_empty() -337 } -338 -339 /// Compute the amount of data that hasn't been acknowledged -340 pub(super) fn unacked(&self) -> u64 { -341 self.data.len() as u64 - self.acks.iter().map(|x| x.end - x.start).sum::<u64>() -342 } -343} -344 -345#[cfg(test)] -346mod tests { -347 use super::*; +274 // When the offset is known, we know how many bytes are required to encode it. +275 // Offset 0 requires no space +276 if self.unsent != 0 { +277 max_len -= VarInt::size(unsafe { VarInt::from_u64_unchecked(self.unsent) }); +278 } +279 if self.offset() - self.unsent < max_len as u64 { +280 encode_length = true; +281 max_len -= 8; +282 } +283 +284 let end = self +285 .offset() +286 .min((max_len as u64).saturating_add(self.unsent)); +287 let result = self.unsent..end; +288 self.unsent = end; +289 (result, encode_length) +290 } +291 +292 /// Returns data which is associated with a range +293 /// +294 /// This function can return a subset of the range, if the data is stored +295 /// in noncontiguous fashion in the send buffer. In this case callers +296 /// should call the function again with an incremented start offset to +297 /// retrieve more data. +298 #[cfg(any(test, feature = "bench"))] +299 pub(super) fn get(&self, offsets: Range<u64>) -> &[u8] { +300 self.data.get(offsets) +301 } +302 +303 pub(super) fn get_into(&self, offsets: Range<u64>, buf: &mut impl BufMut) { +304 self.data.get_into(offsets, buf) +305 } +306 +307 /// Queue a range of sent but unacknowledged data to be retransmitted +308 pub(super) fn retransmit(&mut self, mut range: Range<u64>) { +309 debug_assert!(range.end <= self.unsent, "unsent data can't be lost"); +310 // don't allow retransmitting data that has already been fully acknowledged, +311 // since we don't have it anymore. +312 // +313 // Note that we do allow retransmitting data that has been acknowledged +314 // for simplicity. Not doing so would require clipping the range against +315 // all acknowledged ranges. +316 range.start = range.start.max(self.fully_acked_offset()); +317 self.retransmits.insert(range); +318 } +319 +320 pub(super) fn retransmit_all_for_0rtt(&mut self) { +321 // check that we still got all data - we didn't get any acks. +322 debug_assert_eq!(self.fully_acked_offset(), 0); +323 self.unsent = 0; +324 } +325 +326 /// Offset up to which all data has been acknowledged +327 fn fully_acked_offset(&self) -> u64 { +328 self.data.range().start +329 } +330 +331 /// First stream offset unwritten by the application, i.e. the offset that the next write will +332 /// begin at +333 pub(super) fn offset(&self) -> u64 { +334 self.data.range().end +335 } +336 +337 /// Whether all sent data has been acknowledged +338 pub(super) fn is_fully_acked(&self) -> bool { +339 self.data.len() == 0 +340 } +341 +342 /// Whether there's data to send +343 /// +344 /// There may be sent unacknowledged data even when this is false. +345 pub(super) fn has_unsent_data(&self) -> bool { +346 self.unsent != self.offset() || !self.retransmits.is_empty() +347 } 348 -349 #[test] -350 fn fragment_with_length() { -351 let mut buf = SendBuffer::new(); -352 const MSG: &[u8] = b"Hello, world!"; -353 buf.write(MSG.into()); -354 // 0 byte offset => 19 bytes left => 13 byte data isn't enough -355 // with 8 bytes reserved for length 11 payload bytes will fit -356 assert_eq!(buf.poll_transmit(19), (0..11, true)); -357 assert_eq!( -358 buf.poll_transmit(MSG.len() + 16 - 11), -359 (11..MSG.len() as u64, true) -360 ); -361 assert_eq!( -362 buf.poll_transmit(58), -363 (MSG.len() as u64..MSG.len() as u64, true) -364 ); -365 } -366 -367 #[test] -368 fn fragment_without_length() { -369 let mut buf = SendBuffer::new(); -370 const MSG: &[u8] = b"Hello, world with some extra data!"; -371 buf.write(MSG.into()); -372 // 0 byte offset => 19 bytes left => can be filled by 34 bytes payload -373 assert_eq!(buf.poll_transmit(19), (0..19, false)); -374 assert_eq!( -375 buf.poll_transmit(MSG.len() - 19 + 1), -376 (19..MSG.len() as u64, false) -377 ); -378 assert_eq!( -379 buf.poll_transmit(58), -380 (MSG.len() as u64..MSG.len() as u64, true) -381 ); -382 } -383 -384 #[test] -385 fn reserves_encoded_offset() { -386 let mut buf = SendBuffer::new(); -387 -388 // Pretend we have more than 1 GB of data in the buffer -389 let chunk: Bytes = Bytes::from_static(&[0; 1024 * 1024]); -390 for _ in 0..1025 { -391 buf.write(chunk.clone()); -392 } +349 /// Compute the amount of data that hasn't been acknowledged +350 pub(super) fn unacked(&self) -> u64 { +351 self.data.len() as u64 - self.acks.iter().map(|x| x.end - x.start).sum::<u64>() +352 } +353} +354 +355#[cfg(test)] +356mod tests { +357 use super::*; +358 +359 #[test] +360 fn fragment_with_length() { +361 let mut buf = SendBuffer::new(); +362 const MSG: &[u8] = b"Hello, world!"; +363 buf.write(MSG); +364 // 0 byte offset => 19 bytes left => 13 byte data isn't enough +365 // with 8 bytes reserved for length 11 payload bytes will fit +366 assert_eq!(buf.poll_transmit(19), (0..11, true)); +367 assert_eq!( +368 buf.poll_transmit(MSG.len() + 16 - 11), +369 (11..MSG.len() as u64, true) +370 ); +371 assert_eq!( +372 buf.poll_transmit(58), +373 (MSG.len() as u64..MSG.len() as u64, true) +374 ); +375 } +376 +377 #[test] +378 fn fragment_without_length() { +379 let mut buf = SendBuffer::new(); +380 const MSG: &[u8] = b"Hello, world with some extra data!"; +381 buf.write(MSG); +382 // 0 byte offset => 19 bytes left => can be filled by 34 bytes payload +383 assert_eq!(buf.poll_transmit(19), (0..19, false)); +384 assert_eq!( +385 buf.poll_transmit(MSG.len() - 19 + 1), +386 (19..MSG.len() as u64, false) +387 ); +388 assert_eq!( +389 buf.poll_transmit(58), +390 (MSG.len() as u64..MSG.len() as u64, true) +391 ); +392 } 393 -394 const SIZE1: u64 = 64; -395 const SIZE2: u64 = 16 * 1024; -396 const SIZE3: u64 = 1024 * 1024 * 1024; +394 #[test] +395 fn reserves_encoded_offset() { +396 let mut buf = SendBuffer::new(); 397 -398 // Offset 0 requires no space -399 assert_eq!(buf.poll_transmit(16), (0..16, false)); -400 buf.retransmit(0..16); -401 assert_eq!(buf.poll_transmit(16), (0..16, false)); -402 let mut transmitted = 16u64; +398 // Pretend we have more than 1 GB of data in the buffer +399 let chunk: Bytes = Bytes::from_static(&[0; 1024 * 1024]); +400 for _ in 0..1025 { +401 buf.write(chunk.clone()); +402 } 403 -404 // Offset 16 requires 1 byte -405 assert_eq!( -406 buf.poll_transmit((SIZE1 - transmitted + 1) as usize), -407 (transmitted..SIZE1, false) -408 ); -409 buf.retransmit(transmitted..SIZE1); -410 assert_eq!( -411 buf.poll_transmit((SIZE1 - transmitted + 1) as usize), -412 (transmitted..SIZE1, false) -413 ); -414 transmitted = SIZE1; -415 -416 // Offset 64 requires 2 bytes -417 assert_eq!( -418 buf.poll_transmit((SIZE2 - transmitted + 2) as usize), -419 (transmitted..SIZE2, false) -420 ); -421 buf.retransmit(transmitted..SIZE2); -422 assert_eq!( -423 buf.poll_transmit((SIZE2 - transmitted + 2) as usize), -424 (transmitted..SIZE2, false) -425 ); -426 transmitted = SIZE2; -427 -428 // Offset 16384 requires requires 4 bytes -429 assert_eq!( -430 buf.poll_transmit((SIZE3 - transmitted + 4) as usize), -431 (transmitted..SIZE3, false) -432 ); -433 buf.retransmit(transmitted..SIZE3); -434 assert_eq!( -435 buf.poll_transmit((SIZE3 - transmitted + 4) as usize), -436 (transmitted..SIZE3, false) -437 ); -438 transmitted = SIZE3; -439 -440 // Offset 1GB requires 8 bytes -441 assert_eq!( -442 buf.poll_transmit(chunk.len() + 8), -443 (transmitted..transmitted + chunk.len() as u64, false) -444 ); -445 buf.retransmit(transmitted..transmitted + chunk.len() as u64); -446 assert_eq!( -447 buf.poll_transmit(chunk.len() + 8), -448 (transmitted..transmitted + chunk.len() as u64, false) -449 ); -450 } -451 -452 /// tests that large segments are copied as-is in the SendBuffer -453 #[test] -454 fn multiple_large_segments() { -455 // this must be bigger than MAX_COMBINE so we don't get writes coalesced. -456 const N: usize = 2000; -457 const K: u64 = N as u64; -458 fn dup(data: &[u8]) -> Bytes { -459 let mut buf = BytesMut::with_capacity(data.len() * N); -460 for c in data { -461 for _ in 0..N { -462 buf.put_u8(*c); -463 } -464 } -465 buf.freeze() -466 } -467 -468 fn same(a: &[u8], b: &[u8]) -> bool { -469 // surprisingly, eq also checks the fat pointer metadata aka length -470 std::ptr::eq(a.as_ptr(), b.as_ptr()) -471 } -472 -473 let mut buf = SendBuffer::new(); -474 let msg: Bytes = dup(b"Hello, world!"); -475 let msg_len: u64 = msg.len() as u64; -476 -477 let seg1: Bytes = dup(b"He"); -478 buf.write(seg1.clone()); -479 let seg2: Bytes = dup(b"llo,"); -480 buf.write(seg2.clone()); -481 let seg3: Bytes = dup(b" w"); -482 buf.write(seg3.clone()); -483 let seg4: Bytes = dup(b"o"); -484 buf.write(seg4.clone()); -485 let seg5: Bytes = dup(b"rld!"); -486 buf.write(seg5.clone()); -487 assert_eq!(aggregate_unacked(&buf), msg); -488 // Check that the segments were stored as-is -489 assert!(same(buf.get(0..5 * K), &seg1)); -490 assert!(same(buf.get(2 * K..8 * K), &seg2)); -491 assert!(same(buf.get(6 * K..8 * K), &seg3)); -492 assert!(same(buf.get(8 * 2000..msg_len), &seg4)); -493 assert!(same(buf.get(9 * 2000..msg_len), &seg5)); -494 // Now drain the segments -495 buf.ack(0..K); -496 assert_eq!(aggregate_unacked(&buf), &msg[N..]); -497 buf.ack(0..3 * K); -498 assert_eq!(aggregate_unacked(&buf), &msg[3 * N..]); -499 buf.ack(3 * K..5 * K); -500 assert_eq!(aggregate_unacked(&buf), &msg[5 * N..]); -501 // ack with gap, doesn't free anything -502 buf.ack(7 * K..9 * K); -503 assert_eq!(aggregate_unacked(&buf), &msg[5 * N..]); -504 // fill the gap, free up to 9 K -505 buf.ack(4 * K..7 * K); -506 assert_eq!(aggregate_unacked(&buf), &msg[9 * N..]); -507 // ack all -508 buf.ack(0..msg_len); -509 assert_eq!(aggregate_unacked(&buf), &[] as &[u8]); -510 } -511 -512 #[test] -513 fn retransmit() { -514 let mut buf = SendBuffer::new(); -515 const MSG: &[u8] = b"Hello, world with extra data!"; -516 buf.write(MSG.into()); -517 // Transmit two frames -518 assert_eq!(buf.poll_transmit(16), (0..16, false)); -519 assert_eq!(buf.poll_transmit(16), (16..23, true)); -520 // Lose the first, but not the second -521 buf.retransmit(0..16); -522 // Ensure we only retransmit the lost frame, then continue sending fresh data -523 assert_eq!(buf.poll_transmit(16), (0..16, false)); -524 assert_eq!(buf.poll_transmit(16), (23..MSG.len() as u64, true)); -525 // Lose the second frame -526 buf.retransmit(16..23); -527 assert_eq!(buf.poll_transmit(16), (16..23, true)); -528 } -529 -530 #[test] -531 fn ack() { -532 let mut buf = SendBuffer::new(); -533 const MSG: &[u8] = b"Hello, world!"; -534 buf.write(MSG.into()); -535 assert_eq!(buf.poll_transmit(16), (0..8, true)); -536 buf.ack(0..8); -537 assert_eq!(aggregate_unacked(&buf), &MSG[8..]); +404 const SIZE1: u64 = 64; +405 const SIZE2: u64 = 16 * 1024; +406 const SIZE3: u64 = 1024 * 1024 * 1024; +407 +408 // Offset 0 requires no space +409 assert_eq!(buf.poll_transmit(16), (0..16, false)); +410 buf.retransmit(0..16); +411 assert_eq!(buf.poll_transmit(16), (0..16, false)); +412 let mut transmitted = 16u64; +413 +414 // Offset 16 requires 1 byte +415 assert_eq!( +416 buf.poll_transmit((SIZE1 - transmitted + 1) as usize), +417 (transmitted..SIZE1, false) +418 ); +419 buf.retransmit(transmitted..SIZE1); +420 assert_eq!( +421 buf.poll_transmit((SIZE1 - transmitted + 1) as usize), +422 (transmitted..SIZE1, false) +423 ); +424 transmitted = SIZE1; +425 +426 // Offset 64 requires 2 bytes +427 assert_eq!( +428 buf.poll_transmit((SIZE2 - transmitted + 2) as usize), +429 (transmitted..SIZE2, false) +430 ); +431 buf.retransmit(transmitted..SIZE2); +432 assert_eq!( +433 buf.poll_transmit((SIZE2 - transmitted + 2) as usize), +434 (transmitted..SIZE2, false) +435 ); +436 transmitted = SIZE2; +437 +438 // Offset 16384 requires requires 4 bytes +439 assert_eq!( +440 buf.poll_transmit((SIZE3 - transmitted + 4) as usize), +441 (transmitted..SIZE3, false) +442 ); +443 buf.retransmit(transmitted..SIZE3); +444 assert_eq!( +445 buf.poll_transmit((SIZE3 - transmitted + 4) as usize), +446 (transmitted..SIZE3, false) +447 ); +448 transmitted = SIZE3; +449 +450 // Offset 1GB requires 8 bytes +451 assert_eq!( +452 buf.poll_transmit(chunk.len() + 8), +453 (transmitted..transmitted + chunk.len() as u64, false) +454 ); +455 buf.retransmit(transmitted..transmitted + chunk.len() as u64); +456 assert_eq!( +457 buf.poll_transmit(chunk.len() + 8), +458 (transmitted..transmitted + chunk.len() as u64, false) +459 ); +460 } +461 +462 /// tests that large segments are copied as-is in the SendBuffer +463 #[test] +464 fn multiple_large_segments() { +465 // this must be bigger than MAX_COMBINE so we don't get writes coalesced. +466 const N: usize = 2000; +467 const K: u64 = N as u64; +468 fn dup(data: &[u8]) -> Bytes { +469 let mut buf = BytesMut::with_capacity(data.len() * N); +470 for c in data { +471 for _ in 0..N { +472 buf.put_u8(*c); +473 } +474 } +475 buf.freeze() +476 } +477 +478 fn same(a: &[u8], b: &[u8]) -> bool { +479 // surprisingly, eq also checks the fat pointer metadata aka length +480 std::ptr::eq(a.as_ptr(), b.as_ptr()) +481 } +482 +483 let mut buf = SendBuffer::new(); +484 let msg: Bytes = dup(b"Hello, world!"); +485 let msg_len: u64 = msg.len() as u64; +486 +487 let seg1: Bytes = dup(b"He"); +488 buf.write(seg1.clone()); +489 let seg2: Bytes = dup(b"llo,"); +490 buf.write(seg2.clone()); +491 let seg3: Bytes = dup(b" w"); +492 buf.write(seg3.clone()); +493 let seg4: Bytes = dup(b"o"); +494 buf.write(seg4.clone()); +495 let seg5: Bytes = dup(b"rld!"); +496 buf.write(seg5.clone()); +497 assert_eq!(aggregate_unacked(&buf), msg); +498 // Check that the segments were stored as-is +499 assert!(same(buf.get(0..5 * K), &seg1)); +500 assert!(same(buf.get(2 * K..8 * K), &seg2)); +501 assert!(same(buf.get(6 * K..8 * K), &seg3)); +502 assert!(same(buf.get(8 * 2000..msg_len), &seg4)); +503 assert!(same(buf.get(9 * 2000..msg_len), &seg5)); +504 // Now drain the segments +505 buf.ack(0..K); +506 assert_eq!(aggregate_unacked(&buf), &msg[N..]); +507 buf.ack(0..3 * K); +508 assert_eq!(aggregate_unacked(&buf), &msg[3 * N..]); +509 buf.ack(3 * K..5 * K); +510 assert_eq!(aggregate_unacked(&buf), &msg[5 * N..]); +511 // ack with gap, doesn't free anything +512 buf.ack(7 * K..9 * K); +513 assert_eq!(aggregate_unacked(&buf), &msg[5 * N..]); +514 // fill the gap, free up to 9 K +515 buf.ack(4 * K..7 * K); +516 assert_eq!(aggregate_unacked(&buf), &msg[9 * N..]); +517 // ack all +518 buf.ack(0..msg_len); +519 assert_eq!(aggregate_unacked(&buf), &[] as &[u8]); +520 } +521 +522 #[test] +523 fn retransmit() { +524 let mut buf = SendBuffer::new(); +525 const MSG: &[u8] = b"Hello, world with extra data!"; +526 buf.write(MSG); +527 // Transmit two frames +528 assert_eq!(buf.poll_transmit(16), (0..16, false)); +529 assert_eq!(buf.poll_transmit(16), (16..23, true)); +530 // Lose the first, but not the second +531 buf.retransmit(0..16); +532 // Ensure we only retransmit the lost frame, then continue sending fresh data +533 assert_eq!(buf.poll_transmit(16), (0..16, false)); +534 assert_eq!(buf.poll_transmit(16), (23..MSG.len() as u64, true)); +535 // Lose the second frame +536 buf.retransmit(16..23); +537 assert_eq!(buf.poll_transmit(16), (16..23, true)); 538 } 539 540 #[test] -541 fn reordered_ack() { +541 fn ack() { 542 let mut buf = SendBuffer::new(); -543 const MSG: &[u8] = b"Hello, world with extra data!"; -544 buf.write(MSG.into()); -545 assert_eq!(buf.poll_transmit(16), (0..16, false)); -546 assert_eq!(buf.poll_transmit(16), (16..23, true)); -547 buf.ack(16..23); -548 assert_eq!(aggregate_unacked(&buf), MSG); -549 buf.ack(0..16); -550 assert_eq!(aggregate_unacked(&buf), &MSG[23..]); -551 assert!(buf.acks.is_empty()); -552 } -553 -554 fn aggregate_unacked(buf: &SendBuffer) -> Vec<u8> { -555 buf.data.to_vec() -556 } -557 -558 #[test] -559 #[should_panic(expected = "Requested range is outside of buffered data")] -560 fn send_buffer_get_out_of_range() { -561 let data = SendBufferData::default(); -562 data.get(0..1); -563 } -564 -565 #[test] -566 #[should_panic(expected = "Requested range is outside of buffered data")] -567 fn send_buffer_get_into_out_of_range() { -568 let data = SendBufferData::default(); -569 let mut buf = Vec::new(); -570 data.get_into(0..1, &mut buf); -571 } -572} -573 -574#[cfg(all(test, not(target_family = "wasm")))] -575mod proptests { -576 use super::*; -577 -578 use proptest::prelude::*; -579 use test_strategy::{Arbitrary, proptest}; -580 use crate::tests::subscribe; -581 use tracing::trace; -582 -583 #[derive(Debug, Clone, Arbitrary)] -584 enum Op { -585 // write the given bytes -586 Write(#[strategy(proptest::collection::vec(any::<u8>(), 0..1024))] Vec<u8>), -587 // ack a random range -588 Ack(Range<u64>), -589 // retransmit a random range -590 Retransmit(Range<u64>), -591 // poll_transmit with the given max len -592 PollTransmit(#[strategy(16usize..1024)] usize), -593 } -594 -595 /// Map a range into a target range -596 /// -597 /// If the target range is empty, it will be returned as is. -598 /// For a non-empty target range, 0 in the input range will be mapped to -599 /// the start of the target range, and the input range will wrap around -600 /// the target range as needed. -601 fn map_range(input: Range<u64>, target: Range<u64>) -> Range<u64> { -602 if target.is_empty() { -603 return target; -604 } -605 let size = target.end - target.start; -606 let a = target.start + (input.start % size); -607 let b = target.start + (input.end % size); -608 a.min(b)..a.max(b) -609 } -610 -611 #[proptest] -612 fn send_buffer_matches_reference( -613 #[strategy(proptest::collection::vec(any::<Op>(), 1..100))] ops: Vec<Op>, -614 ) { -615 let _guard = subscribe(); -616 let mut sb = SendBuffer::new(); -617 // all data written to the send buffer -618 let mut buf = Vec::new(); -619 // max offset that has been returned by poll_transmit -620 let mut max_send_offset = 0u64; -621 // max offset up to which data has been fully acked -622 let mut max_full_send_offset = 0u64; -623 trace!(""); -624 for op in ops { -625 match op { -626 Op::Write(data) => { -627 trace!("Op::Write({})", data.len()); -628 buf.extend_from_slice(&data); -629 sb.write(Bytes::from(data)); -630 } -631 Op::Ack(range) => { -632 // we can only get acks for data that has been sent -633 let range = map_range(range, 0..max_send_offset); -634 // update fully acked range -635 if range.contains(&max_full_send_offset) { -636 max_full_send_offset = range.end; -637 } -638 trace!("Op::Ack({:?})", range); -639 sb.ack(range); +543 const MSG: &[u8] = b"Hello, world!"; +544 buf.write(MSG); +545 assert_eq!(buf.poll_transmit(16), (0..8, true)); +546 buf.ack(0..8); +547 assert_eq!(aggregate_unacked(&buf), &MSG[8..]); +548 } +549 +550 #[test] +551 fn reordered_ack() { +552 let mut buf = SendBuffer::new(); +553 const MSG: &[u8] = b"Hello, world with extra data!"; +554 buf.write(MSG); +555 assert_eq!(buf.poll_transmit(16), (0..16, false)); +556 assert_eq!(buf.poll_transmit(16), (16..23, true)); +557 buf.ack(16..23); +558 assert_eq!(aggregate_unacked(&buf), MSG); +559 buf.ack(0..16); +560 assert_eq!(aggregate_unacked(&buf), &MSG[23..]); +561 assert!(buf.acks.is_empty()); +562 } +563 +564 fn aggregate_unacked(buf: &SendBuffer) -> Vec<u8> { +565 buf.data.to_vec() +566 } +567 +568 #[test] +569 #[should_panic(expected = "Requested range is outside of buffered data")] +570 fn send_buffer_get_out_of_range() { +571 let data = SendBufferData::default(); +572 data.get(0..1); +573 } +574 +575 #[test] +576 #[should_panic(expected = "Requested range is outside of buffered data")] +577 fn send_buffer_get_into_out_of_range() { +578 let data = SendBufferData::default(); +579 let mut buf = Vec::new(); +580 data.get_into(0..1, &mut buf); +581 } +582} +583 +584#[cfg(all(test, not(target_family = "wasm")))] +585mod proptests { +586 use super::*; +587 +588 use proptest::prelude::*; +589 use test_strategy::{Arbitrary, proptest}; +590 use crate::tests::subscribe; +591 use tracing::trace; +592 +593 #[derive(Debug, Clone, Arbitrary)] +594 enum Op { +595 // write the given bytes +596 Write(#[strategy(proptest::collection::vec(any::<u8>(), 0..1024))] Vec<u8>), +597 // ack a random range +598 Ack(Range<u64>), +599 // retransmit a random range +600 Retransmit(Range<u64>), +601 // poll_transmit with the given max len +602 PollTransmit(#[strategy(16usize..1024)] usize), +603 } +604 +605 /// Map a range into a target range +606 /// +607 /// If the target range is empty, it will be returned as is. +608 /// For a non-empty target range, 0 in the input range will be mapped to +609 /// the start of the target range, and the input range will wrap around +610 /// the target range as needed. +611 fn map_range(input: Range<u64>, target: Range<u64>) -> Range<u64> { +612 if target.is_empty() { +613 return target; +614 } +615 let size = target.end - target.start; +616 let a = target.start + (input.start % size); +617 let b = target.start + (input.end % size); +618 a.min(b)..a.max(b) +619 } +620 +621 #[proptest] +622 fn send_buffer_matches_reference( +623 #[strategy(proptest::collection::vec(any::<Op>(), 1..100))] ops: Vec<Op>, +624 ) { +625 let _guard = subscribe(); +626 let mut sb = SendBuffer::new(); +627 // all data written to the send buffer +628 let mut buf = Vec::new(); +629 // max offset that has been returned by poll_transmit +630 let mut max_send_offset = 0u64; +631 // max offset up to which data has been fully acked +632 let mut max_full_send_offset = 0u64; +633 trace!(""); +634 for op in ops { +635 match op { +636 Op::Write(data) => { +637 trace!("Op::Write({})", data.len()); +638 buf.extend_from_slice(&data); +639 sb.write(Bytes::from(data)); 640 } -641 Op::Retransmit(range) => { -642 // we can only get retransmits for data that has been sent +641 Op::Ack(range) => { +642 // we can only get acks for data that has been sent 643 let range = map_range(range, 0..max_send_offset); -644 trace!("Op::Retransmit({:?})", range); -645 sb.retransmit(range); -646 } -647 Op::PollTransmit(max_len) => { -648 trace!("Op::PollTransmit({})", max_len); -649 let (range, _partial) = sb.poll_transmit(max_len); -650 max_send_offset = max_send_offset.max(range.end); -651 assert!( -652 range.start >= max_full_send_offset, -653 "poll_transmit returned already fully acked data: range={:?}, max_full_send_offset={}", -654 range, -655 max_full_send_offset -656 ); -657 -658 let mut t1 = Vec::new(); -659 sb.get_into(range.clone(), &mut t1); -660 -661 let mut t2 = Vec::new(); -662 t2.extend_from_slice(&buf[range.start as usize..range.end as usize]); -663 -664 assert_eq!(t1, t2, "Data mismatch for range {:?}", range); -665 } -666 } -667 } -668 // Drain all remaining data -669 trace!("Op::Retransmit({:?})", 0..max_send_offset); -670 sb.retransmit(0..max_send_offset); -671 loop { -672 trace!("Op::PollTransmit({})", 1024); -673 let (range, _partial) = sb.poll_transmit(1024); -674 if range.is_empty() { -675 break; +644 // update fully acked range +645 if range.contains(&max_full_send_offset) { +646 max_full_send_offset = range.end; +647 } +648 trace!("Op::Ack({:?})", range); +649 sb.ack(range); +650 } +651 Op::Retransmit(range) => { +652 // we can only get retransmits for data that has been sent +653 let range = map_range(range, 0..max_send_offset); +654 trace!("Op::Retransmit({:?})", range); +655 sb.retransmit(range); +656 } +657 Op::PollTransmit(max_len) => { +658 trace!("Op::PollTransmit({})", max_len); +659 let (range, _partial) = sb.poll_transmit(max_len); +660 max_send_offset = max_send_offset.max(range.end); +661 assert!( +662 range.start >= max_full_send_offset, +663 "poll_transmit returned already fully acked data: range={:?}, max_full_send_offset={}", +664 range, +665 max_full_send_offset +666 ); +667 +668 let mut t1 = Vec::new(); +669 sb.get_into(range.clone(), &mut t1); +670 +671 let mut t2 = Vec::new(); +672 t2.extend_from_slice(&buf[range.start as usize..range.end as usize]); +673 +674 assert_eq!(t1, t2, "Data mismatch for range {:?}", range); +675 } 676 } -677 trace!("Op::Ack({:?})", range); -678 sb.ack(range); -679 } -680 assert!( -681 sb.is_fully_acked(), -682 "SendBuffer not fully acked at end of ops" -683 ); -684 } -685} -686 -687#[cfg(feature = "bench")] -688pub mod send_buffer_benches { -689 //! Bench fns for SendBuffer -690 //! -691 //! These are defined here and re-exported via `bench_exports` in lib.rs, -692 //! so we can access the private `SendBuffer` struct. -693 use bytes::Bytes; -694 use criterion::Criterion; -695 -696 use super::SendBuffer; -697 -698 /// Pathological case: many segments, get from end -699 pub fn get_into_many_segments(criterion: &mut Criterion) { -700 let mut group = criterion.benchmark_group("get_into_many_segments"); -701 let mut buf = SendBuffer::new(); -702 -703 const SEGMENTS: u64 = 10000; -704 const SEGMENT_SIZE: u64 = 10; -705 const PACKET_SIZE: u64 = 1200; -706 const BYTES: u64 = SEGMENTS * SEGMENT_SIZE; +677 } +678 // Drain all remaining data +679 trace!("Op::Retransmit({:?})", 0..max_send_offset); +680 sb.retransmit(0..max_send_offset); +681 loop { +682 trace!("Op::PollTransmit({})", 1024); +683 let (range, _partial) = sb.poll_transmit(1024); +684 if range.is_empty() { +685 break; +686 } +687 trace!("Op::Ack({:?})", range); +688 sb.ack(range); +689 } +690 assert!( +691 sb.is_fully_acked(), +692 "SendBuffer not fully acked at end of ops" +693 ); +694 } +695} +696 +697#[cfg(feature = "bench")] +698pub mod send_buffer_benches { +699 //! Bench fns for SendBuffer +700 //! +701 //! These are defined here and re-exported via `bench_exports` in lib.rs, +702 //! so we can access the private `SendBuffer` struct. +703 use bytes::Bytes; +704 use criterion::Criterion; +705 +706 use super::SendBuffer; 707 -708 // 10000 segments of 10 bytes each = 100KB total (same data size) -709 for i in 0..SEGMENTS { -710 buf.write(Bytes::from(vec![i as u8; SEGMENT_SIZE as usize])); -711 } +708 /// Pathological case: many segments, get from end +709 pub fn get_into_many_segments(criterion: &mut Criterion) { +710 let mut group = criterion.benchmark_group("get_into_many_segments"); +711 let mut buf = SendBuffer::new(); 712 -713 let mut tgt = Vec::with_capacity(PACKET_SIZE as usize); -714 group.bench_function("get_into", |b| { -715 b.iter(|| { -716 // Get from end (very slow - scans through all 1000 segments) -717 tgt.clear(); -718 buf.get_into(BYTES - PACKET_SIZE..BYTES, std::hint::black_box(&mut tgt)); -719 }); -720 }); -721 } +713 const SEGMENTS: u64 = 10000; +714 const SEGMENT_SIZE: u64 = 10; +715 const PACKET_SIZE: u64 = 1200; +716 const BYTES: u64 = SEGMENTS * SEGMENT_SIZE; +717 +718 // 10000 segments of 10 bytes each = 100KB total (same data size) +719 for i in 0..SEGMENTS { +720 buf.write(Bytes::from(vec![i as u8; SEGMENT_SIZE as usize])); +721 } 722 -723 /// Get segments in the old way, using a loop of get calls -724 pub fn get_loop_many_segments(criterion: &mut Criterion) { -725 let mut group = criterion.benchmark_group("get_loop_many_segments"); -726 let mut buf = SendBuffer::new(); -727 -728 const SEGMENTS: u64 = 10000; -729 const SEGMENT_SIZE: u64 = 10; -730 const PACKET_SIZE: u64 = 1200; -731 const BYTES: u64 = SEGMENTS * SEGMENT_SIZE; +723 let mut tgt = Vec::with_capacity(PACKET_SIZE as usize); +724 group.bench_function("get_into", |b| { +725 b.iter(|| { +726 // Get from end (very slow - scans through all 1000 segments) +727 tgt.clear(); +728 buf.get_into(BYTES - PACKET_SIZE..BYTES, std::hint::black_box(&mut tgt)); +729 }); +730 }); +731 } 732 -733 // 10000 segments of 10 bytes each = 100KB total (same data size) -734 for i in 0..SEGMENTS { -735 buf.write(Bytes::from(vec![i as u8; SEGMENT_SIZE as usize])); -736 } +733 /// Get segments in the old way, using a loop of get calls +734 pub fn get_loop_many_segments(criterion: &mut Criterion) { +735 let mut group = criterion.benchmark_group("get_loop_many_segments"); +736 let mut buf = SendBuffer::new(); 737 -738 let mut tgt = Vec::with_capacity(PACKET_SIZE as usize); -739 group.bench_function("get_loop", |b| { -740 b.iter(|| { -741 // Get from end (very slow - scans through all 1000 segments) -742 tgt.clear(); -743 let mut range = BYTES - PACKET_SIZE..BYTES; -744 while range.start < range.end { -745 let slice = std::hint::black_box(buf.get(range.clone())); -746 range.start += slice.len() as u64; -747 tgt.extend_from_slice(slice); -748 } -749 }); -750 }); -751 } -752}
      \ No newline at end of file +738 const SEGMENTS: u64 = 10000; +739 const SEGMENT_SIZE: u64 = 10; +740 const PACKET_SIZE: u64 = 1200; +741 const BYTES: u64 = SEGMENTS * SEGMENT_SIZE; +742 +743 // 10000 segments of 10 bytes each = 100KB total (same data size) +744 for i in 0..SEGMENTS { +745 buf.write(Bytes::from(vec![i as u8; SEGMENT_SIZE as usize])); +746 } +747 +748 let mut tgt = Vec::with_capacity(PACKET_SIZE as usize); +749 group.bench_function("get_loop", |b| { +750 b.iter(|| { +751 // Get from end (very slow - scans through all 1000 segments) +752 tgt.clear(); +753 let mut range = BYTES - PACKET_SIZE..BYTES; +754 while range.start < range.end { +755 let slice = std::hint::black_box(buf.get(range.clone())); +756 range.start += slice.len() as u64; +757 tgt.extend_from_slice(slice); +758 } +759 }); +760 }); +761 } +762}
      \ No newline at end of file diff --git a/pr/255/docs/src/iroh_quinn_proto/connection/streams/mod.rs.html b/pr/255/docs/src/iroh_quinn_proto/connection/streams/mod.rs.html index cd8a6a6fe..3764c8cd9 100644 --- a/pr/255/docs/src/iroh_quinn_proto/connection/streams/mod.rs.html +++ b/pr/255/docs/src/iroh_quinn_proto/connection/streams/mod.rs.html @@ -234,295 +234,321 @@ 234 self.write_source(&mut BytesArray::from_chunks(data)) 235 } 236 -237 fn write_source<B: BytesSource>(&mut self, source: &mut B) -> Result<Written, WriteError> { -238 if self.conn_state.is_closed() { -239 trace!(%self.id, "write blocked; connection draining"); -240 return Err(WriteError::Blocked); -241 } -242 -243 let limit = self.state.write_limit(); -244 -245 let max_send_data = self.state.max_send_data(self.id); -246 -247 let stream = self -248 .state -249 .send -250 .get_mut(&self.id) -251 .map(get_or_insert_send(max_send_data)) -252 .ok_or(WriteError::ClosedStream)?; -253 -254 if limit == 0 { -255 trace!( -256 stream = %self.id, max_data = self.state.max_data, data_sent = self.state.data_sent, -257 "write blocked by connection-level flow control or send window" -258 ); -259 if !stream.connection_blocked { -260 stream.connection_blocked = true; -261 self.state.connection_blocked.push(self.id); -262 } -263 return Err(WriteError::Blocked); -264 } -265 -266 let was_pending = stream.is_pending(); -267 let written = stream.write(source, limit)?; -268 self.state.data_sent += written.bytes as u64; -269 self.state.unacked_data += written.bytes as u64; -270 trace!(stream = %self.id, "wrote {} bytes", written.bytes); -271 if !was_pending { -272 self.state.pending.push_pending(self.id, stream.priority); -273 } -274 Ok(written) -275 } -276 -277 /// Check if this stream was stopped, get the reason if it was -278 pub fn stopped(&self) -> Result<Option<VarInt>, ClosedStream> { -279 match self.state.send.get(&self.id).as_ref() { -280 Some(Some(s)) => Ok(s.stop_reason), -281 Some(None) => Ok(None), -282 None => Err(ClosedStream { _private: () }), -283 } -284 } -285 -286 /// Finish a send stream, signalling that no more data will be sent. -287 /// -288 /// If this fails, no [`StreamEvent::Finished`] will be generated. -289 /// -290 /// [`StreamEvent::Finished`]: crate::StreamEvent::Finished -291 pub fn finish(&mut self) -> Result<(), FinishError> { -292 let max_send_data = self.state.max_send_data(self.id); -293 let stream = self -294 .state -295 .send -296 .get_mut(&self.id) -297 .map(get_or_insert_send(max_send_data)) -298 .ok_or(FinishError::ClosedStream)?; -299 -300 let was_pending = stream.is_pending(); -301 stream.finish()?; -302 if !was_pending { -303 self.state.pending.push_pending(self.id, stream.priority); -304 } -305 -306 Ok(()) -307 } +237 fn write_source<'b, B: BytesSource<'b>>( +238 &mut self, +239 source: &'b mut B, +240 ) -> Result<Written, WriteError> { +241 if self.conn_state.is_closed() { +242 trace!(%self.id, "write blocked; connection draining"); +243 return Err(WriteError::Blocked); +244 } +245 +246 let limit = self.state.write_limit(); +247 +248 let max_send_data = self.state.max_send_data(self.id); +249 +250 let stream = self +251 .state +252 .send +253 .get_mut(&self.id) +254 .map(get_or_insert_send(max_send_data)) +255 .ok_or(WriteError::ClosedStream)?; +256 +257 if limit == 0 { +258 trace!( +259 stream = %self.id, max_data = self.state.max_data, data_sent = self.state.data_sent, +260 "write blocked by connection-level flow control or send window" +261 ); +262 if !stream.connection_blocked { +263 stream.connection_blocked = true; +264 self.state.connection_blocked.push(self.id); +265 } +266 return Err(WriteError::Blocked); +267 } +268 +269 let was_pending = stream.is_pending(); +270 let written = stream.write(source, limit)?; +271 self.state.data_sent += written.bytes as u64; +272 self.state.unacked_data += written.bytes as u64; +273 trace!(stream = %self.id, "wrote {} bytes", written.bytes); +274 if !was_pending { +275 self.state.pending.push_pending(self.id, stream.priority); +276 } +277 Ok(written) +278 } +279 +280 /// Check if this stream was stopped, get the reason if it was +281 pub fn stopped(&self) -> Result<Option<VarInt>, ClosedStream> { +282 match self.state.send.get(&self.id).as_ref() { +283 Some(Some(s)) => Ok(s.stop_reason), +284 Some(None) => Ok(None), +285 None => Err(ClosedStream { _private: () }), +286 } +287 } +288 +289 /// Finish a send stream, signalling that no more data will be sent. +290 /// +291 /// If this fails, no [`StreamEvent::Finished`] will be generated. +292 /// +293 /// [`StreamEvent::Finished`]: crate::StreamEvent::Finished +294 pub fn finish(&mut self) -> Result<(), FinishError> { +295 let max_send_data = self.state.max_send_data(self.id); +296 let stream = self +297 .state +298 .send +299 .get_mut(&self.id) +300 .map(get_or_insert_send(max_send_data)) +301 .ok_or(FinishError::ClosedStream)?; +302 +303 let was_pending = stream.is_pending(); +304 stream.finish()?; +305 if !was_pending { +306 self.state.pending.push_pending(self.id, stream.priority); +307 } 308 -309 /// Abandon transmitting data on a stream -310 /// -311 /// # Panics -312 /// - when applied to a receive stream -313 pub fn reset(&mut self, error_code: VarInt) -> Result<(), ClosedStream> { -314 let max_send_data = self.state.max_send_data(self.id); -315 let stream = self -316 .state -317 .send -318 .get_mut(&self.id) -319 .map(get_or_insert_send(max_send_data)) -320 .ok_or(ClosedStream { _private: () })?; -321 -322 if matches!(stream.state, SendState::ResetSent) { -323 // Redundant reset call -324 return Err(ClosedStream { _private: () }); -325 } -326 -327 // Restore the portion of the send window consumed by the data that we aren't about to -328 // send. We leave flow control alone because the peer's responsible for issuing additional -329 // credit based on the final offset communicated in the RESET_STREAM frame we send. -330 self.state.unacked_data -= stream.pending.unacked(); -331 stream.reset(); -332 self.pending.reset_stream.push((self.id, error_code)); -333 -334 // Don't reopen an already-closed stream we haven't forgotten yet -335 Ok(()) -336 } -337 -338 /// Set the priority of a stream -339 /// -340 /// # Panics -341 /// - when applied to a receive stream -342 pub fn set_priority(&mut self, priority: i32) -> Result<(), ClosedStream> { -343 let max_send_data = self.state.max_send_data(self.id); -344 let stream = self -345 .state -346 .send -347 .get_mut(&self.id) -348 .map(get_or_insert_send(max_send_data)) -349 .ok_or(ClosedStream { _private: () })?; -350 -351 stream.priority = priority; -352 Ok(()) -353 } -354 -355 /// Get the priority of a stream -356 /// -357 /// # Panics -358 /// - when applied to a receive stream -359 pub fn priority(&self) -> Result<i32, ClosedStream> { -360 let stream = self -361 .state -362 .send -363 .get(&self.id) -364 .ok_or(ClosedStream { _private: () })?; -365 -366 Ok(stream.as_ref().map(|s| s.priority).unwrap_or_default()) -367 } -368} -369 -370/// A queue of streams with pending outgoing data, sorted by priority -371struct PendingStreamsQueue { -372 streams: BinaryHeap<PendingStream>, -373 /// The next stream to write out. This is `Some` when `TransportConfig::send_fairness(false)` and writing a stream is -374 /// interrupted while the stream still has some pending data. See `reinsert_pending()`. -375 next: Option<PendingStream>, -376 /// A monotonically decreasing counter, used to implement round-robin scheduling for streams of the same priority. -377 /// Underflowing is not a practical concern, as it is initialized to u64::MAX and only decremented by 1 in `push_pending` -378 recency: u64, -379} -380 -381impl PendingStreamsQueue { -382 fn new() -> Self { -383 Self { -384 streams: BinaryHeap::new(), -385 next: None, -386 recency: u64::MAX, -387 } -388 } -389 -390 /// Reinsert a stream that was pending and still contains unsent data. -391 fn reinsert_pending(&mut self, id: StreamId, priority: i32) { -392 assert!(self.next.is_none()); -393 -394 self.next = Some(PendingStream { -395 priority, -396 recency: self.recency, // the value here doesn't really matter -397 id, -398 }); -399 } -400 -401 /// Push a pending stream ID with the given priority, queued after any already-queued streams for the priority -402 fn push_pending(&mut self, id: StreamId, priority: i32) { -403 // Note that in the case where fairness is disabled, if we have a reinserted stream we don't -404 // bump it even if priority > next.priority. In order to minimize fragmentation we -405 // always try to complete a stream once part of it has been written. -406 -407 // As the recency counter is monotonically decreasing, we know that using its value to sort this stream will queue it -408 // after all other queued streams of the same priority. -409 // This is enough to implement round-robin scheduling for streams that are still pending even after being handled, -410 // as in that case they are removed from the `BinaryHeap`, handled, and then immediately reinserted. -411 self.recency -= 1; -412 self.streams.push(PendingStream { -413 priority, -414 recency: self.recency, -415 id, -416 }); -417 } -418 -419 fn pop(&mut self) -> Option<PendingStream> { -420 self.next.take().or_else(|| self.streams.pop()) -421 } -422 -423 fn clear(&mut self) { -424 self.next = None; -425 self.streams.clear(); -426 } -427 -428 fn iter(&self) -> impl Iterator<Item = &PendingStream> { -429 self.next.iter().chain(self.streams.iter()) -430 } -431 -432 #[cfg(test)] -433 fn len(&self) -> usize { -434 self.streams.len() + self.next.is_some() as usize -435 } -436} -437 -438/// The [`StreamId`] of a stream with pending data queued, ordered by its priority and recency -439#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)] -440struct PendingStream { -441 /// The priority of the stream -442 // Note that this field should be kept above the `recency` field, in order for the `Ord` derive to be correct -443 // (See https://doc.rust-lang.org/stable/std/cmp/trait.Ord.html#derivable) -444 priority: i32, -445 /// A tie-breaker for streams of the same priority, used to improve fairness by implementing round-robin scheduling: -446 /// Larger values are prioritized, so it is initialised to `u64::MAX`, and when a stream writes data, we know -447 /// that it currently has the highest recency value, so it is deprioritized by setting its recency to 1 less than the -448 /// previous lowest recency value, such that all other streams of this priority will get processed once before we get back -449 /// round to this one -450 recency: u64, -451 /// The ID of the stream -452 // The way this type is used ensures that every instance has a unique `recency` value, so this field should be kept below -453 // the `priority` and `recency` fields, so that it does not interfere with the behaviour of the `Ord` derive -454 id: StreamId, -455} -456 -457/// Application events about streams -458#[derive(Debug, PartialEq, Eq)] -459pub enum StreamEvent { -460 /// One or more new streams has been opened and might be readable -461 Opened { -462 /// Directionality for which streams have been opened -463 dir: Dir, -464 }, -465 /// A currently open stream likely has data or errors waiting to be read -466 Readable { -467 /// Which stream is now readable -468 id: StreamId, -469 }, -470 /// A formerly write-blocked stream might be ready for a write or have been stopped -471 /// -472 /// Only generated for streams that are currently open. -473 Writable { -474 /// Which stream is now writable -475 id: StreamId, -476 }, -477 /// A finished stream has been fully acknowledged or stopped -478 Finished { -479 /// Which stream has been finished -480 id: StreamId, -481 }, -482 /// The peer asked us to stop sending on an outgoing stream -483 Stopped { -484 /// Which stream has been stopped -485 id: StreamId, -486 /// Error code supplied by the peer -487 error_code: VarInt, -488 }, -489 /// At least one new stream of a certain directionality may be opened -490 Available { -491 /// Directionality for which streams are newly available -492 dir: Dir, -493 }, -494} -495 -496/// Indicates whether a frame needs to be transmitted -497/// -498/// This type wraps around bool and uses the `#[must_use]` attribute in order -499/// to prevent accidental loss of the frame transmission requirement. -500#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)] -501#[must_use = "A frame might need to be enqueued"] -502pub struct ShouldTransmit(bool); -503 -504impl ShouldTransmit { -505 /// Returns whether a frame should be transmitted -506 pub fn should_transmit(self) -> bool { -507 self.0 -508 } -509} -510 -511/// Error indicating that a stream has not been opened or has already been finished or reset -512#[derive(Debug, Default, Error, Clone, PartialEq, Eq)] -513#[error("closed stream")] -514pub struct ClosedStream { -515 _private: (), -516} -517 -518impl From<ClosedStream> for io::Error { -519 fn from(x: ClosedStream) -> Self { -520 Self::new(io::ErrorKind::NotConnected, x) -521 } -522} -523 -524#[derive(Debug, Copy, Clone, Eq, PartialEq)] -525enum StreamHalf { -526 Send, -527 Recv, -528}
      \ No newline at end of file +309 Ok(()) +310 } +311 +312 /// Abandon transmitting data on a stream +313 /// +314 /// # Panics +315 /// - when applied to a receive stream +316 pub fn reset(&mut self, error_code: VarInt) -> Result<(), ClosedStream> { +317 let max_send_data = self.state.max_send_data(self.id); +318 let stream = self +319 .state +320 .send +321 .get_mut(&self.id) +322 .map(get_or_insert_send(max_send_data)) +323 .ok_or(ClosedStream { _private: () })?; +324 +325 if matches!(stream.state, SendState::ResetSent) { +326 // Redundant reset call +327 return Err(ClosedStream { _private: () }); +328 } +329 +330 // Restore the portion of the send window consumed by the data that we aren't about to +331 // send. We leave flow control alone because the peer's responsible for issuing additional +332 // credit based on the final offset communicated in the RESET_STREAM frame we send. +333 self.state.unacked_data -= stream.pending.unacked(); +334 stream.reset(); +335 self.pending.reset_stream.push((self.id, error_code)); +336 +337 // Don't reopen an already-closed stream we haven't forgotten yet +338 Ok(()) +339 } +340 +341 /// Set the priority of a stream +342 /// +343 /// # Panics +344 /// - when applied to a receive stream +345 pub fn set_priority(&mut self, priority: i32) -> Result<(), ClosedStream> { +346 let max_send_data = self.state.max_send_data(self.id); +347 let stream = self +348 .state +349 .send +350 .get_mut(&self.id) +351 .map(get_or_insert_send(max_send_data)) +352 .ok_or(ClosedStream { _private: () })?; +353 +354 stream.priority = priority; +355 Ok(()) +356 } +357 +358 /// Get the priority of a stream +359 /// +360 /// # Panics +361 /// - when applied to a receive stream +362 pub fn priority(&self) -> Result<i32, ClosedStream> { +363 let stream = self +364 .state +365 .send +366 .get(&self.id) +367 .ok_or(ClosedStream { _private: () })?; +368 +369 Ok(stream.as_ref().map(|s| s.priority).unwrap_or_default()) +370 } +371} +372 +373/// A queue of streams with pending outgoing data, sorted by priority +374struct PendingStreamsQueue { +375 streams: BinaryHeap<PendingStream>, +376 /// The next stream to write out. This is `Some` when `TransportConfig::send_fairness(false)` and writing a stream is +377 /// interrupted while the stream still has some pending data. See `reinsert_pending()`. +378 next: Option<PendingStream>, +379 /// A monotonically decreasing counter, used to implement round-robin scheduling for streams of the same priority. +380 /// Underflowing is not a practical concern, as it is initialized to u64::MAX and only decremented by 1 in `push_pending` +381 recency: u64, +382} +383 +384impl PendingStreamsQueue { +385 fn new() -> Self { +386 Self { +387 streams: BinaryHeap::new(), +388 next: None, +389 recency: u64::MAX, +390 } +391 } +392 +393 /// Reinsert a stream that was pending and still contains unsent data. +394 fn reinsert_pending(&mut self, id: StreamId, priority: i32) { +395 assert!(self.next.is_none()); +396 +397 self.next = Some(PendingStream { +398 priority, +399 recency: self.recency, // the value here doesn't really matter +400 id, +401 }); +402 } +403 +404 /// Push a pending stream ID with the given priority, queued after any already-queued streams for the priority +405 fn push_pending(&mut self, id: StreamId, priority: i32) { +406 // Note that in the case where fairness is disabled, if we have a reinserted stream we don't +407 // bump it even if priority > next.priority. In order to minimize fragmentation we +408 // always try to complete a stream once part of it has been written. +409 +410 // As the recency counter is monotonically decreasing, we know that using its value to sort this stream will queue it +411 // after all other queued streams of the same priority. +412 // This is enough to implement round-robin scheduling for streams that are still pending even after being handled, +413 // as in that case they are removed from the `BinaryHeap`, handled, and then immediately reinserted. +414 self.recency -= 1; +415 self.streams.push(PendingStream { +416 priority, +417 recency: self.recency, +418 id, +419 }); +420 } +421 +422 fn pop(&mut self) -> Option<PendingStream> { +423 self.next.take().or_else(|| self.streams.pop()) +424 } +425 +426 fn clear(&mut self) { +427 self.next = None; +428 self.streams.clear(); +429 } +430 +431 fn iter(&self) -> impl Iterator<Item = &PendingStream> { +432 self.next.iter().chain(self.streams.iter()) +433 } +434 +435 #[cfg(test)] +436 fn len(&self) -> usize { +437 self.streams.len() + self.next.is_some() as usize +438 } +439} +440 +441/// The [`StreamId`] of a stream with pending data queued, ordered by its priority and recency +442#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)] +443struct PendingStream { +444 /// The priority of the stream +445 // Note that this field should be kept above the `recency` field, in order for the `Ord` derive to be correct +446 // (See https://doc.rust-lang.org/stable/std/cmp/trait.Ord.html#derivable) +447 priority: i32, +448 /// A tie-breaker for streams of the same priority, used to improve fairness by implementing round-robin scheduling: +449 /// Larger values are prioritized, so it is initialised to `u64::MAX`, and when a stream writes data, we know +450 /// that it currently has the highest recency value, so it is deprioritized by setting its recency to 1 less than the +451 /// previous lowest recency value, such that all other streams of this priority will get processed once before we get back +452 /// round to this one +453 recency: u64, +454 /// The ID of the stream +455 // The way this type is used ensures that every instance has a unique `recency` value, so this field should be kept below +456 // the `priority` and `recency` fields, so that it does not interfere with the behaviour of the `Ord` derive +457 id: StreamId, +458} +459 +460/// Application events about streams +461#[derive(Debug, PartialEq, Eq)] +462pub enum StreamEvent { +463 /// One or more new streams has been opened and might be readable +464 Opened { +465 /// Directionality for which streams have been opened +466 dir: Dir, +467 }, +468 /// A currently open stream likely has data or errors waiting to be read +469 Readable { +470 /// Which stream is now readable +471 id: StreamId, +472 }, +473 /// A formerly write-blocked stream might be ready for a write or have been stopped +474 /// +475 /// Only generated for streams that are currently open. +476 Writable { +477 /// Which stream is now writable +478 id: StreamId, +479 }, +480 /// A finished stream has been fully acknowledged or stopped +481 Finished { +482 /// Which stream has been finished +483 id: StreamId, +484 }, +485 /// The peer asked us to stop sending on an outgoing stream +486 Stopped { +487 /// Which stream has been stopped +488 id: StreamId, +489 /// Error code supplied by the peer +490 error_code: VarInt, +491 }, +492 /// At least one new stream of a certain directionality may be opened +493 Available { +494 /// Directionality for which streams are newly available +495 dir: Dir, +496 }, +497} +498 +499/// Indicates whether a frame needs to be transmitted +500/// +501/// This type wraps around bool and uses the `#[must_use]` attribute in order +502/// to prevent accidental loss of the frame transmission requirement. +503#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)] +504#[must_use = "A frame might need to be enqueued"] +505pub struct ShouldTransmit(bool); +506 +507impl ShouldTransmit { +508 /// Returns whether a frame should be transmitted +509 pub fn should_transmit(self) -> bool { +510 self.0 +511 } +512} +513 +514/// Error indicating that a stream has not been opened or has already been finished or reset +515#[derive(Debug, Default, Error, Clone, PartialEq, Eq)] +516#[error("closed stream")] +517pub struct ClosedStream { +518 _private: (), +519} +520 +521impl From<ClosedStream> for io::Error { +522 fn from(x: ClosedStream) -> Self { +523 Self::new(io::ErrorKind::NotConnected, x) +524 } +525} +526 +527#[derive(Debug, Copy, Clone, Eq, PartialEq)] +528enum StreamHalf { +529 Send, +530 Recv, +531} +532 +533/// A helper trait to unify Bytes, Vec<u8> and &[u8] as sources of bytes +534pub(super) trait BytesOrSlice<'a>: AsRef<[u8]> + 'a { +535 fn len(&self) -> usize { +536 self.as_ref().len() +537 } +538 fn is_empty(&self) -> bool { +539 self.as_ref().is_empty() +540 } +541 fn into_bytes(self) -> Bytes; +542} +543 +544impl BytesOrSlice<'_> for Bytes { +545 fn into_bytes(self) -> Bytes { +546 self +547 } +548} +549 +550impl<'a> BytesOrSlice<'a> for &'a [u8] { +551 fn into_bytes(self) -> Bytes { +552 Bytes::copy_from_slice(self) +553 } +554}
      \ No newline at end of file diff --git a/pr/255/docs/src/iroh_quinn_proto/connection/streams/send.rs.html b/pr/255/docs/src/iroh_quinn_proto/connection/streams/send.rs.html index ec091cda4..4d8f979d7 100644 --- a/pr/255/docs/src/iroh_quinn_proto/connection/streams/send.rs.html +++ b/pr/255/docs/src/iroh_quinn_proto/connection/streams/send.rs.html @@ -1,402 +1,414 @@ send.rs - source

      iroh_quinn_proto/connection/streams/
      send.rs

      1use bytes::Bytes;
       2use thiserror::Error;
       3
      -4use crate::{VarInt, connection::send_buffer::SendBuffer, frame};
      -5
      -6#[derive(Debug)]
      -7pub(super) struct Send {
      -8    pub(super) max_data: u64,
      -9    pub(super) state: SendState,
      -10    pub(super) pending: SendBuffer,
      -11    pub(super) priority: i32,
      -12    /// Whether a frame containing a FIN bit must be transmitted, even if we don't have any new data
      -13    pub(super) fin_pending: bool,
      -14    /// Whether this stream is in the `connection_blocked` list of `Streams`
      -15    pub(super) connection_blocked: bool,
      -16    /// The reason the peer wants us to stop, if `STOP_SENDING` was received
      -17    pub(super) stop_reason: Option<VarInt>,
      -18}
      -19
      -20impl Send {
      -21    pub(super) fn new(max_data: VarInt) -> Box<Self> {
      -22        Box::new(Self {
      -23            max_data: max_data.into(),
      -24            state: SendState::Ready,
      -25            pending: SendBuffer::new(),
      -26            priority: 0,
      -27            fin_pending: false,
      -28            connection_blocked: false,
      -29            stop_reason: None,
      -30        })
      -31    }
      -32
      -33    /// Whether the stream has been reset
      -34    pub(super) fn is_reset(&self) -> bool {
      -35        matches!(self.state, SendState::ResetSent)
      -36    }
      -37
      -38    pub(super) fn finish(&mut self) -> Result<(), FinishError> {
      -39        if let Some(error_code) = self.stop_reason {
      -40            Err(FinishError::Stopped(error_code))
      -41        } else if self.state == SendState::Ready {
      -42            self.state = SendState::DataSent {
      -43                finish_acked: false,
      -44            };
      -45            self.fin_pending = true;
      -46            Ok(())
      -47        } else {
      -48            Err(FinishError::ClosedStream)
      -49        }
      -50    }
      -51
      -52    pub(super) fn write<S: BytesSource>(
      -53        &mut self,
      -54        source: &mut S,
      -55        limit: u64,
      -56    ) -> Result<Written, WriteError> {
      -57        if !self.is_writable() {
      -58            return Err(WriteError::ClosedStream);
      -59        }
      -60        if let Some(error_code) = self.stop_reason {
      -61            return Err(WriteError::Stopped(error_code));
      -62        }
      -63        let budget = self.max_data - self.pending.offset();
      -64        if budget == 0 {
      -65            return Err(WriteError::Blocked);
      +4use crate::{
      +5    VarInt,
      +6    connection::{send_buffer::SendBuffer, streams::BytesOrSlice},
      +7    frame,
      +8};
      +9
      +10#[derive(Debug)]
      +11pub(super) struct Send {
      +12    pub(super) max_data: u64,
      +13    pub(super) state: SendState,
      +14    pub(super) pending: SendBuffer,
      +15    pub(super) priority: i32,
      +16    /// Whether a frame containing a FIN bit must be transmitted, even if we don't have any new data
      +17    pub(super) fin_pending: bool,
      +18    /// Whether this stream is in the `connection_blocked` list of `Streams`
      +19    pub(super) connection_blocked: bool,
      +20    /// The reason the peer wants us to stop, if `STOP_SENDING` was received
      +21    pub(super) stop_reason: Option<VarInt>,
      +22}
      +23
      +24impl Send {
      +25    pub(super) fn new(max_data: VarInt) -> Box<Self> {
      +26        Box::new(Self {
      +27            max_data: max_data.into(),
      +28            state: SendState::Ready,
      +29            pending: SendBuffer::new(),
      +30            priority: 0,
      +31            fin_pending: false,
      +32            connection_blocked: false,
      +33            stop_reason: None,
      +34        })
      +35    }
      +36
      +37    /// Whether the stream has been reset
      +38    pub(super) fn is_reset(&self) -> bool {
      +39        matches!(self.state, SendState::ResetSent)
      +40    }
      +41
      +42    pub(super) fn finish(&mut self) -> Result<(), FinishError> {
      +43        if let Some(error_code) = self.stop_reason {
      +44            Err(FinishError::Stopped(error_code))
      +45        } else if self.state == SendState::Ready {
      +46            self.state = SendState::DataSent {
      +47                finish_acked: false,
      +48            };
      +49            self.fin_pending = true;
      +50            Ok(())
      +51        } else {
      +52            Err(FinishError::ClosedStream)
      +53        }
      +54    }
      +55
      +56    pub(super) fn write<'a, S: BytesSource<'a>>(
      +57        &mut self,
      +58        source: &'a mut S,
      +59        limit: u64,
      +60    ) -> Result<Written, WriteError> {
      +61        if !self.is_writable() {
      +62            return Err(WriteError::ClosedStream);
      +63        }
      +64        if let Some(error_code) = self.stop_reason {
      +65            return Err(WriteError::Stopped(error_code));
       66        }
      -67        let mut limit = limit.min(budget) as usize;
      -68
      -69        let mut result = Written::default();
      -70        loop {
      -71            let (chunk, chunks_consumed) = source.pop_chunk(limit);
      -72            result.chunks += chunks_consumed;
      -73            result.bytes += chunk.len();
      -74
      -75            if chunk.is_empty() {
      -76                break;
      -77            }
      +67        let budget = self.max_data - self.pending.offset();
      +68        if budget == 0 {
      +69            return Err(WriteError::Blocked);
      +70        }
      +71        let mut limit = limit.min(budget) as usize;
      +72
      +73        let mut result = Written::default();
      +74        loop {
      +75            let (chunk, chunks_consumed) = source.pop_chunk(limit);
      +76            result.chunks += chunks_consumed;
      +77            result.bytes += chunk.len();
       78
      -79            limit -= chunk.len();
      -80            self.pending.write(chunk);
      -81        }
      +79            if chunk.is_empty() {
      +80                break;
      +81            }
       82
      -83        Ok(result)
      -84    }
      -85
      -86    /// Update stream state due to a reset sent by the local application
      -87    pub(super) fn reset(&mut self) {
      -88        use SendState::*;
      -89        if let DataSent { .. } | Ready = self.state {
      -90            self.state = ResetSent;
      -91        }
      -92    }
      -93
      -94    /// Handle STOP_SENDING
      -95    ///
      -96    /// Returns true if the stream was stopped due to this frame, and false
      -97    /// if it had been stopped before
      -98    pub(super) fn try_stop(&mut self, error_code: VarInt) -> bool {
      -99        if self.stop_reason.is_none() {
      -100            self.stop_reason = Some(error_code);
      -101            true
      -102        } else {
      -103            false
      -104        }
      -105    }
      -106
      -107    /// Returns whether the stream has been finished and all data has been acknowledged by the peer
      -108    pub(super) fn ack(&mut self, frame: frame::StreamMeta) -> bool {
      -109        self.pending.ack(frame.offsets);
      -110        match self.state {
      -111            SendState::DataSent {
      -112                ref mut finish_acked,
      -113            } => {
      -114                *finish_acked |= frame.fin;
      -115                *finish_acked && self.pending.is_fully_acked()
      -116            }
      -117            _ => false,
      -118        }
      -119    }
      -120
      -121    /// Handle increase to stream-level flow control limit
      -122    ///
      -123    /// Returns whether the stream was unblocked
      -124    pub(super) fn increase_max_data(&mut self, offset: u64) -> bool {
      -125        if offset <= self.max_data || self.state != SendState::Ready {
      -126            return false;
      -127        }
      -128        let was_blocked = self.pending.offset() == self.max_data;
      -129        self.max_data = offset;
      -130        was_blocked
      -131    }
      -132
      -133    pub(super) fn offset(&self) -> u64 {
      -134        self.pending.offset()
      +83            limit -= chunk.len();
      +84            self.pending.write(chunk);
      +85        }
      +86
      +87        Ok(result)
      +88    }
      +89
      +90    /// Update stream state due to a reset sent by the local application
      +91    pub(super) fn reset(&mut self) {
      +92        use SendState::*;
      +93        if let DataSent { .. } | Ready = self.state {
      +94            self.state = ResetSent;
      +95        }
      +96    }
      +97
      +98    /// Handle STOP_SENDING
      +99    ///
      +100    /// Returns true if the stream was stopped due to this frame, and false
      +101    /// if it had been stopped before
      +102    pub(super) fn try_stop(&mut self, error_code: VarInt) -> bool {
      +103        if self.stop_reason.is_none() {
      +104            self.stop_reason = Some(error_code);
      +105            true
      +106        } else {
      +107            false
      +108        }
      +109    }
      +110
      +111    /// Returns whether the stream has been finished and all data has been acknowledged by the peer
      +112    pub(super) fn ack(&mut self, frame: frame::StreamMeta) -> bool {
      +113        self.pending.ack(frame.offsets);
      +114        match self.state {
      +115            SendState::DataSent {
      +116                ref mut finish_acked,
      +117            } => {
      +118                *finish_acked |= frame.fin;
      +119                *finish_acked && self.pending.is_fully_acked()
      +120            }
      +121            _ => false,
      +122        }
      +123    }
      +124
      +125    /// Handle increase to stream-level flow control limit
      +126    ///
      +127    /// Returns whether the stream was unblocked
      +128    pub(super) fn increase_max_data(&mut self, offset: u64) -> bool {
      +129        if offset <= self.max_data || self.state != SendState::Ready {
      +130            return false;
      +131        }
      +132        let was_blocked = self.pending.offset() == self.max_data;
      +133        self.max_data = offset;
      +134        was_blocked
       135    }
       136
      -137    pub(super) fn is_pending(&self) -> bool {
      -138        self.pending.has_unsent_data() || self.fin_pending
      +137    pub(super) fn offset(&self) -> u64 {
      +138        self.pending.offset()
       139    }
       140
      -141    pub(super) fn is_writable(&self) -> bool {
      -142        matches!(self.state, SendState::Ready)
      +141    pub(super) fn is_pending(&self) -> bool {
      +142        self.pending.has_unsent_data() || self.fin_pending
       143    }
      -144}
      -145
      -146/// A [`BytesSource`] implementation for `&'a mut [Bytes]`
      -147///
      -148/// The type allows to dequeue [`Bytes`] chunks from an array of chunks, up to
      -149/// a configured limit.
      -150pub(crate) struct BytesArray<'a> {
      -151    /// The wrapped slice of `Bytes`
      -152    chunks: &'a mut [Bytes],
      -153    /// The amount of chunks consumed from this source
      -154    consumed: usize,
      -155}
      -156
      -157impl<'a> BytesArray<'a> {
      -158    pub(crate) fn from_chunks(chunks: &'a mut [Bytes]) -> Self {
      -159        Self {
      -160            chunks,
      -161            consumed: 0,
      -162        }
      -163    }
      -164}
      -165
      -166impl BytesSource for BytesArray<'_> {
      -167    fn pop_chunk(&mut self, limit: usize) -> (Bytes, usize) {
      -168        // The loop exists to skip empty chunks while still marking them as
      -169        // consumed
      -170        let mut chunks_consumed = 0;
      -171
      -172        while self.consumed < self.chunks.len() {
      -173            let chunk = &mut self.chunks[self.consumed];
      -174
      -175            if chunk.len() <= limit {
      -176                let chunk = std::mem::take(chunk);
      -177                self.consumed += 1;
      -178                chunks_consumed += 1;
      -179                if chunk.is_empty() {
      -180                    continue;
      -181                }
      -182                return (chunk, chunks_consumed);
      -183            } else if limit > 0 {
      -184                let chunk = chunk.split_to(limit);
      -185                return (chunk, chunks_consumed);
      -186            } else {
      -187                break;
      -188            }
      -189        }
      -190
      -191        (Bytes::new(), chunks_consumed)
      -192    }
      -193}
      -194
      -195/// A [`BytesSource`] implementation for `&[u8]`
      -196///
      -197/// The type allows to dequeue a single [`Bytes`] chunk, which will be lazily
      -198/// created from a reference. This allows to defer the allocation until it is
      -199/// known how much data needs to be copied.
      -200pub(crate) struct ByteSlice<'a> {
      -201    /// The wrapped byte slice
      -202    data: &'a [u8],
      -203}
      -204
      -205impl<'a> ByteSlice<'a> {
      -206    pub(crate) fn from_slice(data: &'a [u8]) -> Self {
      -207        Self { data }
      -208    }
      -209}
      -210
      -211impl BytesSource for ByteSlice<'_> {
      -212    fn pop_chunk(&mut self, limit: usize) -> (Bytes, usize) {
      -213        let limit = limit.min(self.data.len());
      -214        if limit == 0 {
      -215            return (Bytes::new(), 0);
      -216        }
      +144
      +145    pub(super) fn is_writable(&self) -> bool {
      +146        matches!(self.state, SendState::Ready)
      +147    }
      +148}
      +149
      +150/// A [`BytesSource`] implementation for `&'a mut [Bytes]`
      +151///
      +152/// The type allows to dequeue [`Bytes`] chunks from an array of chunks, up to
      +153/// a configured limit.
      +154pub(crate) struct BytesArray<'a> {
      +155    /// The wrapped slice of `Bytes`
      +156    chunks: &'a mut [Bytes],
      +157    /// The amount of chunks consumed from this source
      +158    consumed: usize,
      +159}
      +160
      +161impl<'a> BytesArray<'a> {
      +162    pub(crate) fn from_chunks(chunks: &'a mut [Bytes]) -> Self {
      +163        Self {
      +164            chunks,
      +165            consumed: 0,
      +166        }
      +167    }
      +168}
      +169
      +170impl<'a> BytesSource<'a> for BytesArray<'a> {
      +171    fn pop_chunk<'b>(&'b mut self, limit: usize) -> (impl BytesOrSlice<'b>, usize)
      +172    where
      +173        'a: 'b,
      +174    {
      +175        // The loop exists to skip empty chunks while still marking them as
      +176        // consumed
      +177        let mut chunks_consumed = 0;
      +178
      +179        while self.consumed < self.chunks.len() {
      +180            let chunk = &mut self.chunks[self.consumed];
      +181
      +182            if chunk.len() <= limit {
      +183                let chunk = std::mem::take(chunk);
      +184                self.consumed += 1;
      +185                chunks_consumed += 1;
      +186                if chunk.is_empty() {
      +187                    continue;
      +188                }
      +189                return (chunk, chunks_consumed);
      +190            } else if limit > 0 {
      +191                let chunk = chunk.split_to(limit);
      +192                return (chunk, chunks_consumed);
      +193            } else {
      +194                break;
      +195            }
      +196        }
      +197
      +198        (Bytes::new(), chunks_consumed)
      +199    }
      +200}
      +201
      +202/// A [`BytesSource`] implementation for `&[u8]`
      +203///
      +204/// The type allows to dequeue a single [`Bytes`] chunk, which will be lazily
      +205/// created from a reference. This allows to defer the allocation until it is
      +206/// known how much data needs to be copied.
      +207pub(crate) struct ByteSlice<'a> {
      +208    /// The wrapped byte slice
      +209    data: &'a [u8],
      +210}
      +211
      +212impl<'a> ByteSlice<'a> {
      +213    pub(crate) fn from_slice(data: &'a [u8]) -> Self {
      +214        Self { data }
      +215    }
      +216}
       217
      -218        let chunk = Bytes::from(self.data[..limit].to_owned());
      -219        self.data = &self.data[chunk.len()..];
      -220
      -221        let chunks_consumed = usize::from(self.data.is_empty());
      -222        (chunk, chunks_consumed)
      -223    }
      -224}
      -225
      -226/// A source of one or more buffers which can be converted into `Bytes` buffers on demand
      -227///
      -228/// The purpose of this data type is to defer conversion as long as possible,
      -229/// so that no heap allocation is required in case no data is writable.
      -230pub(super) trait BytesSource {
      -231    /// Returns the next chunk from the source of owned chunks.
      -232    ///
      -233    /// This method will consume parts of the source.
      -234    /// Calling it will yield `Bytes` elements up to the configured `limit`.
      -235    ///
      -236    /// The method returns a tuple:
      -237    /// - The first item is the yielded `Bytes` element. The element will be
      -238    ///   empty if the limit is zero or no more data is available.
      -239    /// - The second item returns how many complete chunks inside the source had
      -240    ///   had been consumed. This can be less than 1, if a chunk inside the
      -241    ///   source had been truncated in order to adhere to the limit. It can also
      -242    ///   be more than 1, if zero-length chunks had been skipped.
      -243    fn pop_chunk(&mut self, limit: usize) -> (Bytes, usize);
      -244}
      -245
      -246/// Indicates how many bytes and chunks had been transferred in a write operation
      -247#[derive(Debug, Default, PartialEq, Eq, Clone, Copy)]
      -248pub struct Written {
      -249    /// The amount of bytes which had been written
      -250    pub bytes: usize,
      -251    /// The amount of full chunks which had been written
      -252    ///
      -253    /// If a chunk was only partially written, it will not be counted by this field.
      -254    pub chunks: usize,
      -255}
      -256
      -257/// Errors triggered while writing to a send stream
      -258#[derive(Debug, Error, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
      -259pub enum WriteError {
      -260    /// The peer is not able to accept additional data, or the connection is congested.
      -261    ///
      -262    /// If the peer issues additional flow control credit, a [`StreamEvent::Writable`] event will
      -263    /// be generated, indicating that retrying the write might succeed.
      +218impl<'a> BytesSource<'a> for ByteSlice<'a> {
      +219    fn pop_chunk<'b>(&'b mut self, limit: usize) -> (impl BytesOrSlice<'b>, usize)
      +220    where
      +221        'a: 'b,
      +222    {
      +223        let limit = limit.min(self.data.len());
      +224        if limit == 0 {
      +225            return (&[][..], 0);
      +226        }
      +227
      +228        let chunk = &self.data[..limit];
      +229        self.data = &self.data[chunk.len()..];
      +230
      +231        let chunks_consumed = usize::from(self.data.is_empty());
      +232        (chunk, chunks_consumed)
      +233    }
      +234}
      +235
      +236/// A source of one or more buffers which can be converted into `Bytes` buffers on demand
      +237///
      +238/// The purpose of this data type is to defer conversion as long as possible,
      +239/// so that no heap allocation is required in case no data is writable.
      +240pub(super) trait BytesSource<'a> {
      +241    /// Returns the next chunk from the source of owned chunks.
      +242    ///
      +243    /// This method will consume parts of the source.
      +244    /// Calling it will yield `Bytes` elements up to the configured `limit`.
      +245    ///
      +246    /// The method returns a tuple:
      +247    /// - The first item is the yielded `Bytes` element. The element will be
      +248    ///   empty if the limit is zero or no more data is available.
      +249    /// - The second item returns how many complete chunks inside the source had
      +250    ///   had been consumed. This can be less than 1, if a chunk inside the
      +251    ///   source had been truncated in order to adhere to the limit. It can also
      +252    ///   be more than 1, if zero-length chunks had been skipped.
      +253    fn pop_chunk<'b>(&'b mut self, limit: usize) -> (impl BytesOrSlice<'b>, usize)
      +254    where
      +255        'a: 'b;
      +256}
      +257
      +258/// Indicates how many bytes and chunks had been transferred in a write operation
      +259#[derive(Debug, Default, PartialEq, Eq, Clone, Copy)]
      +260pub struct Written {
      +261    /// The amount of bytes which had been written
      +262    pub bytes: usize,
      +263    /// The amount of full chunks which had been written
       264    ///
      -265    /// [`StreamEvent::Writable`]: crate::StreamEvent::Writable
      -266    #[error("unable to accept further writes")]
      -267    Blocked,
      -268    /// The peer is no longer accepting data on this stream, and it has been implicitly reset. The
      -269    /// stream cannot be finished or further written to.
      -270    ///
      -271    /// Carries an application-defined error code.
      -272    ///
      -273    /// [`StreamEvent::Finished`]: crate::StreamEvent::Finished
      -274    #[error("stopped by peer: code {0}")]
      -275    Stopped(VarInt),
      -276    /// The stream has not been opened or has already been finished or reset
      -277    #[error("closed stream")]
      -278    ClosedStream,
      -279}
      -280
      -281#[derive(Debug, Copy, Clone, Eq, PartialEq)]
      -282pub(super) enum SendState {
      -283    /// Sending new data
      -284    Ready,
      -285    /// Stream was finished; now sending retransmits only
      -286    DataSent { finish_acked: bool },
      -287    /// Sent RESET
      -288    ResetSent,
      -289}
      -290
      -291/// Reasons why attempting to finish a stream might fail
      -292#[derive(Debug, Error, Clone, PartialEq, Eq)]
      -293pub enum FinishError {
      -294    /// The peer is no longer accepting data on this stream. No
      -295    /// [`StreamEvent::Finished`] event will be emitted for this stream.
      -296    ///
      -297    /// Carries an application-defined error code.
      -298    ///
      -299    /// [`StreamEvent::Finished`]: crate::StreamEvent::Finished
      -300    #[error("stopped by peer: code {0}")]
      -301    Stopped(VarInt),
      -302    /// The stream has not been opened or was already finished or reset
      -303    #[error("closed stream")]
      -304    ClosedStream,
      -305}
      -306
      -307#[cfg(test)]
      -308mod tests {
      -309    use super::*;
      -310
      -311    #[test]
      -312    fn bytes_array() {
      -313        let full = b"Hello World 123456789 ABCDEFGHJIJKLMNOPQRSTUVWXYZ".to_owned();
      -314        for limit in 0..full.len() {
      -315            let mut chunks = [
      -316                Bytes::from_static(b""),
      -317                Bytes::from_static(b"Hello "),
      -318                Bytes::from_static(b"Wo"),
      -319                Bytes::from_static(b""),
      -320                Bytes::from_static(b"r"),
      -321                Bytes::from_static(b"ld"),
      -322                Bytes::from_static(b""),
      -323                Bytes::from_static(b" 12345678"),
      -324                Bytes::from_static(b"9 ABCDE"),
      -325                Bytes::from_static(b"F"),
      -326                Bytes::from_static(b"GHJIJKLMNOPQRSTUVWXYZ"),
      -327            ];
      -328            let num_chunks = chunks.len();
      -329            let last_chunk_len = chunks[chunks.len() - 1].len();
      -330
      -331            let mut array = BytesArray::from_chunks(&mut chunks);
      -332
      -333            let mut buf = Vec::new();
      -334            let mut chunks_popped = 0;
      -335            let mut chunks_consumed = 0;
      -336            let mut remaining = limit;
      -337            loop {
      -338                let (chunk, consumed) = array.pop_chunk(remaining);
      -339                chunks_consumed += consumed;
      -340
      -341                if !chunk.is_empty() {
      -342                    buf.extend_from_slice(&chunk);
      -343                    remaining -= chunk.len();
      -344                    chunks_popped += 1;
      -345                } else {
      -346                    break;
      -347                }
      -348            }
      -349
      -350            assert_eq!(&buf[..], &full[..limit]);
      -351
      -352            if limit == full.len() {
      -353                // Full consumption of the last chunk
      -354                assert_eq!(chunks_consumed, num_chunks);
      -355                // Since there are empty chunks, we consume more than there are popped
      -356                assert_eq!(chunks_consumed, chunks_popped + 3);
      -357            } else if limit > full.len() - last_chunk_len {
      -358                // Partial consumption of the last chunk
      -359                assert_eq!(chunks_consumed, num_chunks - 1);
      -360                assert_eq!(chunks_consumed, chunks_popped + 2);
      -361            }
      -362        }
      -363    }
      -364
      -365    #[test]
      -366    fn byte_slice() {
      -367        let full = b"Hello World 123456789 ABCDEFGHJIJKLMNOPQRSTUVWXYZ".to_owned();
      -368        for limit in 0..full.len() {
      -369            let mut array = ByteSlice::from_slice(&full[..]);
      -370
      -371            let mut buf = Vec::new();
      -372            let mut chunks_popped = 0;
      -373            let mut chunks_consumed = 0;
      -374            let mut remaining = limit;
      -375            loop {
      -376                let (chunk, consumed) = array.pop_chunk(remaining);
      -377                chunks_consumed += consumed;
      -378
      -379                if !chunk.is_empty() {
      -380                    buf.extend_from_slice(&chunk);
      -381                    remaining -= chunk.len();
      -382                    chunks_popped += 1;
      -383                } else {
      -384                    break;
      -385                }
      -386            }
      -387
      -388            assert_eq!(&buf[..], &full[..limit]);
      -389            if limit != 0 {
      -390                assert_eq!(chunks_popped, 1);
      -391            } else {
      -392                assert_eq!(chunks_popped, 0);
      -393            }
      -394
      -395            if limit == full.len() {
      -396                assert_eq!(chunks_consumed, 1);
      -397            } else {
      -398                assert_eq!(chunks_consumed, 0);
      -399            }
      -400        }
      -401    }
      -402}
      \ No newline at end of file +265 /// If a chunk was only partially written, it will not be counted by this field. +266 pub chunks: usize, +267} +268 +269/// Errors triggered while writing to a send stream +270#[derive(Debug, Error, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] +271pub enum WriteError { +272 /// The peer is not able to accept additional data, or the connection is congested. +273 /// +274 /// If the peer issues additional flow control credit, a [`StreamEvent::Writable`] event will +275 /// be generated, indicating that retrying the write might succeed. +276 /// +277 /// [`StreamEvent::Writable`]: crate::StreamEvent::Writable +278 #[error("unable to accept further writes")] +279 Blocked, +280 /// The peer is no longer accepting data on this stream, and it has been implicitly reset. The +281 /// stream cannot be finished or further written to. +282 /// +283 /// Carries an application-defined error code. +284 /// +285 /// [`StreamEvent::Finished`]: crate::StreamEvent::Finished +286 #[error("stopped by peer: code {0}")] +287 Stopped(VarInt), +288 /// The stream has not been opened or has already been finished or reset +289 #[error("closed stream")] +290 ClosedStream, +291} +292 +293#[derive(Debug, Copy, Clone, Eq, PartialEq)] +294pub(super) enum SendState { +295 /// Sending new data +296 Ready, +297 /// Stream was finished; now sending retransmits only +298 DataSent { finish_acked: bool }, +299 /// Sent RESET +300 ResetSent, +301} +302 +303/// Reasons why attempting to finish a stream might fail +304#[derive(Debug, Error, Clone, PartialEq, Eq)] +305pub enum FinishError { +306 /// The peer is no longer accepting data on this stream. No +307 /// [`StreamEvent::Finished`] event will be emitted for this stream. +308 /// +309 /// Carries an application-defined error code. +310 /// +311 /// [`StreamEvent::Finished`]: crate::StreamEvent::Finished +312 #[error("stopped by peer: code {0}")] +313 Stopped(VarInt), +314 /// The stream has not been opened or was already finished or reset +315 #[error("closed stream")] +316 ClosedStream, +317} +318 +319#[cfg(test)] +320mod tests { +321 use super::*; +322 +323 #[test] +324 fn bytes_array() { +325 let full = b"Hello World 123456789 ABCDEFGHJIJKLMNOPQRSTUVWXYZ".to_owned(); +326 for limit in 0..full.len() { +327 let mut chunks = [ +328 Bytes::from_static(b""), +329 Bytes::from_static(b"Hello "), +330 Bytes::from_static(b"Wo"), +331 Bytes::from_static(b""), +332 Bytes::from_static(b"r"), +333 Bytes::from_static(b"ld"), +334 Bytes::from_static(b""), +335 Bytes::from_static(b" 12345678"), +336 Bytes::from_static(b"9 ABCDE"), +337 Bytes::from_static(b"F"), +338 Bytes::from_static(b"GHJIJKLMNOPQRSTUVWXYZ"), +339 ]; +340 let num_chunks = chunks.len(); +341 let last_chunk_len = chunks[chunks.len() - 1].len(); +342 +343 let mut array = BytesArray::from_chunks(&mut chunks); +344 +345 let mut buf = Vec::new(); +346 let mut chunks_popped = 0; +347 let mut chunks_consumed = 0; +348 let mut remaining = limit; +349 loop { +350 let (chunk, consumed) = array.pop_chunk(remaining); +351 chunks_consumed += consumed; +352 +353 if !chunk.is_empty() { +354 buf.extend_from_slice(chunk.as_ref()); +355 remaining -= chunk.len(); +356 chunks_popped += 1; +357 } else { +358 break; +359 } +360 } +361 +362 assert_eq!(&buf[..], &full[..limit]); +363 +364 if limit == full.len() { +365 // Full consumption of the last chunk +366 assert_eq!(chunks_consumed, num_chunks); +367 // Since there are empty chunks, we consume more than there are popped +368 assert_eq!(chunks_consumed, chunks_popped + 3); +369 } else if limit > full.len() - last_chunk_len { +370 // Partial consumption of the last chunk +371 assert_eq!(chunks_consumed, num_chunks - 1); +372 assert_eq!(chunks_consumed, chunks_popped + 2); +373 } +374 } +375 } +376 +377 #[test] +378 fn byte_slice() { +379 let full = b"Hello World 123456789 ABCDEFGHJIJKLMNOPQRSTUVWXYZ".to_owned(); +380 for limit in 0..full.len() { +381 let mut array = ByteSlice::from_slice(&full[..]); +382 +383 let mut buf = Vec::new(); +384 let mut chunks_popped = 0; +385 let mut chunks_consumed = 0; +386 let mut remaining = limit; +387 loop { +388 let (chunk, consumed) = array.pop_chunk(remaining); +389 chunks_consumed += consumed; +390 +391 if !chunk.is_empty() { +392 buf.extend_from_slice(chunk.as_ref()); +393 remaining -= chunk.len(); +394 chunks_popped += 1; +395 } else { +396 break; +397 } +398 } +399 +400 assert_eq!(&buf[..], &full[..limit]); +401 if limit != 0 { +402 assert_eq!(chunks_popped, 1); +403 } else { +404 assert_eq!(chunks_popped, 0); +405 } +406 +407 if limit == full.len() { +408 assert_eq!(chunks_consumed, 1); +409 } else { +410 assert_eq!(chunks_consumed, 0); +411 } +412 } +413 } +414}
      \ No newline at end of file diff --git a/pr/255/docs/src/iroh_quinn_proto/frame.rs.html b/pr/255/docs/src/iroh_quinn_proto/frame.rs.html index be85b8d73..1b521222d 100644 --- a/pr/255/docs/src/iroh_quinn_proto/frame.rs.html +++ b/pr/255/docs/src/iroh_quinn_proto/frame.rs.html @@ -20,2233 +20,2272 @@ 20#[cfg(feature = "arbitrary")] 21use arbitrary::Arbitrary; 22 -23/// Generates the [`FrameType`] enum, and its associated conversions from and to u64 -24macro_rules! frame_types { -25 // Process the unit variants. -26 (enum_defs: [$($enum_defs: tt)*] try_from_arms: [$($try_from_arms: tt)*] to_u64_arms:[$($to_u64_arms: tt)*] // accumulators -27 $variant: ident = $value: literal, // VariantName = value, -28 $($token: tt)*) => { -29 frame_types!{ -30 enum_defs: [$($enum_defs)* $variant,] -31 try_from_arms: [$($try_from_arms)* $value => Self::$variant,] -32 to_u64_arms: [$($to_u64_arms)* FrameType::$variant => $value,] -33 $($token)* -34 } -35 }; -36 -37 // Process the tuple variants. -38 (enum_defs: [$($enum_defs: tt)*] try_from_arms: [$($try_from_arms: tt)*] to_u64_arms:[$($to_u64_arms: tt)*] // accumulators -39 $variant: ident($inner: ident), // VariantName(InnerType), -40 $($token: tt)*) => { -41 frame_types!{ -42 enum_defs: [$($enum_defs)* $variant($inner),] -43 try_from_arms: [$($try_from_arms)* value if <$inner>::VALUES.contains(&value) => Self::$variant($inner(value as u8)),] -44 to_u64_arms: [$($to_u64_arms)* FrameType::$variant($inner(value)) => value as u64,] -45 $($token)* -46 } -47 }; -48 -49 // Final generation step. -50 (enum_defs: [$($enum_defs: tt)+] try_from_arms: [$($try_from_arms: tt)+] to_u64_arms: [$($to_u64_arms: tt)+]) => { -51 /// A QUIC frame type -52 #[derive(Copy, Clone, Eq, PartialEq, derive_more::Debug, derive_more::Display)] -53 #[display(rename_all = "SCREAMING_SNAKE_CASE")] -54 #[allow(missing_docs)] -55 pub enum FrameType { -56 $($enum_defs)* -57 } -58 -59 pub struct InvalidFrameId(u64); -60 -61 impl TryFrom<u64> for FrameType { -62 type Error = InvalidFrameId; -63 fn try_from(value: u64) -> Result<Self, Self::Error> { -64 Ok(match value { -65 $($try_from_arms)* -66 other => return Err(InvalidFrameId(other)) -67 }) -68 } -69 } -70 -71 impl FrameType { -72 pub(crate) const fn to_u64(self) -> u64 { -73 match self { -74 $($to_u64_arms)* -75 } -76 } -77 } -78 }; -79} -80 -81frame_types! { -82 enum_defs: [] -83 try_from_arms: [] -84 to_u64_arms: [] -85 Padding = 0x00, -86 Ping = 0x01, -87 Ack = 0x02, -88 AckEcn = 0x03, -89 ResetStream = 0x04, -90 StopSending = 0x05, -91 Crypto = 0x06, -92 NewToken = 0x07, -93 // STREAM -94 Stream(StreamInfo), -95 MaxData = 0x10, -96 MaxStreamData = 0x11, -97 MaxStreamsBidi = 0x12, -98 MaxStreamsUni = 0x13, -99 DataBlocked = 0x14, -100 StreamDataBlocked = 0x15, -101 StreamsBlockedBidi = 0x16, -102 StreamsBlockedUni = 0x17, -103 NewConnectionId = 0x18, -104 RetireConnectionId = 0x19, -105 PathChallenge = 0x1a, -106 PathResponse = 0x1b, -107 ConnectionClose = 0x1c, -108 ApplicationClose = 0x1d, -109 HandshakeDone = 0x1e, -110 // ACK Frequency -111 AckFrequency = 0xaf, -112 ImmediateAck = 0x1f, -113 // DATAGRAM -114 Datagram(DatagramInfo), -115 // ADDRESS DISCOVERY REPORT -116 ObservedIpv4Addr = 0x9f81a6, -117 ObservedIpv6Addr = 0x9f81a7, -118 // Multipath -119 PathAck = 0x15228c00, -120 PathAckEcn = 0x15228c01, -121 PathAbandon = 0x15228c05, -122 PathStatusBackup = 0x15228c07, -123 PathStatusAvailable = 0x15228c08, -124 PathNewConnectionId = 0x15228c09, -125 PathRetireConnectionId = 0x15228c0a, -126 MaxPathId = 0x15228c0c, -127 PathsBlocked = 0x15228c0d, -128 PathCidsBlocked = 0x15228c0e, -129 // IROH'S NAT TRAVERSAL -130 AddIpv4Address = 0x3d7f90, -131 AddIpv6Address = 0x3d7f91, -132 ReachOutAtIpv4 = 0x3d7f92, -133 ReachOutAtIpv6 = 0x3d7f93, -134 RemoveAddress = 0x3d7f94, -135} -136 -137impl FrameType { -138 /// The encoded size of this [`FrameType`]. -139 const fn size(&self) -> usize { -140 VarInt(self.to_u64()).size() -141 } -142} -143 -144impl Decodable for FrameType { -145 fn decode<B: Buf>(buf: &mut B) -> coding::Result<Self> { -146 Self::try_from(buf.get_var()?).map_err(|_| coding::UnexpectedEnd) +23#[derive( +24 Copy, Clone, Eq, PartialEq, derive_more::Debug, derive_more::Display, enum_assoc::Assoc, +25)] +26#[display(rename_all = "SCREAMING_SNAKE_CASE")] +27#[allow(missing_docs)] +28#[func( +29 pub(crate) const fn to_u64(self) -> u64, +30 const fn from_u64(rev: u64) -> Option<Self>, +31)] +32pub enum FrameType { +33 #[assoc(to_u64 = 0x00)] +34 Padding, +35 #[assoc(to_u64 = 0x01)] +36 Ping, +37 #[assoc(to_u64 = 0x02)] +38 Ack, +39 #[assoc(to_u64 = 0x03)] +40 AckEcn, +41 #[assoc(to_u64 = 0x04)] +42 ResetStream, +43 #[assoc(to_u64 = 0x05)] +44 StopSending, +45 #[assoc(to_u64 = 0x06)] +46 Crypto, +47 #[assoc(to_u64 = 0x07)] +48 NewToken, +49 // STREAM +50 #[assoc(to_u64 = _0.to_u64())] +51 Stream(StreamInfo), +52 #[assoc(to_u64 = 0x10)] +53 MaxData, +54 #[assoc(to_u64 = 0x11)] +55 MaxStreamData, +56 #[assoc(to_u64 = 0x12)] +57 MaxStreamsBidi, +58 #[assoc(to_u64 = 0x13)] +59 MaxStreamsUni, +60 #[assoc(to_u64 = 0x14)] +61 DataBlocked, +62 #[assoc(to_u64 = 0x15)] +63 StreamDataBlocked, +64 #[assoc(to_u64 = 0x16)] +65 StreamsBlockedBidi, +66 #[assoc(to_u64 = 0x17)] +67 StreamsBlockedUni, +68 #[assoc(to_u64 = 0x18)] +69 NewConnectionId, +70 #[assoc(to_u64 = 0x19)] +71 RetireConnectionId, +72 #[assoc(to_u64 = 0x1a)] +73 PathChallenge, +74 #[assoc(to_u64 = 0x1b)] +75 PathResponse, +76 #[assoc(to_u64 = 0x1c)] +77 ConnectionClose, +78 #[assoc(to_u64 = 0x1d)] +79 ApplicationClose, +80 #[assoc(to_u64 = 0x1e)] +81 HandshakeDone, +82 // ACK Frequency +83 #[assoc(to_u64 = 0xaf)] +84 AckFrequency, +85 #[assoc(to_u64 = 0x1f)] +86 ImmediateAck, +87 // DATAGRAM +88 #[assoc(to_u64 = _0.to_u64())] +89 Datagram(DatagramInfo), +90 // ADDRESS DISCOVERY REPORT +91 #[assoc(to_u64 = 0x9f81a6)] +92 ObservedIpv4Addr, +93 #[assoc(to_u64 = 0x9f81a7)] +94 ObservedIpv6Addr, +95 // Multipath +96 #[assoc(to_u64 = 0x15228c00)] +97 PathAck, +98 #[assoc(to_u64 = 0x15228c01)] +99 PathAckEcn, +100 #[assoc(to_u64 = 0x15228c05)] +101 PathAbandon, +102 #[assoc(to_u64 = 0x15228c07)] +103 PathStatusBackup, +104 #[assoc(to_u64 = 0x15228c08)] +105 PathStatusAvailable, +106 #[assoc(to_u64 = 0x15228c09)] +107 PathNewConnectionId, +108 #[assoc(to_u64 = 0x15228c0a)] +109 PathRetireConnectionId, +110 #[assoc(to_u64 = 0x15228c0c)] +111 MaxPathId, +112 #[assoc(to_u64 = 0x15228c0d)] +113 PathsBlocked, +114 #[assoc(to_u64 = 0x15228c0e)] +115 PathCidsBlocked, +116 // IROH'S NAT TRAVERSAL +117 #[assoc(to_u64 = 0x3d7f90)] +118 AddIpv4Address, +119 #[assoc(to_u64 = 0x3d7f91)] +120 AddIpv6Address, +121 #[assoc(to_u64 = 0x3d7f92)] +122 ReachOutAtIpv4, +123 #[assoc(to_u64 = 0x3d7f93)] +124 ReachOutAtIpv6, +125 #[assoc(to_u64 = 0x3d7f94)] +126 RemoveAddress, +127} +128 +129#[derive(Debug, PartialEq, Eq)] +130pub struct InvalidFrameId(u64); +131 +132impl TryFrom<u64> for FrameType { +133 type Error = InvalidFrameId; +134 fn try_from(value: u64) -> Result<Self, Self::Error> { +135 match Self::from_u64(value) { +136 Some(t) => Ok(t), +137 None => { +138 if DatagramInfo::VALUES.contains(&value) { +139 return Ok(Self::Datagram(DatagramInfo(value as u8))); +140 } +141 if StreamInfo::VALUES.contains(&value) { +142 return Ok(Self::Stream(StreamInfo(value as u8))); +143 } +144 Err(InvalidFrameId(value)) +145 } +146 } 147 } 148} 149 -150impl Encodable for FrameType { -151 fn encode<B: BufMut>(&self, buf: &mut B) { -152 buf.write_var(self.to_u64()); -153 } -154} -155 -156pub(crate) trait FrameStruct { -157 /// Smallest number of bytes this type of frame is guaranteed to fit within. -158 const SIZE_BOUND: usize; -159} -160 -161/// The type used to refer to [`FrameType`]s in closing and transport errors. -162#[derive(Copy, Clone, Eq, PartialEq, derive_more::Debug, derive_more::Display)] -163pub enum MaybeFrame { -164 /// Not attributed to any particular [`FrameType`]. -165 None, -166 /// Attributed to some frame type this implementation does not recognize. -167 #[display("UNKNOWN{:02x}", _0)] -168 #[debug("Unknown{:02x}", _0)] -169 Unknown(u64), -170 /// Attributed to a specific [`FrameType`], never [`FrameType::Padding`]. -171 Known(FrameType), +150impl FrameType { +151 /// The encoded size of this [`FrameType`]. +152 const fn size(&self) -> usize { +153 VarInt(self.to_u64()).size() +154 } +155} +156 +157impl Decodable for FrameType { +158 fn decode<B: Buf>(buf: &mut B) -> coding::Result<Self> { +159 Self::try_from(buf.get_var()?).map_err(|_| coding::UnexpectedEnd) +160 } +161} +162 +163impl Encodable for FrameType { +164 fn encode<B: BufMut>(&self, buf: &mut B) { +165 buf.write_var(self.to_u64()); +166 } +167} +168 +169pub(crate) trait FrameStruct { +170 /// Smallest number of bytes this type of frame is guaranteed to fit within. +171 const SIZE_BOUND: usize; 172} 173 -174impl MaybeFrame { -175 /// Encoded size of this [`MaybeFrame`]. -176 const fn size(&self) -> usize { -177 match self { -178 Self::None => VarInt(0).size(), -179 Self::Unknown(other) => VarInt(*other).size(), -180 Self::Known(frame_type) => frame_type.size(), -181 } -182 } -183} -184 -185impl Decodable for MaybeFrame { -186 fn decode<B: Buf>(buf: &mut B) -> coding::Result<Self> { -187 match FrameType::try_from(buf.get_var()?) { -188 Ok(FrameType::Padding) => Ok(Self::None), -189 Ok(other_frame) => Ok(Self::Known(other_frame)), -190 Err(InvalidFrameId(other)) => Ok(Self::Unknown(other)), -191 } -192 } -193} -194 -195impl Encodable for MaybeFrame { -196 fn encode<B: BufMut>(&self, buf: &mut B) { -197 match self { -198 Self::None => buf.write(0u64), -199 Self::Unknown(frame_id) => buf.write(*frame_id), -200 Self::Known(frame_type) => buf.write(*frame_type), -201 } -202 } -203} -204 -205#[derive(Debug, Copy, Clone, Eq, PartialEq, derive_more::Display)] -206#[display("STREAM")] -207pub struct StreamInfo(u8); -208 -209impl StreamInfo { -210 const VALUES: RangeInclusive<u64> = RangeInclusive::new(0x08, 0x0f); -211 fn fin(self) -> bool { -212 self.0 & 0x01 != 0 -213 } -214 fn len(self) -> bool { -215 self.0 & 0x02 != 0 -216 } -217 fn off(self) -> bool { -218 self.0 & 0x04 != 0 -219 } -220} +174/// The type used to refer to [`FrameType`]s in closing and transport errors. +175#[derive(Copy, Clone, Eq, PartialEq, derive_more::Debug, derive_more::Display)] +176pub enum MaybeFrame { +177 /// Not attributed to any particular [`FrameType`]. +178 None, +179 /// Attributed to some frame type this implementation does not recognize. +180 #[display("UNKNOWN{:02x}", _0)] +181 #[debug("Unknown{:02x}", _0)] +182 Unknown(u64), +183 /// Attributed to a specific [`FrameType`], never [`FrameType::Padding`]. +184 Known(FrameType), +185} +186 +187impl MaybeFrame { +188 /// Encoded size of this [`MaybeFrame`]. +189 const fn size(&self) -> usize { +190 match self { +191 Self::None => VarInt(0).size(), +192 Self::Unknown(other) => VarInt(*other).size(), +193 Self::Known(frame_type) => frame_type.size(), +194 } +195 } +196} +197 +198impl Decodable for MaybeFrame { +199 fn decode<B: Buf>(buf: &mut B) -> coding::Result<Self> { +200 match FrameType::try_from(buf.get_var()?) { +201 Ok(FrameType::Padding) => Ok(Self::None), +202 Ok(other_frame) => Ok(Self::Known(other_frame)), +203 Err(InvalidFrameId(other)) => Ok(Self::Unknown(other)), +204 } +205 } +206} +207 +208impl Encodable for MaybeFrame { +209 fn encode<B: BufMut>(&self, buf: &mut B) { +210 match self { +211 Self::None => buf.write(0u64), +212 Self::Unknown(frame_id) => buf.write(*frame_id), +213 Self::Known(frame_type) => buf.write(*frame_type), +214 } +215 } +216} +217 +218#[derive(Debug, Copy, Clone, Eq, PartialEq, derive_more::Display)] +219#[display("STREAM")] +220pub struct StreamInfo(u8); 221 -222#[derive(Debug, Copy, Clone, Eq, PartialEq, derive_more::Display)] -223#[display("DATAGRAM")] -224pub struct DatagramInfo(u8); -225 -226impl DatagramInfo { -227 const VALUES: RangeInclusive<u64> = RangeInclusive::new(0x30, 0x31); -228 -229 fn len(self) -> bool { -230 self.0 & 0x01 != 0 -231 } -232} +222impl StreamInfo { +223 const VALUES: RangeInclusive<u64> = RangeInclusive::new(0x08, 0x0f); +224 fn fin(self) -> bool { +225 self.0 & 0x01 != 0 +226 } +227 fn len(self) -> bool { +228 self.0 & 0x02 != 0 +229 } +230 fn off(self) -> bool { +231 self.0 & 0x04 != 0 +232 } 233 -234#[derive(Debug)] -235pub(crate) enum Frame { -236 Padding, -237 Ping, -238 Ack(Ack), -239 PathAck(PathAck), -240 ResetStream(ResetStream), -241 StopSending(StopSending), -242 Crypto(Crypto), -243 NewToken(NewToken), -244 Stream(Stream), -245 MaxData(VarInt), -246 MaxStreamData { id: StreamId, offset: u64 }, -247 MaxStreams { dir: Dir, count: u64 }, -248 DataBlocked { offset: u64 }, -249 StreamDataBlocked { id: StreamId, offset: u64 }, -250 StreamsBlocked { dir: Dir, limit: u64 }, -251 NewConnectionId(NewConnectionId), -252 RetireConnectionId(RetireConnectionId), -253 PathChallenge(PathChallenge), -254 PathResponse(PathResponse), -255 Close(Close), -256 Datagram(Datagram), -257 AckFrequency(AckFrequency), -258 ImmediateAck, -259 HandshakeDone, -260 ObservedAddr(ObservedAddr), -261 PathAbandon(PathAbandon), -262 PathStatusAvailable(PathStatusAvailable), -263 PathStatusBackup(PathStatusBackup), -264 MaxPathId(MaxPathId), -265 PathsBlocked(PathsBlocked), -266 PathCidsBlocked(PathCidsBlocked), -267 AddAddress(AddAddress), -268 ReachOut(ReachOut), -269 RemoveAddress(RemoveAddress), -270} -271 -272impl fmt::Display for Frame { -273 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { -274 // Eventually all our frames will support fmt::Display and be able to be used to log -275 // consistently. For now we fall back to fmt::Debug. -276 match self { -277 Self::Padding => write!(f, "PADDING"), -278 Self::Ping => write!(f, "PING"), -279 Self::PathChallenge(frame) => write!(f, "{frame}"), -280 Self::PathResponse(frame) => write!(f, "{frame}"), -281 Self::ImmediateAck => write!(f, "IMMEDIATE_ACK"), -282 Self::HandshakeDone => write!(f, "HANDSHAKE_DONE"), -283 _ => write!(f, "{self:?}"), -284 } -285 } -286} -287 -288impl Frame { -289 pub(crate) fn ty(&self) -> FrameType { -290 use Frame::*; -291 match *self { -292 Padding => FrameType::Padding, -293 ResetStream(_) => FrameType::ResetStream, -294 Close(self::Close::Connection(_)) => FrameType::ConnectionClose, -295 Close(self::Close::Application(_)) => FrameType::ConnectionClose, -296 MaxData(_) => FrameType::MaxData, -297 MaxStreamData { .. } => FrameType::MaxStreamData, -298 MaxStreams { dir: Dir::Bi, .. } => FrameType::MaxStreamsBidi, -299 MaxStreams { dir: Dir::Uni, .. } => FrameType::MaxStreamsUni, -300 Ping => FrameType::Ping, -301 DataBlocked { .. } => FrameType::DataBlocked, -302 StreamDataBlocked { .. } => FrameType::StreamDataBlocked, -303 StreamsBlocked { dir: Dir::Bi, .. } => FrameType::StreamsBlockedBidi, -304 StreamsBlocked { dir: Dir::Uni, .. } => FrameType::StreamsBlockedUni, -305 StopSending { .. } => FrameType::StopSending, -306 RetireConnectionId { .. } => FrameType::RetireConnectionId, -307 Ack(_) => FrameType::Ack, -308 PathAck(_) => FrameType::PathAck, -309 Stream(ref x) => { -310 let mut ty = *StreamInfo::VALUES.start() as u8; -311 if x.fin { -312 ty |= 0x01; -313 } -314 if x.offset != 0 { -315 ty |= 0x04; -316 } -317 // TODO(@divma): move all this to getframetype for Stream -318 FrameType::Stream(StreamInfo(ty)) -319 } -320 PathChallenge(_) => FrameType::PathChallenge, -321 PathResponse(_) => FrameType::PathResponse, -322 NewConnectionId(cid) => cid.get_type(), -323 Crypto(_) => FrameType::Crypto, -324 NewToken(_) => FrameType::NewToken, -325 Datagram(_) => FrameType::Datagram(DatagramInfo(*DatagramInfo::VALUES.start() as u8)), -326 AckFrequency(_) => FrameType::AckFrequency, -327 ImmediateAck => FrameType::ImmediateAck, -328 HandshakeDone => FrameType::HandshakeDone, -329 ObservedAddr(ref observed) => observed.get_type(), -330 PathAbandon(_) => FrameType::PathAbandon, -331 PathStatusAvailable(_) => FrameType::PathStatusAvailable, -332 PathStatusBackup(_) => FrameType::PathStatusBackup, -333 MaxPathId(_) => FrameType::MaxPathId, -334 PathsBlocked(_) => FrameType::PathsBlocked, -335 PathCidsBlocked(_) => FrameType::PathCidsBlocked, -336 AddAddress(ref frame) => frame.get_type(), -337 ReachOut(ref frame) => frame.get_type(), -338 RemoveAddress(_) => self::RemoveAddress::TYPE, -339 } -340 } -341 -342 pub(crate) fn is_ack_eliciting(&self) -> bool { -343 !matches!( -344 *self, -345 Self::Ack(_) | Self::PathAck(_) | Self::Padding | Self::Close(_) -346 ) -347 } -348 -349 /// Returns `true` if this frame MUST be sent in 1-RTT space -350 pub(crate) fn is_1rtt(&self) -> bool { -351 // See also https://www.ietf.org/archive/id/draft-ietf-quic-multipath-17.html#section-4-1: -352 // > All frames defined in this document MUST only be sent in 1-RTT packets. -353 // > If an endpoint receives a multipath-specific frame in a different packet type, it MUST close the -354 // > connection with an error of type PROTOCOL_VIOLATION. -355 -356 self.is_multipath_frame() || self.is_qad_frame() -357 } -358 -359 fn is_qad_frame(&self) -> bool { -360 matches!(*self, Self::ObservedAddr(_)) +234 const fn to_u64(self) -> u64 { +235 self.0 as u64 +236 } +237} +238 +239#[derive(Debug, Copy, Clone, Eq, PartialEq, derive_more::Display)] +240#[display("DATAGRAM")] +241pub struct DatagramInfo(u8); +242 +243impl DatagramInfo { +244 const VALUES: RangeInclusive<u64> = RangeInclusive::new(0x30, 0x31); +245 +246 fn len(self) -> bool { +247 self.0 & 0x01 != 0 +248 } +249 +250 const fn to_u64(self) -> u64 { +251 self.0 as u64 +252 } +253} +254 +255#[derive(Debug)] +256pub(crate) enum Frame { +257 Padding, +258 Ping, +259 Ack(Ack), +260 PathAck(PathAck), +261 ResetStream(ResetStream), +262 StopSending(StopSending), +263 Crypto(Crypto), +264 NewToken(NewToken), +265 Stream(Stream), +266 MaxData(VarInt), +267 MaxStreamData { id: StreamId, offset: u64 }, +268 MaxStreams { dir: Dir, count: u64 }, +269 DataBlocked { offset: u64 }, +270 StreamDataBlocked { id: StreamId, offset: u64 }, +271 StreamsBlocked { dir: Dir, limit: u64 }, +272 NewConnectionId(NewConnectionId), +273 RetireConnectionId(RetireConnectionId), +274 PathChallenge(PathChallenge), +275 PathResponse(PathResponse), +276 Close(Close), +277 Datagram(Datagram), +278 AckFrequency(AckFrequency), +279 ImmediateAck, +280 HandshakeDone, +281 ObservedAddr(ObservedAddr), +282 PathAbandon(PathAbandon), +283 PathStatusAvailable(PathStatusAvailable), +284 PathStatusBackup(PathStatusBackup), +285 MaxPathId(MaxPathId), +286 PathsBlocked(PathsBlocked), +287 PathCidsBlocked(PathCidsBlocked), +288 AddAddress(AddAddress), +289 ReachOut(ReachOut), +290 RemoveAddress(RemoveAddress), +291} +292 +293impl fmt::Display for Frame { +294 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +295 // Eventually all our frames will support fmt::Display and be able to be used to log +296 // consistently. For now we fall back to fmt::Debug. +297 match self { +298 Self::Padding => write!(f, "PADDING"), +299 Self::Ping => write!(f, "PING"), +300 Self::PathChallenge(frame) => write!(f, "{frame}"), +301 Self::PathResponse(frame) => write!(f, "{frame}"), +302 Self::ImmediateAck => write!(f, "IMMEDIATE_ACK"), +303 Self::HandshakeDone => write!(f, "HANDSHAKE_DONE"), +304 _ => write!(f, "{self:?}"), +305 } +306 } +307} +308 +309impl Frame { +310 pub(crate) fn ty(&self) -> FrameType { +311 use Frame::*; +312 match *self { +313 Padding => FrameType::Padding, +314 ResetStream(_) => FrameType::ResetStream, +315 Close(self::Close::Connection(_)) => FrameType::ConnectionClose, +316 Close(self::Close::Application(_)) => FrameType::ConnectionClose, +317 MaxData(_) => FrameType::MaxData, +318 MaxStreamData { .. } => FrameType::MaxStreamData, +319 MaxStreams { dir: Dir::Bi, .. } => FrameType::MaxStreamsBidi, +320 MaxStreams { dir: Dir::Uni, .. } => FrameType::MaxStreamsUni, +321 Ping => FrameType::Ping, +322 DataBlocked { .. } => FrameType::DataBlocked, +323 StreamDataBlocked { .. } => FrameType::StreamDataBlocked, +324 StreamsBlocked { dir: Dir::Bi, .. } => FrameType::StreamsBlockedBidi, +325 StreamsBlocked { dir: Dir::Uni, .. } => FrameType::StreamsBlockedUni, +326 StopSending { .. } => FrameType::StopSending, +327 RetireConnectionId { .. } => FrameType::RetireConnectionId, +328 Ack(_) => FrameType::Ack, +329 PathAck(_) => FrameType::PathAck, +330 Stream(ref x) => { +331 let mut ty = *StreamInfo::VALUES.start() as u8; +332 if x.fin { +333 ty |= 0x01; +334 } +335 if x.offset != 0 { +336 ty |= 0x04; +337 } +338 // TODO(@divma): move all this to getframetype for Stream +339 FrameType::Stream(StreamInfo(ty)) +340 } +341 PathChallenge(_) => FrameType::PathChallenge, +342 PathResponse(_) => FrameType::PathResponse, +343 NewConnectionId(cid) => cid.get_type(), +344 Crypto(_) => FrameType::Crypto, +345 NewToken(_) => FrameType::NewToken, +346 Datagram(_) => FrameType::Datagram(DatagramInfo(*DatagramInfo::VALUES.start() as u8)), +347 AckFrequency(_) => FrameType::AckFrequency, +348 ImmediateAck => FrameType::ImmediateAck, +349 HandshakeDone => FrameType::HandshakeDone, +350 ObservedAddr(ref observed) => observed.get_type(), +351 PathAbandon(_) => FrameType::PathAbandon, +352 PathStatusAvailable(_) => FrameType::PathStatusAvailable, +353 PathStatusBackup(_) => FrameType::PathStatusBackup, +354 MaxPathId(_) => FrameType::MaxPathId, +355 PathsBlocked(_) => FrameType::PathsBlocked, +356 PathCidsBlocked(_) => FrameType::PathCidsBlocked, +357 AddAddress(ref frame) => frame.get_type(), +358 ReachOut(ref frame) => frame.get_type(), +359 RemoveAddress(_) => self::RemoveAddress::TYPE, +360 } 361 } 362 -363 fn is_multipath_frame(&self) -> bool { -364 matches!( +363 pub(crate) fn is_ack_eliciting(&self) -> bool { +364 !matches!( 365 *self, -366 Self::PathAck(_) -367 | Self::PathAbandon(_) -368 | Self::PathStatusBackup(_) -369 | Self::PathStatusAvailable(_) -370 | Self::MaxPathId(_) -371 | Self::PathsBlocked(_) -372 | Self::PathCidsBlocked(_) -373 | Self::NewConnectionId(NewConnectionId { -374 path_id: Some(_), -375 .. -376 }) -377 | Self::RetireConnectionId(RetireConnectionId { -378 path_id: Some(_), -379 .. -380 }) -381 ) +366 Self::Ack(_) | Self::PathAck(_) | Self::Padding | Self::Close(_) +367 ) +368 } +369 +370 /// Returns `true` if this frame MUST be sent in 1-RTT space +371 pub(crate) fn is_1rtt(&self) -> bool { +372 // See also https://www.ietf.org/archive/id/draft-ietf-quic-multipath-17.html#section-4-1: +373 // > All frames defined in this document MUST only be sent in 1-RTT packets. +374 // > If an endpoint receives a multipath-specific frame in a different packet type, it MUST close the +375 // > connection with an error of type PROTOCOL_VIOLATION. +376 +377 self.is_multipath_frame() || self.is_qad_frame() +378 } +379 +380 fn is_qad_frame(&self) -> bool { +381 matches!(*self, Self::ObservedAddr(_)) 382 } -383} -384 -385#[derive(Debug, Clone, Copy, PartialEq, Eq, derive_more::Display)] -386#[display("PATH_CHALLENGE({_0:08x})")] -387pub(crate) struct PathChallenge(pub(crate) u64); -388 -389impl PathChallenge { -390 pub(crate) const SIZE_BOUND: usize = 9; -391} -392impl Decodable for PathChallenge { -393 fn decode<B: Buf>(buf: &mut B) -> coding::Result<Self> { -394 Ok(Self(buf.get()?)) -395 } -396} -397impl Encodable for PathChallenge { -398 fn encode<B: BufMut>(&self, buf: &mut B) { -399 buf.write(FrameType::PathChallenge); -400 buf.write(self.0); -401 } -402} -403 -404#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, derive_more::Display)] -405#[display("PATH_RESPONSE({_0:08x})")] -406pub(crate) struct PathResponse(pub(crate) u64); -407 -408impl PathResponse { -409 pub(crate) const SIZE_BOUND: usize = 9; -410} -411 -412impl Decodable for PathResponse { -413 fn decode<B: Buf>(buf: &mut B) -> coding::Result<Self> { -414 Ok(Self(buf.get()?)) -415 } -416} -417impl Encodable for PathResponse { -418 fn encode<B: BufMut>(&self, buf: &mut B) { -419 buf.write(FrameType::PathResponse); -420 buf.write(self.0); -421 } -422} -423 -424#[derive(Debug, PartialEq, Eq)] -425pub(crate) struct RetireConnectionId { -426 pub(crate) path_id: Option<PathId>, -427 pub(crate) sequence: u64, -428} -429 -430impl RetireConnectionId { -431 /// Maximum size of this frame when the frame type is [`FrameType::RetireConnectionId`] -432 pub(crate) const SIZE_BOUND: usize = { -433 let type_len = FrameType::RetireConnectionId.size(); -434 let seq_max_len = 8usize; -435 type_len + seq_max_len -436 }; -437 -438 /// Maximum size of this frame when the frame type is [`FrameType::PathRetireConnectionId`] -439 pub(crate) const SIZE_BOUND_MULTIPATH: usize = { -440 let type_len = FrameType::PathRetireConnectionId.size(); -441 let path_id_len = VarInt::from_u32(u32::MAX).size(); -442 let seq_max_len = 8usize; -443 type_len + path_id_len + seq_max_len -444 }; -445 -446 /// Decode [`Self`] from the buffer, provided that the frame type has been verified (either -447 /// [`FrameType::PathRetireConnectionId`], or [`FrameType::RetireConnectionId`]) -448 pub(crate) fn decode<R: Buf>(bytes: &mut R, read_path: bool) -> coding::Result<Self> { -449 Ok(Self { -450 path_id: if read_path { Some(bytes.get()?) } else { None }, -451 sequence: bytes.get_var()?, -452 }) -453 } -454 -455 /// Get the [`FrameType`] for this [`RetireConnectionId`] -456 pub(crate) fn get_type(&self) -> FrameType { -457 if self.path_id.is_some() { -458 FrameType::PathRetireConnectionId -459 } else { -460 FrameType::RetireConnectionId -461 } -462 } -463 -464 /// Returns the maximum encoded size on the wire -465 /// -466 /// `path_retire_cid` determines whether this frame is a multipath frame. This is a rough upper -467 /// estimate, does not squeeze every last byte out. -468 pub(crate) const fn size_bound(path_retire_cid: bool) -> usize { -469 match path_retire_cid { -470 true => Self::SIZE_BOUND_MULTIPATH, -471 false => Self::SIZE_BOUND, -472 } -473 } -474} +383 +384 fn is_multipath_frame(&self) -> bool { +385 matches!( +386 *self, +387 Self::PathAck(_) +388 | Self::PathAbandon(_) +389 | Self::PathStatusBackup(_) +390 | Self::PathStatusAvailable(_) +391 | Self::MaxPathId(_) +392 | Self::PathsBlocked(_) +393 | Self::PathCidsBlocked(_) +394 | Self::NewConnectionId(NewConnectionId { +395 path_id: Some(_), +396 .. +397 }) +398 | Self::RetireConnectionId(RetireConnectionId { +399 path_id: Some(_), +400 .. +401 }) +402 ) +403 } +404} +405 +406#[derive(Debug, Clone, Copy, PartialEq, Eq, derive_more::Display)] +407#[display("PATH_CHALLENGE({_0:08x})")] +408pub(crate) struct PathChallenge(pub(crate) u64); +409 +410impl PathChallenge { +411 pub(crate) const SIZE_BOUND: usize = 9; +412} +413impl Decodable for PathChallenge { +414 fn decode<B: Buf>(buf: &mut B) -> coding::Result<Self> { +415 Ok(Self(buf.get()?)) +416 } +417} +418impl Encodable for PathChallenge { +419 fn encode<B: BufMut>(&self, buf: &mut B) { +420 buf.write(FrameType::PathChallenge); +421 buf.write(self.0); +422 } +423} +424 +425#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, derive_more::Display)] +426#[display("PATH_RESPONSE({_0:08x})")] +427pub(crate) struct PathResponse(pub(crate) u64); +428 +429impl PathResponse { +430 pub(crate) const SIZE_BOUND: usize = 9; +431} +432 +433impl Decodable for PathResponse { +434 fn decode<B: Buf>(buf: &mut B) -> coding::Result<Self> { +435 Ok(Self(buf.get()?)) +436 } +437} +438impl Encodable for PathResponse { +439 fn encode<B: BufMut>(&self, buf: &mut B) { +440 buf.write(FrameType::PathResponse); +441 buf.write(self.0); +442 } +443} +444 +445#[derive(Debug, PartialEq, Eq)] +446pub(crate) struct RetireConnectionId { +447 pub(crate) path_id: Option<PathId>, +448 pub(crate) sequence: u64, +449} +450 +451impl RetireConnectionId { +452 /// Maximum size of this frame when the frame type is [`FrameType::RetireConnectionId`] +453 pub(crate) const SIZE_BOUND: usize = { +454 let type_len = FrameType::RetireConnectionId.size(); +455 let seq_max_len = 8usize; +456 type_len + seq_max_len +457 }; +458 +459 /// Maximum size of this frame when the frame type is [`FrameType::PathRetireConnectionId`] +460 pub(crate) const SIZE_BOUND_MULTIPATH: usize = { +461 let type_len = FrameType::PathRetireConnectionId.size(); +462 let path_id_len = VarInt::from_u32(u32::MAX).size(); +463 let seq_max_len = 8usize; +464 type_len + path_id_len + seq_max_len +465 }; +466 +467 /// Decode [`Self`] from the buffer, provided that the frame type has been verified (either +468 /// [`FrameType::PathRetireConnectionId`], or [`FrameType::RetireConnectionId`]) +469 pub(crate) fn decode<R: Buf>(bytes: &mut R, read_path: bool) -> coding::Result<Self> { +470 Ok(Self { +471 path_id: if read_path { Some(bytes.get()?) } else { None }, +472 sequence: bytes.get_var()?, +473 }) +474 } 475 -476impl Encodable for RetireConnectionId { -477 fn encode<W: BufMut>(&self, buf: &mut W) { -478 buf.write(self.get_type()); -479 if let Some(id) = self.path_id { -480 buf.write(id); -481 } -482 buf.write_var(self.sequence); +476 /// Get the [`FrameType`] for this [`RetireConnectionId`] +477 pub(crate) fn get_type(&self) -> FrameType { +478 if self.path_id.is_some() { +479 FrameType::PathRetireConnectionId +480 } else { +481 FrameType::RetireConnectionId +482 } 483 } -484} -485 -486#[derive(Clone, Debug)] -487pub enum Close { -488 Connection(ConnectionClose), -489 Application(ApplicationClose), -490} -491 -492impl Close { -493 pub(crate) fn encoder(&self, max_len: usize) -> CloseEncoder<'_> { -494 CloseEncoder { -495 close: self, -496 max_len, -497 } -498 } -499 -500 pub(crate) fn is_transport_layer(&self) -> bool { -501 matches!(*self, Self::Connection(_)) -502 } -503} -504 -505pub(crate) struct CloseEncoder<'a> { -506 close: &'a Close, -507 max_len: usize, -508} -509 -510impl<'a> Encodable for CloseEncoder<'a> { -511 fn encode<W: BufMut>(&self, out: &mut W) { -512 match self.close { -513 Close::Connection(x) => x.encode(out, self.max_len), -514 Close::Application(x) => x.encode(out, self.max_len), -515 } -516 } -517} -518 -519impl From<TransportError> for Close { -520 fn from(x: TransportError) -> Self { -521 Self::Connection(x.into()) -522 } -523} -524impl From<ConnectionClose> for Close { -525 fn from(x: ConnectionClose) -> Self { -526 Self::Connection(x) -527 } -528} -529impl From<ApplicationClose> for Close { -530 fn from(x: ApplicationClose) -> Self { -531 Self::Application(x) -532 } -533} -534 -535/// Reason given by the transport for closing the connection -536#[derive(Debug, Clone, PartialEq, Eq)] -537pub struct ConnectionClose { -538 /// Class of error as encoded in the specification -539 pub error_code: TransportErrorCode, -540 /// Type of frame that caused the close -541 pub frame_type: MaybeFrame, -542 /// Human-readable reason for the close -543 pub reason: Bytes, +484 +485 /// Returns the maximum encoded size on the wire +486 /// +487 /// `path_retire_cid` determines whether this frame is a multipath frame. This is a rough upper +488 /// estimate, does not squeeze every last byte out. +489 pub(crate) const fn size_bound(path_retire_cid: bool) -> usize { +490 match path_retire_cid { +491 true => Self::SIZE_BOUND_MULTIPATH, +492 false => Self::SIZE_BOUND, +493 } +494 } +495} +496 +497impl Encodable for RetireConnectionId { +498 fn encode<W: BufMut>(&self, buf: &mut W) { +499 buf.write(self.get_type()); +500 if let Some(id) = self.path_id { +501 buf.write(id); +502 } +503 buf.write_var(self.sequence); +504 } +505} +506 +507#[derive(Clone, Debug)] +508pub enum Close { +509 Connection(ConnectionClose), +510 Application(ApplicationClose), +511} +512 +513impl Close { +514 pub(crate) fn encoder(&self, max_len: usize) -> CloseEncoder<'_> { +515 CloseEncoder { +516 close: self, +517 max_len, +518 } +519 } +520 +521 pub(crate) fn is_transport_layer(&self) -> bool { +522 matches!(*self, Self::Connection(_)) +523 } +524} +525 +526pub(crate) struct CloseEncoder<'a> { +527 close: &'a Close, +528 max_len: usize, +529} +530 +531impl<'a> Encodable for CloseEncoder<'a> { +532 fn encode<W: BufMut>(&self, out: &mut W) { +533 match self.close { +534 Close::Connection(x) => x.encode(out, self.max_len), +535 Close::Application(x) => x.encode(out, self.max_len), +536 } +537 } +538} +539 +540impl From<TransportError> for Close { +541 fn from(x: TransportError) -> Self { +542 Self::Connection(x.into()) +543 } 544} -545 -546impl fmt::Display for ConnectionClose { -547 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { -548 self.error_code.fmt(f)?; -549 if !self.reason.as_ref().is_empty() { -550 f.write_str(": ")?; -551 f.write_str(&String::from_utf8_lossy(&self.reason))?; -552 } -553 Ok(()) -554 } -555} -556 -557impl From<TransportError> for ConnectionClose { -558 fn from(x: TransportError) -> Self { -559 Self { -560 error_code: x.code, -561 frame_type: x.frame, -562 reason: x.reason.into(), -563 } -564 } +545impl From<ConnectionClose> for Close { +546 fn from(x: ConnectionClose) -> Self { +547 Self::Connection(x) +548 } +549} +550impl From<ApplicationClose> for Close { +551 fn from(x: ApplicationClose) -> Self { +552 Self::Application(x) +553 } +554} +555 +556/// Reason given by the transport for closing the connection +557#[derive(Debug, Clone, PartialEq, Eq)] +558pub struct ConnectionClose { +559 /// Class of error as encoded in the specification +560 pub error_code: TransportErrorCode, +561 /// Type of frame that caused the close +562 pub frame_type: MaybeFrame, +563 /// Human-readable reason for the close +564 pub reason: Bytes, 565} 566 -567impl FrameStruct for ConnectionClose { -568 const SIZE_BOUND: usize = 1 + 8 + 8 + 8; -569} -570 -571impl ConnectionClose { -572 pub(crate) fn encode<W: BufMut>(&self, out: &mut W, max_len: usize) { -573 out.write(FrameType::ConnectionClose); // 1 byte -574 out.write(self.error_code); // <= 8 bytes -575 out.write(self.frame_type); // <= 8 bytes -576 let max_len = max_len -577 - 3 -578 - self.frame_type.size() -579 - VarInt::from_u64(self.reason.len() as u64).unwrap().size(); -580 let actual_len = self.reason.len().min(max_len); -581 out.write_var(actual_len as u64); // <= 8 bytes -582 out.put_slice(&self.reason[0..actual_len]); // whatever's left -583 } -584} -585 -586/// Reason given by an application for closing the connection -587#[derive(Debug, Clone, PartialEq, Eq)] -588pub struct ApplicationClose { -589 /// Application-specific reason code -590 pub error_code: VarInt, -591 /// Human-readable reason for the close -592 pub reason: Bytes, -593} -594 -595impl fmt::Display for ApplicationClose { -596 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { -597 if !self.reason.as_ref().is_empty() { -598 f.write_str(&String::from_utf8_lossy(&self.reason))?; -599 f.write_str(" (code ")?; -600 self.error_code.fmt(f)?; -601 f.write_str(")")?; -602 } else { -603 self.error_code.fmt(f)?; -604 } -605 Ok(()) -606 } -607} -608 -609impl FrameStruct for ApplicationClose { -610 const SIZE_BOUND: usize = 1 + 8 + 8; -611} -612 -613impl ApplicationClose { -614 pub(crate) fn encode<W: BufMut>(&self, out: &mut W, max_len: usize) { -615 out.write(FrameType::ApplicationClose); // 1 byte -616 out.write(self.error_code); // <= 8 bytes -617 let max_len = max_len - 3 - VarInt::from_u64(self.reason.len() as u64).unwrap().size(); -618 let actual_len = self.reason.len().min(max_len); -619 out.write_var(actual_len as u64); // <= 8 bytes -620 out.put_slice(&self.reason[0..actual_len]); // whatever's left -621 } -622} -623 -624#[derive(Clone, Eq, PartialEq)] -625pub struct PathAck { -626 pub path_id: PathId, -627 pub largest: u64, -628 pub delay: u64, -629 pub additional: Bytes, -630 pub ecn: Option<EcnCounts>, -631} -632 -633impl fmt::Debug for PathAck { -634 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { -635 let mut ranges = "[".to_string(); -636 let mut first = true; -637 for range in self.into_iter() { -638 if !first { -639 ranges.push(','); -640 } -641 write!(ranges, "{range:?}")?; -642 first = false; -643 } -644 ranges.push(']'); -645 -646 f.debug_struct("PathAck") -647 .field("path_id", &self.path_id) -648 .field("largest", &self.largest) -649 .field("delay", &self.delay) -650 .field("ecn", &self.ecn) -651 .field("ranges", &ranges) -652 .finish() -653 } -654} -655 -656impl<'a> IntoIterator for &'a PathAck { -657 type Item = RangeInclusive<u64>; -658 type IntoIter = AckIter<'a>; -659 -660 fn into_iter(self) -> AckIter<'a> { -661 AckIter::new(self.largest, &self.additional[..]) -662 } -663} -664 -665impl PathAck { -666 pub fn into_ack(self) -> (Ack, PathId) { -667 let ack = Ack { -668 largest: self.largest, -669 delay: self.delay, -670 additional: self.additional, -671 ecn: self.ecn, -672 }; -673 -674 (ack, self.path_id) -675 } +567impl fmt::Display for ConnectionClose { +568 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +569 self.error_code.fmt(f)?; +570 if !self.reason.as_ref().is_empty() { +571 f.write_str(": ")?; +572 f.write_str(&String::from_utf8_lossy(&self.reason))?; +573 } +574 Ok(()) +575 } +576} +577 +578impl From<TransportError> for ConnectionClose { +579 fn from(x: TransportError) -> Self { +580 Self { +581 error_code: x.code, +582 frame_type: x.frame, +583 reason: x.reason.into(), +584 } +585 } +586} +587 +588impl FrameStruct for ConnectionClose { +589 const SIZE_BOUND: usize = 1 + 8 + 8 + 8; +590} +591 +592impl ConnectionClose { +593 pub(crate) fn encode<W: BufMut>(&self, out: &mut W, max_len: usize) { +594 out.write(FrameType::ConnectionClose); // 1 byte +595 out.write(self.error_code); // <= 8 bytes +596 out.write(self.frame_type); // <= 8 bytes +597 let max_len = max_len +598 - 3 +599 - self.frame_type.size() +600 - VarInt::from_u64(self.reason.len() as u64).unwrap().size(); +601 let actual_len = self.reason.len().min(max_len); +602 out.write_var(actual_len as u64); // <= 8 bytes +603 out.put_slice(&self.reason[0..actual_len]); // whatever's left +604 } +605} +606 +607/// Reason given by an application for closing the connection +608#[derive(Debug, Clone, PartialEq, Eq)] +609pub struct ApplicationClose { +610 /// Application-specific reason code +611 pub error_code: VarInt, +612 /// Human-readable reason for the close +613 pub reason: Bytes, +614} +615 +616impl fmt::Display for ApplicationClose { +617 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +618 if !self.reason.as_ref().is_empty() { +619 f.write_str(&String::from_utf8_lossy(&self.reason))?; +620 f.write_str(" (code ")?; +621 self.error_code.fmt(f)?; +622 f.write_str(")")?; +623 } else { +624 self.error_code.fmt(f)?; +625 } +626 Ok(()) +627 } +628} +629 +630impl FrameStruct for ApplicationClose { +631 const SIZE_BOUND: usize = 1 + 8 + 8; +632} +633 +634impl ApplicationClose { +635 pub(crate) fn encode<W: BufMut>(&self, out: &mut W, max_len: usize) { +636 out.write(FrameType::ApplicationClose); // 1 byte +637 out.write(self.error_code); // <= 8 bytes +638 let max_len = max_len - 3 - VarInt::from_u64(self.reason.len() as u64).unwrap().size(); +639 let actual_len = self.reason.len().min(max_len); +640 out.write_var(actual_len as u64); // <= 8 bytes +641 out.put_slice(&self.reason[0..actual_len]); // whatever's left +642 } +643} +644 +645#[derive(Clone, Eq, PartialEq)] +646pub struct PathAck { +647 pub path_id: PathId, +648 pub largest: u64, +649 pub delay: u64, +650 pub additional: Bytes, +651 pub ecn: Option<EcnCounts>, +652} +653 +654impl fmt::Debug for PathAck { +655 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +656 let mut ranges = "[".to_string(); +657 let mut first = true; +658 for range in self.into_iter() { +659 if !first { +660 ranges.push(','); +661 } +662 write!(ranges, "{range:?}")?; +663 first = false; +664 } +665 ranges.push(']'); +666 +667 f.debug_struct("PathAck") +668 .field("path_id", &self.path_id) +669 .field("largest", &self.largest) +670 .field("delay", &self.delay) +671 .field("ecn", &self.ecn) +672 .field("ranges", &ranges) +673 .finish() +674 } +675} 676 -677 pub(crate) fn encoder<'a>( -678 path_id: PathId, -679 delay: u64, -680 ranges: &'a ArrayRangeSet, -681 ecn: Option<&'a EcnCounts>, -682 ) -> PathAckEncoder<'a> { -683 PathAckEncoder { -684 path_id, -685 delay, -686 ranges, -687 ecn, -688 } -689 } -690} -691 -692pub(crate) struct PathAckEncoder<'a> { -693 path_id: PathId, -694 delay: u64, -695 ranges: &'a ArrayRangeSet, -696 ecn: Option<&'a EcnCounts>, -697} -698 -699impl<'a> Encodable for PathAckEncoder<'a> { -700 /// Encode [`Self`] into the given buffer -701 /// -702 /// The [`FrameType`] will be either [`FrameType::PathAckEcn`] or [`FrameType::PathAck`] -703 /// depending on whether [`EcnCounts`] are provided. -704 /// -705 /// PANICS: if `ranges` is empty. -706 fn encode<W: BufMut>(&self, buf: &mut W) { -707 let PathAckEncoder { -708 path_id, -709 delay, -710 ranges, -711 ecn, -712 } = self; -713 let mut rest = ranges.iter().rev(); -714 let first = rest -715 .next() -716 .expect("Caller has verified ranges is non empty"); -717 let largest = first.end - 1; -718 let first_size = first.end - first.start; -719 let kind = match ecn.is_some() { -720 true => FrameType::PathAckEcn, -721 false => FrameType::PathAck, -722 }; -723 buf.write(kind); -724 buf.write(*path_id); -725 buf.write_var(largest); -726 buf.write_var(*delay); -727 buf.write_var(ranges.len() as u64 - 1); -728 buf.write_var(first_size - 1); -729 let mut prev = first.start; -730 for block in rest { -731 let size = block.end - block.start; -732 buf.write_var(prev - block.end - 1); -733 buf.write_var(size - 1); -734 prev = block.start; -735 } -736 if let Some(x) = ecn { -737 x.encode(buf) -738 } -739 } -740} -741 -742#[derive(Clone, Eq, PartialEq)] -743pub struct Ack { -744 pub largest: u64, -745 pub delay: u64, -746 pub additional: Bytes, -747 pub ecn: Option<EcnCounts>, -748} -749 -750impl fmt::Debug for Ack { -751 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { -752 let mut ranges = "[".to_string(); -753 let mut first = true; -754 for range in self.iter() { -755 if !first { -756 ranges.push(','); -757 } -758 write!(ranges, "{range:?}").unwrap(); -759 first = false; -760 } -761 ranges.push(']'); +677impl<'a> IntoIterator for &'a PathAck { +678 type Item = RangeInclusive<u64>; +679 type IntoIter = AckIter<'a>; +680 +681 fn into_iter(self) -> AckIter<'a> { +682 AckIter::new(self.largest, &self.additional[..]) +683 } +684} +685 +686impl PathAck { +687 pub fn into_ack(self) -> (Ack, PathId) { +688 let ack = Ack { +689 largest: self.largest, +690 delay: self.delay, +691 additional: self.additional, +692 ecn: self.ecn, +693 }; +694 +695 (ack, self.path_id) +696 } +697 +698 pub(crate) fn encoder<'a>( +699 path_id: PathId, +700 delay: u64, +701 ranges: &'a ArrayRangeSet, +702 ecn: Option<&'a EcnCounts>, +703 ) -> PathAckEncoder<'a> { +704 PathAckEncoder { +705 path_id, +706 delay, +707 ranges, +708 ecn, +709 } +710 } +711} +712 +713pub(crate) struct PathAckEncoder<'a> { +714 path_id: PathId, +715 delay: u64, +716 ranges: &'a ArrayRangeSet, +717 ecn: Option<&'a EcnCounts>, +718} +719 +720impl<'a> Encodable for PathAckEncoder<'a> { +721 /// Encode [`Self`] into the given buffer +722 /// +723 /// The [`FrameType`] will be either [`FrameType::PathAckEcn`] or [`FrameType::PathAck`] +724 /// depending on whether [`EcnCounts`] are provided. +725 /// +726 /// PANICS: if `ranges` is empty. +727 fn encode<W: BufMut>(&self, buf: &mut W) { +728 let PathAckEncoder { +729 path_id, +730 delay, +731 ranges, +732 ecn, +733 } = self; +734 let mut rest = ranges.iter().rev(); +735 let first = rest +736 .next() +737 .expect("Caller has verified ranges is non empty"); +738 let largest = first.end - 1; +739 let first_size = first.end - first.start; +740 let kind = match ecn.is_some() { +741 true => FrameType::PathAckEcn, +742 false => FrameType::PathAck, +743 }; +744 buf.write(kind); +745 buf.write(*path_id); +746 buf.write_var(largest); +747 buf.write_var(*delay); +748 buf.write_var(ranges.len() as u64 - 1); +749 buf.write_var(first_size - 1); +750 let mut prev = first.start; +751 for block in rest { +752 let size = block.end - block.start; +753 buf.write_var(prev - block.end - 1); +754 buf.write_var(size - 1); +755 prev = block.start; +756 } +757 if let Some(x) = ecn { +758 x.encode(buf) +759 } +760 } +761} 762 -763 f.debug_struct("Ack") -764 .field("largest", &self.largest) -765 .field("delay", &self.delay) -766 .field("ecn", &self.ecn) -767 .field("ranges", &ranges) -768 .finish() -769 } -770} -771 -772impl<'a> IntoIterator for &'a Ack { -773 type Item = RangeInclusive<u64>; -774 type IntoIter = AckIter<'a>; -775 -776 fn into_iter(self) -> AckIter<'a> { -777 AckIter::new(self.largest, &self.additional[..]) -778 } -779} -780 -781impl Ack { -782 pub(crate) fn encoder<'a>( -783 delay: u64, -784 ranges: &'a ArrayRangeSet, -785 ecn: Option<&'a EcnCounts>, -786 ) -> AckEncoder<'a> { -787 AckEncoder { delay, ranges, ecn } -788 } -789 -790 pub fn iter(&self) -> AckIter<'_> { -791 self.into_iter() -792 } -793} -794 -795pub(crate) struct AckEncoder<'a> { -796 delay: u64, -797 ranges: &'a ArrayRangeSet, -798 ecn: Option<&'a EcnCounts>, -799} -800 -801impl<'a> Encodable for AckEncoder<'a> { -802 fn encode<W: BufMut>(&self, buf: &mut W) { -803 let AckEncoder { delay, ranges, ecn } = self; -804 let mut rest = ranges.iter().rev(); -805 let first = rest.next().unwrap(); -806 let largest = first.end - 1; -807 let first_size = first.end - first.start; -808 let kind = match ecn.is_some() { -809 true => FrameType::AckEcn, -810 false => FrameType::Ack, -811 }; -812 buf.write(kind); -813 buf.write_var(largest); -814 buf.write_var(*delay); -815 buf.write_var(ranges.len() as u64 - 1); -816 buf.write_var(first_size - 1); -817 let mut prev = first.start; -818 for block in rest { -819 let size = block.end - block.start; -820 buf.write_var(prev - block.end - 1); -821 buf.write_var(size - 1); -822 prev = block.start; -823 } -824 if let Some(x) = ecn { -825 x.encode(buf) -826 } -827 } -828} -829 -830#[derive(Debug, Copy, Clone, Eq, PartialEq)] -831pub struct EcnCounts { -832 pub ect0: u64, -833 pub ect1: u64, -834 pub ce: u64, -835} -836 -837impl std::ops::AddAssign<EcnCodepoint> for EcnCounts { -838 fn add_assign(&mut self, rhs: EcnCodepoint) { -839 match rhs { -840 EcnCodepoint::Ect0 => { -841 self.ect0 += 1; -842 } -843 EcnCodepoint::Ect1 => { -844 self.ect1 += 1; -845 } -846 EcnCodepoint::Ce => { -847 self.ce += 1; -848 } -849 } -850 } -851} -852 -853impl EcnCounts { -854 pub const ZERO: Self = Self { -855 ect0: 0, -856 ect1: 0, -857 ce: 0, -858 }; -859} -860 -861impl Encodable for EcnCounts { -862 fn encode<W: BufMut>(&self, out: &mut W) { -863 out.write_var(self.ect0); -864 out.write_var(self.ect1); -865 out.write_var(self.ce); -866 } -867} -868 -869#[derive(Debug, Clone)] -870pub(crate) struct Stream { -871 pub(crate) id: StreamId, -872 pub(crate) offset: u64, -873 pub(crate) fin: bool, -874 pub(crate) data: Bytes, -875} -876 -877impl FrameStruct for Stream { -878 const SIZE_BOUND: usize = 1 + 8 + 8 + 8; -879} -880 -881/// Metadata from a stream frame -882#[derive(Debug, Clone)] -883pub(crate) struct StreamMeta { -884 pub(crate) id: StreamId, -885 pub(crate) offsets: Range<u64>, -886 pub(crate) fin: bool, -887} -888 -889// This manual implementation exists because `Default` is not implemented for `StreamId` -890impl Default for StreamMeta { -891 fn default() -> Self { -892 Self { -893 id: StreamId(0), -894 offsets: 0..0, -895 fin: false, -896 } -897 } -898} -899 -900impl StreamMeta { -901 pub(crate) fn encoder(&self, encode_length: bool) -> StreamMetaEncoder<'_> { -902 StreamMetaEncoder { -903 meta: self, -904 encode_length, -905 } -906 } -907} -908 -909pub(crate) struct StreamMetaEncoder<'a> { -910 meta: &'a StreamMeta, -911 encode_length: bool, -912} -913 -914impl<'a> Encodable for StreamMetaEncoder<'a> { -915 fn encode<W: BufMut>(&self, out: &mut W) { -916 let StreamMetaEncoder { -917 meta, -918 encode_length: length, -919 } = self; -920 let mut ty = *StreamInfo::VALUES.start(); -921 if meta.offsets.start != 0 { -922 ty |= 0x04; -923 } -924 if *length { -925 ty |= 0x02; +763#[derive(Clone, Eq, PartialEq)] +764pub struct Ack { +765 pub largest: u64, +766 pub delay: u64, +767 pub additional: Bytes, +768 pub ecn: Option<EcnCounts>, +769} +770 +771impl fmt::Debug for Ack { +772 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +773 let mut ranges = "[".to_string(); +774 let mut first = true; +775 for range in self.iter() { +776 if !first { +777 ranges.push(','); +778 } +779 write!(ranges, "{range:?}").unwrap(); +780 first = false; +781 } +782 ranges.push(']'); +783 +784 f.debug_struct("Ack") +785 .field("largest", &self.largest) +786 .field("delay", &self.delay) +787 .field("ecn", &self.ecn) +788 .field("ranges", &ranges) +789 .finish() +790 } +791} +792 +793impl<'a> IntoIterator for &'a Ack { +794 type Item = RangeInclusive<u64>; +795 type IntoIter = AckIter<'a>; +796 +797 fn into_iter(self) -> AckIter<'a> { +798 AckIter::new(self.largest, &self.additional[..]) +799 } +800} +801 +802impl Ack { +803 pub(crate) fn encoder<'a>( +804 delay: u64, +805 ranges: &'a ArrayRangeSet, +806 ecn: Option<&'a EcnCounts>, +807 ) -> AckEncoder<'a> { +808 AckEncoder { delay, ranges, ecn } +809 } +810 +811 pub fn iter(&self) -> AckIter<'_> { +812 self.into_iter() +813 } +814} +815 +816pub(crate) struct AckEncoder<'a> { +817 delay: u64, +818 ranges: &'a ArrayRangeSet, +819 ecn: Option<&'a EcnCounts>, +820} +821 +822impl<'a> Encodable for AckEncoder<'a> { +823 fn encode<W: BufMut>(&self, buf: &mut W) { +824 let AckEncoder { delay, ranges, ecn } = self; +825 let mut rest = ranges.iter().rev(); +826 let first = rest.next().unwrap(); +827 let largest = first.end - 1; +828 let first_size = first.end - first.start; +829 let kind = match ecn.is_some() { +830 true => FrameType::AckEcn, +831 false => FrameType::Ack, +832 }; +833 buf.write(kind); +834 buf.write_var(largest); +835 buf.write_var(*delay); +836 buf.write_var(ranges.len() as u64 - 1); +837 buf.write_var(first_size - 1); +838 let mut prev = first.start; +839 for block in rest { +840 let size = block.end - block.start; +841 buf.write_var(prev - block.end - 1); +842 buf.write_var(size - 1); +843 prev = block.start; +844 } +845 if let Some(x) = ecn { +846 x.encode(buf) +847 } +848 } +849} +850 +851#[derive(Debug, Copy, Clone, Eq, PartialEq)] +852pub struct EcnCounts { +853 pub ect0: u64, +854 pub ect1: u64, +855 pub ce: u64, +856} +857 +858impl std::ops::AddAssign<EcnCodepoint> for EcnCounts { +859 fn add_assign(&mut self, rhs: EcnCodepoint) { +860 match rhs { +861 EcnCodepoint::Ect0 => { +862 self.ect0 += 1; +863 } +864 EcnCodepoint::Ect1 => { +865 self.ect1 += 1; +866 } +867 EcnCodepoint::Ce => { +868 self.ce += 1; +869 } +870 } +871 } +872} +873 +874impl EcnCounts { +875 pub const ZERO: Self = Self { +876 ect0: 0, +877 ect1: 0, +878 ce: 0, +879 }; +880} +881 +882impl Encodable for EcnCounts { +883 fn encode<W: BufMut>(&self, out: &mut W) { +884 out.write_var(self.ect0); +885 out.write_var(self.ect1); +886 out.write_var(self.ce); +887 } +888} +889 +890#[derive(Debug, Clone)] +891pub(crate) struct Stream { +892 pub(crate) id: StreamId, +893 pub(crate) offset: u64, +894 pub(crate) fin: bool, +895 pub(crate) data: Bytes, +896} +897 +898impl FrameStruct for Stream { +899 const SIZE_BOUND: usize = 1 + 8 + 8 + 8; +900} +901 +902/// Metadata from a stream frame +903#[derive(Debug, Clone)] +904pub(crate) struct StreamMeta { +905 pub(crate) id: StreamId, +906 pub(crate) offsets: Range<u64>, +907 pub(crate) fin: bool, +908} +909 +910// This manual implementation exists because `Default` is not implemented for `StreamId` +911impl Default for StreamMeta { +912 fn default() -> Self { +913 Self { +914 id: StreamId(0), +915 offsets: 0..0, +916 fin: false, +917 } +918 } +919} +920 +921impl StreamMeta { +922 pub(crate) fn encoder(&self, encode_length: bool) -> StreamMetaEncoder<'_> { +923 StreamMetaEncoder { +924 meta: self, +925 encode_length, 926 } -927 if meta.fin { -928 ty |= 0x01; -929 } -930 out.write_var(ty); // 1 byte -931 out.write(meta.id); // <=8 bytes -932 if meta.offsets.start != 0 { -933 out.write_var(meta.offsets.start); // <=8 bytes -934 } -935 if *length { -936 out.write_var(meta.offsets.end - meta.offsets.start); // <=8 bytes -937 } -938 } -939} -940 -941/// A vector of [`StreamMeta`] with optimization for the single element case -942pub(crate) type StreamMetaVec = TinyVec<[StreamMeta; 1]>; -943 -944#[derive(Debug, Clone)] -945pub(crate) struct Crypto { -946 pub(crate) offset: u64, -947 pub(crate) data: Bytes, -948} -949 -950impl Crypto { -951 pub(crate) const SIZE_BOUND: usize = 17; -952} -953 -954impl Encodable for Crypto { -955 fn encode<W: BufMut>(&self, out: &mut W) { -956 out.write(FrameType::Crypto); -957 out.write_var(self.offset); -958 out.write_var(self.data.len() as u64); -959 out.put_slice(&self.data); -960 } -961} -962 -963#[derive(Debug, Clone)] -964pub(crate) struct NewToken { -965 pub(crate) token: Bytes, -966} -967 -968impl Encodable for NewToken { -969 fn encode<W: BufMut>(&self, out: &mut W) { -970 out.write(FrameType::NewToken); -971 out.write_var(self.token.len() as u64); -972 out.put_slice(&self.token); -973 } -974} -975 -976impl NewToken { -977 pub(crate) fn size(&self) -> usize { -978 1 + VarInt::from_u64(self.token.len() as u64).unwrap().size() + self.token.len() -979 } -980} -981 -982#[derive(Debug, Clone)] -983pub(crate) struct MaxPathId(pub(crate) PathId); -984 -985impl MaxPathId { -986 pub(crate) const SIZE_BOUND: usize = -987 FrameType::MaxPathId.size() + VarInt(u32::MAX as u64).size(); -988} -989 -990impl Decodable for MaxPathId { -991 fn decode<B: Buf>(buf: &mut B) -> coding::Result<Self> { -992 Ok(Self(buf.get()?)) -993 } -994} -995 -996impl Encodable for MaxPathId { -997 fn encode<B: BufMut>(&self, buf: &mut B) { -998 buf.write(FrameType::MaxPathId); -999 buf.write(self.0); +927 } +928} +929 +930pub(crate) struct StreamMetaEncoder<'a> { +931 meta: &'a StreamMeta, +932 encode_length: bool, +933} +934 +935impl<'a> Encodable for StreamMetaEncoder<'a> { +936 fn encode<W: BufMut>(&self, out: &mut W) { +937 let StreamMetaEncoder { +938 meta, +939 encode_length: length, +940 } = self; +941 let mut ty = *StreamInfo::VALUES.start(); +942 if meta.offsets.start != 0 { +943 ty |= 0x04; +944 } +945 if *length { +946 ty |= 0x02; +947 } +948 if meta.fin { +949 ty |= 0x01; +950 } +951 out.write_var(ty); // 1 byte +952 out.write(meta.id); // <=8 bytes +953 if meta.offsets.start != 0 { +954 out.write_var(meta.offsets.start); // <=8 bytes +955 } +956 if *length { +957 out.write_var(meta.offsets.end - meta.offsets.start); // <=8 bytes +958 } +959 } +960} +961 +962/// A vector of [`StreamMeta`] with optimization for the single element case +963pub(crate) type StreamMetaVec = TinyVec<[StreamMeta; 1]>; +964 +965#[derive(Debug, Clone)] +966pub(crate) struct Crypto { +967 pub(crate) offset: u64, +968 pub(crate) data: Bytes, +969} +970 +971impl Crypto { +972 pub(crate) const SIZE_BOUND: usize = 17; +973} +974 +975impl Encodable for Crypto { +976 fn encode<W: BufMut>(&self, out: &mut W) { +977 out.write(FrameType::Crypto); +978 out.write_var(self.offset); +979 out.write_var(self.data.len() as u64); +980 out.put_slice(&self.data); +981 } +982} +983 +984#[derive(Debug, Clone)] +985pub(crate) struct NewToken { +986 pub(crate) token: Bytes, +987} +988 +989impl Encodable for NewToken { +990 fn encode<W: BufMut>(&self, out: &mut W) { +991 out.write(FrameType::NewToken); +992 out.write_var(self.token.len() as u64); +993 out.put_slice(&self.token); +994 } +995} +996 +997impl NewToken { +998 pub(crate) fn size(&self) -> usize { +999 1 + VarInt::from_u64(self.token.len() as u64).unwrap().size() + self.token.len() 1000 } 1001} 1002 -1003#[derive(Debug, Clone, PartialEq, Eq)] -1004pub(crate) struct PathsBlocked(pub(crate) PathId); +1003#[derive(Debug, Clone)] +1004pub(crate) struct MaxPathId(pub(crate) PathId); 1005 -1006impl PathsBlocked { +1006impl MaxPathId { 1007 pub(crate) const SIZE_BOUND: usize = -1008 FrameType::PathsBlocked.size() + VarInt(u32::MAX as u64).size(); +1008 FrameType::MaxPathId.size() + VarInt(u32::MAX as u64).size(); 1009} 1010 -1011impl Encodable for PathsBlocked { -1012 fn encode<B: BufMut>(&self, buf: &mut B) { -1013 buf.write(FrameType::PathsBlocked); -1014 buf.write(self.0); -1015 } -1016} -1017 -1018impl Decodable for PathsBlocked { -1019 /// Decode [`Self`] from the buffer, provided that the frame type has been verified -1020 fn decode<B: Buf>(buf: &mut B) -> coding::Result<Self> { -1021 Ok(Self(buf.get()?)) -1022 } -1023} -1024 -1025#[derive(Debug, Clone, PartialEq, Eq)] -1026pub(crate) struct PathCidsBlocked { -1027 pub(crate) path_id: PathId, -1028 pub(crate) next_seq: VarInt, -1029} -1030 -1031impl PathCidsBlocked { -1032 pub(crate) const SIZE_BOUND: usize = -1033 FrameType::PathCidsBlocked.size() + VarInt(u32::MAX as u64).size() + VarInt::MAX.size(); -1034} -1035 -1036impl Decodable for PathCidsBlocked { -1037 fn decode<R: Buf>(buf: &mut R) -> coding::Result<Self> { -1038 Ok(Self { -1039 path_id: buf.get()?, -1040 next_seq: buf.get()?, -1041 }) -1042 } -1043} -1044 -1045impl Encodable for PathCidsBlocked { -1046 fn encode<W: BufMut>(&self, buf: &mut W) { -1047 buf.write(FrameType::PathCidsBlocked); -1048 buf.write(self.path_id); -1049 buf.write(self.next_seq); -1050 } -1051} -1052 -1053pub(crate) struct Iter { -1054 bytes: Bytes, -1055 last_ty: MaybeFrame, -1056} -1057 -1058impl Iter { -1059 pub(crate) fn new(payload: Bytes) -> Result<Self, TransportError> { -1060 if payload.is_empty() { -1061 // "An endpoint MUST treat receipt of a packet containing no frames as a -1062 // connection error of type PROTOCOL_VIOLATION." -1063 // https://www.rfc-editor.org/rfc/rfc9000.html#name-frames-and-frame-types -1064 return Err(TransportError::PROTOCOL_VIOLATION( -1065 "packet payload is empty", -1066 )); -1067 } -1068 -1069 Ok(Self { -1070 bytes: payload, -1071 last_ty: MaybeFrame::None, -1072 }) -1073 } -1074 -1075 fn take_len(&mut self) -> Result<Bytes, UnexpectedEnd> { -1076 let len = self.bytes.get_var()?; -1077 if len > self.bytes.remaining() as u64 { -1078 return Err(UnexpectedEnd); -1079 } -1080 Ok(self.bytes.split_to(len as usize)) -1081 } -1082 -1083 #[track_caller] -1084 fn try_next(&mut self) -> Result<Frame, IterErr> { -1085 self.last_ty = self.bytes.get()?; -1086 -1087 let ty = match self.last_ty { -1088 MaybeFrame::None => FrameType::Padding, -1089 MaybeFrame::Unknown(_other) => return Err(IterErr::InvalidFrameId), -1090 MaybeFrame::Known(frame_type) => frame_type, -1091 }; -1092 Ok(match ty { -1093 FrameType::Padding => Frame::Padding, -1094 FrameType::ResetStream => Frame::ResetStream(ResetStream { -1095 id: self.bytes.get()?, -1096 error_code: self.bytes.get()?, -1097 final_offset: self.bytes.get()?, -1098 }), -1099 FrameType::ConnectionClose => Frame::Close(Close::Connection(ConnectionClose { -1100 error_code: self.bytes.get()?, -1101 frame_type: self.bytes.get()?, -1102 reason: self.take_len()?, -1103 })), -1104 FrameType::ApplicationClose => Frame::Close(Close::Application(ApplicationClose { -1105 error_code: self.bytes.get()?, -1106 reason: self.take_len()?, -1107 })), -1108 FrameType::MaxData => Frame::MaxData(self.bytes.get()?), -1109 FrameType::MaxStreamData => Frame::MaxStreamData { -1110 id: self.bytes.get()?, -1111 offset: self.bytes.get_var()?, -1112 }, -1113 FrameType::MaxStreamsBidi => Frame::MaxStreams { -1114 dir: Dir::Bi, -1115 count: self.bytes.get_var()?, -1116 }, -1117 FrameType::MaxStreamsUni => Frame::MaxStreams { -1118 dir: Dir::Uni, -1119 count: self.bytes.get_var()?, -1120 }, -1121 FrameType::Ping => Frame::Ping, -1122 FrameType::DataBlocked => Frame::DataBlocked { -1123 offset: self.bytes.get_var()?, -1124 }, -1125 FrameType::StreamDataBlocked => Frame::StreamDataBlocked { -1126 id: self.bytes.get()?, -1127 offset: self.bytes.get_var()?, -1128 }, -1129 FrameType::StreamsBlockedBidi => Frame::StreamsBlocked { -1130 dir: Dir::Bi, -1131 limit: self.bytes.get_var()?, -1132 }, -1133 FrameType::StreamsBlockedUni => Frame::StreamsBlocked { -1134 dir: Dir::Uni, -1135 limit: self.bytes.get_var()?, -1136 }, -1137 FrameType::StopSending => Frame::StopSending(StopSending { -1138 id: self.bytes.get()?, -1139 error_code: self.bytes.get()?, -1140 }), -1141 FrameType::RetireConnectionId | FrameType::PathRetireConnectionId => { -1142 Frame::RetireConnectionId(RetireConnectionId::decode( -1143 &mut self.bytes, -1144 ty == FrameType::PathRetireConnectionId, -1145 )?) -1146 } -1147 FrameType::Ack | FrameType::AckEcn => { -1148 let largest = self.bytes.get_var()?; -1149 let delay = self.bytes.get_var()?; -1150 let extra_blocks = self.bytes.get_var()? as usize; -1151 let n = scan_ack_blocks(&self.bytes, largest, extra_blocks)?; -1152 Frame::Ack(Ack { -1153 delay, -1154 largest, -1155 additional: self.bytes.split_to(n), -1156 ecn: if ty != FrameType::AckEcn && ty != FrameType::PathAckEcn { -1157 None -1158 } else { -1159 Some(EcnCounts { -1160 ect0: self.bytes.get_var()?, -1161 ect1: self.bytes.get_var()?, -1162 ce: self.bytes.get_var()?, -1163 }) -1164 }, -1165 }) -1166 } -1167 FrameType::PathAck | FrameType::PathAckEcn => { -1168 let path_id = self.bytes.get()?; +1011impl Decodable for MaxPathId { +1012 fn decode<B: Buf>(buf: &mut B) -> coding::Result<Self> { +1013 Ok(Self(buf.get()?)) +1014 } +1015} +1016 +1017impl Encodable for MaxPathId { +1018 fn encode<B: BufMut>(&self, buf: &mut B) { +1019 buf.write(FrameType::MaxPathId); +1020 buf.write(self.0); +1021 } +1022} +1023 +1024#[derive(Debug, Clone, PartialEq, Eq)] +1025pub(crate) struct PathsBlocked(pub(crate) PathId); +1026 +1027impl PathsBlocked { +1028 pub(crate) const SIZE_BOUND: usize = +1029 FrameType::PathsBlocked.size() + VarInt(u32::MAX as u64).size(); +1030} +1031 +1032impl Encodable for PathsBlocked { +1033 fn encode<B: BufMut>(&self, buf: &mut B) { +1034 buf.write(FrameType::PathsBlocked); +1035 buf.write(self.0); +1036 } +1037} +1038 +1039impl Decodable for PathsBlocked { +1040 /// Decode [`Self`] from the buffer, provided that the frame type has been verified +1041 fn decode<B: Buf>(buf: &mut B) -> coding::Result<Self> { +1042 Ok(Self(buf.get()?)) +1043 } +1044} +1045 +1046#[derive(Debug, Clone, PartialEq, Eq)] +1047pub(crate) struct PathCidsBlocked { +1048 pub(crate) path_id: PathId, +1049 pub(crate) next_seq: VarInt, +1050} +1051 +1052impl PathCidsBlocked { +1053 pub(crate) const SIZE_BOUND: usize = +1054 FrameType::PathCidsBlocked.size() + VarInt(u32::MAX as u64).size() + VarInt::MAX.size(); +1055} +1056 +1057impl Decodable for PathCidsBlocked { +1058 fn decode<R: Buf>(buf: &mut R) -> coding::Result<Self> { +1059 Ok(Self { +1060 path_id: buf.get()?, +1061 next_seq: buf.get()?, +1062 }) +1063 } +1064} +1065 +1066impl Encodable for PathCidsBlocked { +1067 fn encode<W: BufMut>(&self, buf: &mut W) { +1068 buf.write(FrameType::PathCidsBlocked); +1069 buf.write(self.path_id); +1070 buf.write(self.next_seq); +1071 } +1072} +1073 +1074pub(crate) struct Iter { +1075 bytes: Bytes, +1076 last_ty: MaybeFrame, +1077} +1078 +1079impl Iter { +1080 pub(crate) fn new(payload: Bytes) -> Result<Self, TransportError> { +1081 if payload.is_empty() { +1082 // "An endpoint MUST treat receipt of a packet containing no frames as a +1083 // connection error of type PROTOCOL_VIOLATION." +1084 // https://www.rfc-editor.org/rfc/rfc9000.html#name-frames-and-frame-types +1085 return Err(TransportError::PROTOCOL_VIOLATION( +1086 "packet payload is empty", +1087 )); +1088 } +1089 +1090 Ok(Self { +1091 bytes: payload, +1092 last_ty: MaybeFrame::None, +1093 }) +1094 } +1095 +1096 fn take_len(&mut self) -> Result<Bytes, UnexpectedEnd> { +1097 let len = self.bytes.get_var()?; +1098 if len > self.bytes.remaining() as u64 { +1099 return Err(UnexpectedEnd); +1100 } +1101 Ok(self.bytes.split_to(len as usize)) +1102 } +1103 +1104 #[track_caller] +1105 fn try_next(&mut self) -> Result<Frame, IterErr> { +1106 self.last_ty = self.bytes.get()?; +1107 +1108 let ty = match self.last_ty { +1109 MaybeFrame::None => FrameType::Padding, +1110 MaybeFrame::Unknown(_other) => return Err(IterErr::InvalidFrameId), +1111 MaybeFrame::Known(frame_type) => frame_type, +1112 }; +1113 Ok(match ty { +1114 FrameType::Padding => Frame::Padding, +1115 FrameType::ResetStream => Frame::ResetStream(ResetStream { +1116 id: self.bytes.get()?, +1117 error_code: self.bytes.get()?, +1118 final_offset: self.bytes.get()?, +1119 }), +1120 FrameType::ConnectionClose => Frame::Close(Close::Connection(ConnectionClose { +1121 error_code: self.bytes.get()?, +1122 frame_type: self.bytes.get()?, +1123 reason: self.take_len()?, +1124 })), +1125 FrameType::ApplicationClose => Frame::Close(Close::Application(ApplicationClose { +1126 error_code: self.bytes.get()?, +1127 reason: self.take_len()?, +1128 })), +1129 FrameType::MaxData => Frame::MaxData(self.bytes.get()?), +1130 FrameType::MaxStreamData => Frame::MaxStreamData { +1131 id: self.bytes.get()?, +1132 offset: self.bytes.get_var()?, +1133 }, +1134 FrameType::MaxStreamsBidi => Frame::MaxStreams { +1135 dir: Dir::Bi, +1136 count: self.bytes.get_var()?, +1137 }, +1138 FrameType::MaxStreamsUni => Frame::MaxStreams { +1139 dir: Dir::Uni, +1140 count: self.bytes.get_var()?, +1141 }, +1142 FrameType::Ping => Frame::Ping, +1143 FrameType::DataBlocked => Frame::DataBlocked { +1144 offset: self.bytes.get_var()?, +1145 }, +1146 FrameType::StreamDataBlocked => Frame::StreamDataBlocked { +1147 id: self.bytes.get()?, +1148 offset: self.bytes.get_var()?, +1149 }, +1150 FrameType::StreamsBlockedBidi => Frame::StreamsBlocked { +1151 dir: Dir::Bi, +1152 limit: self.bytes.get_var()?, +1153 }, +1154 FrameType::StreamsBlockedUni => Frame::StreamsBlocked { +1155 dir: Dir::Uni, +1156 limit: self.bytes.get_var()?, +1157 }, +1158 FrameType::StopSending => Frame::StopSending(StopSending { +1159 id: self.bytes.get()?, +1160 error_code: self.bytes.get()?, +1161 }), +1162 FrameType::RetireConnectionId | FrameType::PathRetireConnectionId => { +1163 Frame::RetireConnectionId(RetireConnectionId::decode( +1164 &mut self.bytes, +1165 ty == FrameType::PathRetireConnectionId, +1166 )?) +1167 } +1168 FrameType::Ack | FrameType::AckEcn => { 1169 let largest = self.bytes.get_var()?; 1170 let delay = self.bytes.get_var()?; 1171 let extra_blocks = self.bytes.get_var()? as usize; 1172 let n = scan_ack_blocks(&self.bytes, largest, extra_blocks)?; -1173 Frame::PathAck(PathAck { -1174 path_id, -1175 delay, -1176 largest, -1177 additional: self.bytes.split_to(n), -1178 ecn: if ty != FrameType::AckEcn && ty != FrameType::PathAckEcn { -1179 None -1180 } else { -1181 Some(EcnCounts { -1182 ect0: self.bytes.get_var()?, -1183 ect1: self.bytes.get_var()?, -1184 ce: self.bytes.get_var()?, -1185 }) -1186 }, -1187 }) -1188 } -1189 FrameType::PathChallenge => Frame::PathChallenge(self.bytes.get()?), -1190 FrameType::PathResponse => Frame::PathResponse(self.bytes.get()?), -1191 FrameType::NewConnectionId | FrameType::PathNewConnectionId => { -1192 let read_path = ty == FrameType::PathNewConnectionId; -1193 Frame::NewConnectionId(NewConnectionId::read(&mut self.bytes, read_path)?) -1194 } -1195 FrameType::Crypto => Frame::Crypto(Crypto { -1196 offset: self.bytes.get_var()?, -1197 data: self.take_len()?, -1198 }), -1199 FrameType::NewToken => Frame::NewToken(NewToken { -1200 token: self.take_len()?, -1201 }), -1202 FrameType::HandshakeDone => Frame::HandshakeDone, -1203 FrameType::AckFrequency => Frame::AckFrequency(AckFrequency { -1204 sequence: self.bytes.get()?, -1205 ack_eliciting_threshold: self.bytes.get()?, -1206 request_max_ack_delay: self.bytes.get()?, -1207 reordering_threshold: self.bytes.get()?, -1208 }), -1209 FrameType::ImmediateAck => Frame::ImmediateAck, -1210 FrameType::ObservedIpv4Addr | FrameType::ObservedIpv6Addr => { -1211 let is_ipv6 = ty == FrameType::ObservedIpv6Addr; -1212 let observed = ObservedAddr::read(&mut self.bytes, is_ipv6)?; -1213 Frame::ObservedAddr(observed) -1214 } -1215 FrameType::PathAbandon => Frame::PathAbandon(PathAbandon::decode(&mut self.bytes)?), -1216 FrameType::PathStatusAvailable => { -1217 Frame::PathStatusAvailable(PathStatusAvailable::decode(&mut self.bytes)?) -1218 } -1219 FrameType::PathStatusBackup => { -1220 Frame::PathStatusBackup(PathStatusBackup::decode(&mut self.bytes)?) -1221 } -1222 FrameType::MaxPathId => Frame::MaxPathId(MaxPathId::decode(&mut self.bytes)?), -1223 FrameType::PathsBlocked => Frame::PathsBlocked(PathsBlocked::decode(&mut self.bytes)?), -1224 FrameType::PathCidsBlocked => { -1225 Frame::PathCidsBlocked(PathCidsBlocked::decode(&mut self.bytes)?) -1226 } -1227 FrameType::AddIpv4Address | FrameType::AddIpv6Address => { -1228 let is_ipv6 = ty == FrameType::AddIpv6Address; -1229 let add_address = AddAddress::read(&mut self.bytes, is_ipv6)?; -1230 Frame::AddAddress(add_address) -1231 } -1232 FrameType::ReachOutAtIpv4 | FrameType::ReachOutAtIpv6 => { -1233 let is_ipv6 = ty == FrameType::ReachOutAtIpv6; -1234 let reach_out = ReachOut::read(&mut self.bytes, is_ipv6)?; -1235 Frame::ReachOut(reach_out) -1236 } -1237 FrameType::RemoveAddress => Frame::RemoveAddress(RemoveAddress::read(&mut self.bytes)?), -1238 FrameType::Stream(s) => Frame::Stream(Stream { -1239 id: self.bytes.get()?, -1240 offset: if s.off() { self.bytes.get_var()? } else { 0 }, -1241 fin: s.fin(), -1242 data: if s.len() { -1243 self.take_len()? -1244 } else { -1245 self.take_remaining() -1246 }, -1247 }), -1248 FrameType::Datagram(d) => Frame::Datagram(Datagram { -1249 data: if d.len() { -1250 self.take_len()? -1251 } else { -1252 self.take_remaining() -1253 }, -1254 }), -1255 }) -1256 } -1257 -1258 fn take_remaining(&mut self) -> Bytes { -1259 mem::take(&mut self.bytes) -1260 } -1261} -1262 -1263impl Iterator for Iter { -1264 type Item = Result<Frame, InvalidFrame>; -1265 fn next(&mut self) -> Option<Self::Item> { -1266 if !self.bytes.has_remaining() { -1267 return None; -1268 } -1269 match self.try_next() { -1270 Ok(x) => Some(Ok(x)), -1271 Err(e) => { -1272 // Corrupt frame, skip it and everything that follows -1273 self.bytes.clear(); -1274 Some(Err(InvalidFrame { -1275 ty: self.last_ty, -1276 reason: e.reason(), -1277 })) -1278 } -1279 } -1280 } -1281} -1282 -1283#[derive(Debug)] -1284pub(crate) struct InvalidFrame { -1285 pub(crate) ty: MaybeFrame, -1286 pub(crate) reason: &'static str, -1287} -1288 -1289impl From<InvalidFrame> for TransportError { -1290 fn from(err: InvalidFrame) -> Self { -1291 let mut te = Self::FRAME_ENCODING_ERROR(err.reason); -1292 te.frame = err.ty; -1293 te -1294 } -1295} -1296 -1297/// Validate exactly `n` ACK ranges in `buf` and return the number of bytes they cover -1298fn scan_ack_blocks(mut buf: &[u8], largest: u64, n: usize) -> Result<usize, IterErr> { -1299 let total_len = buf.remaining(); -1300 let first_block = buf.get_var()?; -1301 let mut smallest = largest.checked_sub(first_block).ok_or(IterErr::Malformed)?; -1302 for _ in 0..n { -1303 let gap = buf.get_var()?; -1304 smallest = smallest.checked_sub(gap + 2).ok_or(IterErr::Malformed)?; -1305 let block = buf.get_var()?; -1306 smallest = smallest.checked_sub(block).ok_or(IterErr::Malformed)?; -1307 } -1308 Ok(total_len - buf.remaining()) -1309} -1310 -1311#[derive(Debug)] -1312enum IterErr { -1313 UnexpectedEnd, -1314 InvalidFrameId, -1315 Malformed, +1173 Frame::Ack(Ack { +1174 delay, +1175 largest, +1176 additional: self.bytes.split_to(n), +1177 ecn: if ty != FrameType::AckEcn && ty != FrameType::PathAckEcn { +1178 None +1179 } else { +1180 Some(EcnCounts { +1181 ect0: self.bytes.get_var()?, +1182 ect1: self.bytes.get_var()?, +1183 ce: self.bytes.get_var()?, +1184 }) +1185 }, +1186 }) +1187 } +1188 FrameType::PathAck | FrameType::PathAckEcn => { +1189 let path_id = self.bytes.get()?; +1190 let largest = self.bytes.get_var()?; +1191 let delay = self.bytes.get_var()?; +1192 let extra_blocks = self.bytes.get_var()? as usize; +1193 let n = scan_ack_blocks(&self.bytes, largest, extra_blocks)?; +1194 Frame::PathAck(PathAck { +1195 path_id, +1196 delay, +1197 largest, +1198 additional: self.bytes.split_to(n), +1199 ecn: if ty != FrameType::AckEcn && ty != FrameType::PathAckEcn { +1200 None +1201 } else { +1202 Some(EcnCounts { +1203 ect0: self.bytes.get_var()?, +1204 ect1: self.bytes.get_var()?, +1205 ce: self.bytes.get_var()?, +1206 }) +1207 }, +1208 }) +1209 } +1210 FrameType::PathChallenge => Frame::PathChallenge(self.bytes.get()?), +1211 FrameType::PathResponse => Frame::PathResponse(self.bytes.get()?), +1212 FrameType::NewConnectionId | FrameType::PathNewConnectionId => { +1213 let read_path = ty == FrameType::PathNewConnectionId; +1214 Frame::NewConnectionId(NewConnectionId::read(&mut self.bytes, read_path)?) +1215 } +1216 FrameType::Crypto => Frame::Crypto(Crypto { +1217 offset: self.bytes.get_var()?, +1218 data: self.take_len()?, +1219 }), +1220 FrameType::NewToken => Frame::NewToken(NewToken { +1221 token: self.take_len()?, +1222 }), +1223 FrameType::HandshakeDone => Frame::HandshakeDone, +1224 FrameType::AckFrequency => Frame::AckFrequency(AckFrequency { +1225 sequence: self.bytes.get()?, +1226 ack_eliciting_threshold: self.bytes.get()?, +1227 request_max_ack_delay: self.bytes.get()?, +1228 reordering_threshold: self.bytes.get()?, +1229 }), +1230 FrameType::ImmediateAck => Frame::ImmediateAck, +1231 FrameType::ObservedIpv4Addr | FrameType::ObservedIpv6Addr => { +1232 let is_ipv6 = ty == FrameType::ObservedIpv6Addr; +1233 let observed = ObservedAddr::read(&mut self.bytes, is_ipv6)?; +1234 Frame::ObservedAddr(observed) +1235 } +1236 FrameType::PathAbandon => Frame::PathAbandon(PathAbandon::decode(&mut self.bytes)?), +1237 FrameType::PathStatusAvailable => { +1238 Frame::PathStatusAvailable(PathStatusAvailable::decode(&mut self.bytes)?) +1239 } +1240 FrameType::PathStatusBackup => { +1241 Frame::PathStatusBackup(PathStatusBackup::decode(&mut self.bytes)?) +1242 } +1243 FrameType::MaxPathId => Frame::MaxPathId(MaxPathId::decode(&mut self.bytes)?), +1244 FrameType::PathsBlocked => Frame::PathsBlocked(PathsBlocked::decode(&mut self.bytes)?), +1245 FrameType::PathCidsBlocked => { +1246 Frame::PathCidsBlocked(PathCidsBlocked::decode(&mut self.bytes)?) +1247 } +1248 FrameType::AddIpv4Address | FrameType::AddIpv6Address => { +1249 let is_ipv6 = ty == FrameType::AddIpv6Address; +1250 let add_address = AddAddress::read(&mut self.bytes, is_ipv6)?; +1251 Frame::AddAddress(add_address) +1252 } +1253 FrameType::ReachOutAtIpv4 | FrameType::ReachOutAtIpv6 => { +1254 let is_ipv6 = ty == FrameType::ReachOutAtIpv6; +1255 let reach_out = ReachOut::read(&mut self.bytes, is_ipv6)?; +1256 Frame::ReachOut(reach_out) +1257 } +1258 FrameType::RemoveAddress => Frame::RemoveAddress(RemoveAddress::read(&mut self.bytes)?), +1259 FrameType::Stream(s) => Frame::Stream(Stream { +1260 id: self.bytes.get()?, +1261 offset: if s.off() { self.bytes.get_var()? } else { 0 }, +1262 fin: s.fin(), +1263 data: if s.len() { +1264 self.take_len()? +1265 } else { +1266 self.take_remaining() +1267 }, +1268 }), +1269 FrameType::Datagram(d) => Frame::Datagram(Datagram { +1270 data: if d.len() { +1271 self.take_len()? +1272 } else { +1273 self.take_remaining() +1274 }, +1275 }), +1276 }) +1277 } +1278 +1279 fn take_remaining(&mut self) -> Bytes { +1280 mem::take(&mut self.bytes) +1281 } +1282} +1283 +1284impl Iterator for Iter { +1285 type Item = Result<Frame, InvalidFrame>; +1286 fn next(&mut self) -> Option<Self::Item> { +1287 if !self.bytes.has_remaining() { +1288 return None; +1289 } +1290 match self.try_next() { +1291 Ok(x) => Some(Ok(x)), +1292 Err(e) => { +1293 // Corrupt frame, skip it and everything that follows +1294 self.bytes.clear(); +1295 Some(Err(InvalidFrame { +1296 ty: self.last_ty, +1297 reason: e.reason(), +1298 })) +1299 } +1300 } +1301 } +1302} +1303 +1304#[derive(Debug)] +1305pub(crate) struct InvalidFrame { +1306 pub(crate) ty: MaybeFrame, +1307 pub(crate) reason: &'static str, +1308} +1309 +1310impl From<InvalidFrame> for TransportError { +1311 fn from(err: InvalidFrame) -> Self { +1312 let mut te = Self::FRAME_ENCODING_ERROR(err.reason); +1313 te.frame = err.ty; +1314 te +1315 } 1316} 1317 -1318impl IterErr { -1319 fn reason(&self) -> &'static str { -1320 use IterErr::*; -1321 match *self { -1322 UnexpectedEnd => "unexpected end", -1323 InvalidFrameId => "invalid frame ID", -1324 Malformed => "malformed", -1325 } -1326 } -1327} -1328 -1329impl From<UnexpectedEnd> for IterErr { -1330 fn from(_: UnexpectedEnd) -> Self { -1331 Self::UnexpectedEnd -1332 } -1333} -1334 -1335#[derive(Debug, Clone)] -1336pub struct AckIter<'a> { -1337 largest: u64, -1338 data: &'a [u8], -1339} -1340 -1341impl<'a> AckIter<'a> { -1342 fn new(largest: u64, data: &'a [u8]) -> Self { -1343 Self { largest, data } -1344 } -1345} -1346 -1347impl Iterator for AckIter<'_> { -1348 type Item = RangeInclusive<u64>; -1349 fn next(&mut self) -> Option<RangeInclusive<u64>> { -1350 if !self.data.has_remaining() { -1351 return None; -1352 } -1353 let block = self.data.get_var().unwrap(); -1354 let largest = self.largest; -1355 if let Ok(gap) = self.data.get_var() { -1356 self.largest -= block + gap + 2; -1357 } -1358 Some(largest - block..=largest) -1359 } +1318/// Validate exactly `n` ACK ranges in `buf` and return the number of bytes they cover +1319fn scan_ack_blocks(mut buf: &[u8], largest: u64, n: usize) -> Result<usize, IterErr> { +1320 let total_len = buf.remaining(); +1321 let first_block = buf.get_var()?; +1322 let mut smallest = largest.checked_sub(first_block).ok_or(IterErr::Malformed)?; +1323 for _ in 0..n { +1324 let gap = buf.get_var()?; +1325 smallest = smallest.checked_sub(gap + 2).ok_or(IterErr::Malformed)?; +1326 let block = buf.get_var()?; +1327 smallest = smallest.checked_sub(block).ok_or(IterErr::Malformed)?; +1328 } +1329 Ok(total_len - buf.remaining()) +1330} +1331 +1332#[derive(Debug)] +1333enum IterErr { +1334 UnexpectedEnd, +1335 InvalidFrameId, +1336 Malformed, +1337} +1338 +1339impl IterErr { +1340 fn reason(&self) -> &'static str { +1341 use IterErr::*; +1342 match *self { +1343 UnexpectedEnd => "unexpected end", +1344 InvalidFrameId => "invalid frame ID", +1345 Malformed => "malformed", +1346 } +1347 } +1348} +1349 +1350impl From<UnexpectedEnd> for IterErr { +1351 fn from(_: UnexpectedEnd) -> Self { +1352 Self::UnexpectedEnd +1353 } +1354} +1355 +1356#[derive(Debug, Clone)] +1357pub struct AckIter<'a> { +1358 largest: u64, +1359 data: &'a [u8], 1360} 1361 -1362#[allow(unreachable_pub)] // fuzzing only -1363#[cfg_attr(feature = "arbitrary", derive(Arbitrary))] -1364#[derive(Debug, Copy, Clone)] -1365pub struct ResetStream { -1366 pub(crate) id: StreamId, -1367 pub(crate) error_code: VarInt, -1368 pub(crate) final_offset: VarInt, -1369} -1370 -1371impl FrameStruct for ResetStream { -1372 const SIZE_BOUND: usize = 1 + 8 + 8 + 8; -1373} -1374 -1375impl Encodable for ResetStream { -1376 fn encode<W: BufMut>(&self, out: &mut W) { -1377 out.write(FrameType::ResetStream); // 1 byte -1378 out.write(self.id); // <= 8 bytes -1379 out.write(self.error_code); // <= 8 bytes -1380 out.write(self.final_offset); // <= 8 bytes -1381 } -1382} -1383 -1384#[derive(Debug, Copy, Clone)] -1385pub(crate) struct StopSending { -1386 pub(crate) id: StreamId, -1387 pub(crate) error_code: VarInt, -1388} -1389 -1390impl FrameStruct for StopSending { -1391 const SIZE_BOUND: usize = 1 + 8 + 8; -1392} -1393 -1394impl Encodable for StopSending { -1395 fn encode<W: BufMut>(&self, out: &mut W) { -1396 out.write(FrameType::StopSending); // 1 byte -1397 out.write(self.id); // <= 8 bytes -1398 out.write(self.error_code) // <= 8 bytes -1399 } -1400} -1401 -1402#[derive(Debug, Copy, Clone, PartialEq, Eq)] -1403pub(crate) struct NewConnectionId { -1404 pub(crate) path_id: Option<PathId>, -1405 pub(crate) sequence: u64, -1406 pub(crate) retire_prior_to: u64, -1407 pub(crate) id: ConnectionId, -1408 pub(crate) reset_token: ResetToken, +1362impl<'a> AckIter<'a> { +1363 fn new(largest: u64, data: &'a [u8]) -> Self { +1364 Self { largest, data } +1365 } +1366} +1367 +1368impl Iterator for AckIter<'_> { +1369 type Item = RangeInclusive<u64>; +1370 fn next(&mut self) -> Option<RangeInclusive<u64>> { +1371 if !self.data.has_remaining() { +1372 return None; +1373 } +1374 let block = self.data.get_var().unwrap(); +1375 let largest = self.largest; +1376 if let Ok(gap) = self.data.get_var() { +1377 self.largest -= block + gap + 2; +1378 } +1379 Some(largest - block..=largest) +1380 } +1381} +1382 +1383#[allow(unreachable_pub)] // fuzzing only +1384#[cfg_attr(feature = "arbitrary", derive(Arbitrary))] +1385#[derive(Debug, Copy, Clone)] +1386pub struct ResetStream { +1387 pub(crate) id: StreamId, +1388 pub(crate) error_code: VarInt, +1389 pub(crate) final_offset: VarInt, +1390} +1391 +1392impl FrameStruct for ResetStream { +1393 const SIZE_BOUND: usize = 1 + 8 + 8 + 8; +1394} +1395 +1396impl Encodable for ResetStream { +1397 fn encode<W: BufMut>(&self, out: &mut W) { +1398 out.write(FrameType::ResetStream); // 1 byte +1399 out.write(self.id); // <= 8 bytes +1400 out.write(self.error_code); // <= 8 bytes +1401 out.write(self.final_offset); // <= 8 bytes +1402 } +1403} +1404 +1405#[derive(Debug, Copy, Clone)] +1406pub(crate) struct StopSending { +1407 pub(crate) id: StreamId, +1408 pub(crate) error_code: VarInt, 1409} 1410 -1411impl NewConnectionId { -1412 /// Maximum size of this frame when the frame type is [`FrameType::NewConnectionId`], -1413 pub(crate) const SIZE_BOUND: usize = { -1414 let type_len = FrameType::NewConnectionId.size(); -1415 let seq_max_len = 8usize; -1416 let retire_prior_to_max_len = 8usize; -1417 let cid_len_len = 1; -1418 let cid_len = 160; -1419 let reset_token_len = 16; -1420 type_len + seq_max_len + retire_prior_to_max_len + cid_len_len + cid_len + reset_token_len -1421 }; +1411impl FrameStruct for StopSending { +1412 const SIZE_BOUND: usize = 1 + 8 + 8; +1413} +1414 +1415impl Encodable for StopSending { +1416 fn encode<W: BufMut>(&self, out: &mut W) { +1417 out.write(FrameType::StopSending); // 1 byte +1418 out.write(self.id); // <= 8 bytes +1419 out.write(self.error_code) // <= 8 bytes +1420 } +1421} 1422 -1423 /// Maximum size of this frame when the frame type is [`FrameType::PathNewConnectionId`], -1424 pub(crate) const SIZE_BOUND_MULTIPATH: usize = { -1425 let type_len = FrameType::PathNewConnectionId.size(); -1426 let path_id_len = VarInt::from_u32(u32::MAX).size(); -1427 let seq_max_len = 8usize; -1428 let retire_prior_to_max_len = 8usize; -1429 let cid_len_len = 1; -1430 let cid_len = 160; -1431 let reset_token_len = 16; -1432 type_len -1433 + path_id_len -1434 + seq_max_len -1435 + retire_prior_to_max_len -1436 + cid_len_len -1437 + cid_len -1438 + reset_token_len -1439 }; -1440 -1441 pub(crate) fn get_type(&self) -> FrameType { -1442 if self.path_id.is_some() { -1443 FrameType::PathNewConnectionId -1444 } else { -1445 FrameType::NewConnectionId -1446 } -1447 } -1448 -1449 /// Returns the maximum encoded size on the wire. -1450 /// -1451 /// This is a rough upper estimate, does not squeeze every last byte out. -1452 pub(crate) const fn size_bound(path_new_cid: bool, cid_len: usize) -> usize { -1453 let upper_bound = match path_new_cid { -1454 true => Self::SIZE_BOUND_MULTIPATH, -1455 false => Self::SIZE_BOUND, -1456 }; -1457 // instead of using the maximum cid len, use the provided one -1458 upper_bound - 160 + cid_len -1459 } -1460 -1461 fn read<R: Buf>(bytes: &mut R, read_path: bool) -> Result<Self, IterErr> { -1462 let path_id = if read_path { Some(bytes.get()?) } else { None }; -1463 let sequence = bytes.get_var()?; -1464 let retire_prior_to = bytes.get_var()?; -1465 if retire_prior_to > sequence { -1466 return Err(IterErr::Malformed); +1423#[derive(Debug, Copy, Clone, PartialEq, Eq)] +1424pub(crate) struct NewConnectionId { +1425 pub(crate) path_id: Option<PathId>, +1426 pub(crate) sequence: u64, +1427 pub(crate) retire_prior_to: u64, +1428 pub(crate) id: ConnectionId, +1429 pub(crate) reset_token: ResetToken, +1430} +1431 +1432impl NewConnectionId { +1433 /// Maximum size of this frame when the frame type is [`FrameType::NewConnectionId`], +1434 pub(crate) const SIZE_BOUND: usize = { +1435 let type_len = FrameType::NewConnectionId.size(); +1436 let seq_max_len = 8usize; +1437 let retire_prior_to_max_len = 8usize; +1438 let cid_len_len = 1; +1439 let cid_len = 160; +1440 let reset_token_len = 16; +1441 type_len + seq_max_len + retire_prior_to_max_len + cid_len_len + cid_len + reset_token_len +1442 }; +1443 +1444 /// Maximum size of this frame when the frame type is [`FrameType::PathNewConnectionId`], +1445 pub(crate) const SIZE_BOUND_MULTIPATH: usize = { +1446 let type_len = FrameType::PathNewConnectionId.size(); +1447 let path_id_len = VarInt::from_u32(u32::MAX).size(); +1448 let seq_max_len = 8usize; +1449 let retire_prior_to_max_len = 8usize; +1450 let cid_len_len = 1; +1451 let cid_len = 160; +1452 let reset_token_len = 16; +1453 type_len +1454 + path_id_len +1455 + seq_max_len +1456 + retire_prior_to_max_len +1457 + cid_len_len +1458 + cid_len +1459 + reset_token_len +1460 }; +1461 +1462 pub(crate) fn get_type(&self) -> FrameType { +1463 if self.path_id.is_some() { +1464 FrameType::PathNewConnectionId +1465 } else { +1466 FrameType::NewConnectionId 1467 } -1468 let length = bytes.get::<u8>()? as usize; -1469 if length > MAX_CID_SIZE || length == 0 { -1470 return Err(IterErr::Malformed); -1471 } -1472 if length > bytes.remaining() { -1473 return Err(IterErr::UnexpectedEnd); -1474 } -1475 let mut stage = [0; MAX_CID_SIZE]; -1476 bytes.copy_to_slice(&mut stage[0..length]); -1477 let id = ConnectionId::new(&stage[..length]); -1478 if bytes.remaining() < 16 { -1479 return Err(IterErr::UnexpectedEnd); -1480 } -1481 let mut reset_token = [0; RESET_TOKEN_SIZE]; -1482 bytes.copy_to_slice(&mut reset_token); -1483 Ok(Self { -1484 path_id, -1485 sequence, -1486 retire_prior_to, -1487 id, -1488 reset_token: reset_token.into(), -1489 }) -1490 } -1491} -1492 -1493impl Encodable for NewConnectionId { -1494 fn encode<W: BufMut>(&self, out: &mut W) { -1495 out.write(self.get_type()); -1496 if let Some(id) = self.path_id { -1497 out.write(id); -1498 } -1499 out.write_var(self.sequence); -1500 out.write_var(self.retire_prior_to); -1501 out.write(self.id.len() as u8); -1502 out.put_slice(&self.id); -1503 out.put_slice(&self.reset_token); -1504 } -1505} -1506 -1507impl FrameStruct for NewConnectionId { -1508 const SIZE_BOUND: usize = 1 + 8 + 8 + 1 + MAX_CID_SIZE + RESET_TOKEN_SIZE; -1509} -1510 -1511/// An unreliable datagram -1512#[derive(Debug, Clone)] -1513pub struct Datagram { -1514 /// Payload -1515 pub data: Bytes, -1516} -1517 -1518impl FrameStruct for Datagram { -1519 const SIZE_BOUND: usize = 1 + 8; -1520} -1521 -1522impl Datagram { -1523 pub(crate) fn size(&self, length: bool) -> usize { -1524 1 + if length { -1525 VarInt::from_u64(self.data.len() as u64).unwrap().size() -1526 } else { -1527 0 -1528 } + self.data.len() -1529 } +1468 } +1469 +1470 /// Returns the maximum encoded size on the wire. +1471 /// +1472 /// This is a rough upper estimate, does not squeeze every last byte out. +1473 pub(crate) const fn size_bound(path_new_cid: bool, cid_len: usize) -> usize { +1474 let upper_bound = match path_new_cid { +1475 true => Self::SIZE_BOUND_MULTIPATH, +1476 false => Self::SIZE_BOUND, +1477 }; +1478 // instead of using the maximum cid len, use the provided one +1479 upper_bound - 160 + cid_len +1480 } +1481 +1482 fn read<R: Buf>(bytes: &mut R, read_path: bool) -> Result<Self, IterErr> { +1483 let path_id = if read_path { Some(bytes.get()?) } else { None }; +1484 let sequence = bytes.get_var()?; +1485 let retire_prior_to = bytes.get_var()?; +1486 if retire_prior_to > sequence { +1487 return Err(IterErr::Malformed); +1488 } +1489 let length = bytes.get::<u8>()? as usize; +1490 if length > MAX_CID_SIZE || length == 0 { +1491 return Err(IterErr::Malformed); +1492 } +1493 if length > bytes.remaining() { +1494 return Err(IterErr::UnexpectedEnd); +1495 } +1496 let mut stage = [0; MAX_CID_SIZE]; +1497 bytes.copy_to_slice(&mut stage[0..length]); +1498 let id = ConnectionId::new(&stage[..length]); +1499 if bytes.remaining() < 16 { +1500 return Err(IterErr::UnexpectedEnd); +1501 } +1502 let mut reset_token = [0; RESET_TOKEN_SIZE]; +1503 bytes.copy_to_slice(&mut reset_token); +1504 Ok(Self { +1505 path_id, +1506 sequence, +1507 retire_prior_to, +1508 id, +1509 reset_token: reset_token.into(), +1510 }) +1511 } +1512} +1513 +1514impl Encodable for NewConnectionId { +1515 fn encode<W: BufMut>(&self, out: &mut W) { +1516 out.write(self.get_type()); +1517 if let Some(id) = self.path_id { +1518 out.write(id); +1519 } +1520 out.write_var(self.sequence); +1521 out.write_var(self.retire_prior_to); +1522 out.write(self.id.len() as u8); +1523 out.put_slice(&self.id); +1524 out.put_slice(&self.reset_token); +1525 } +1526} +1527 +1528impl FrameStruct for NewConnectionId { +1529 const SIZE_BOUND: usize = 1 + 8 + 8 + 1 + MAX_CID_SIZE + RESET_TOKEN_SIZE; 1530} 1531 -1532impl Encodable for Datagram { -1533 fn encode<B: BufMut>(&self, out: &mut B) { -1534 // A datagram is encoded only after this is verified. -1535 const ENCODE_LEN: bool = true; -1536 out.write(FrameType::Datagram(DatagramInfo( -1537 *DatagramInfo::VALUES.start() as u8 | u8::from(ENCODE_LEN), -1538 ))); // 1 byte -1539 // Safe to unwrap because we check length sanity before queueing datagrams -1540 out.write(VarInt::from_u64(self.data.len() as u64).unwrap()); // <= 8 bytes -1541 out.put_slice(&self.data); -1542 } -1543} -1544 -1545#[derive(Debug, Copy, Clone, PartialEq, Eq)] -1546pub(crate) struct AckFrequency { -1547 pub(crate) sequence: VarInt, -1548 pub(crate) ack_eliciting_threshold: VarInt, -1549 pub(crate) request_max_ack_delay: VarInt, -1550 pub(crate) reordering_threshold: VarInt, +1532/// An unreliable datagram +1533#[derive(Debug, Clone)] +1534pub struct Datagram { +1535 /// Payload +1536 pub data: Bytes, +1537} +1538 +1539impl FrameStruct for Datagram { +1540 const SIZE_BOUND: usize = 1 + 8; +1541} +1542 +1543impl Datagram { +1544 pub(crate) fn size(&self, length: bool) -> usize { +1545 1 + if length { +1546 VarInt::from_u64(self.data.len() as u64).unwrap().size() +1547 } else { +1548 0 +1549 } + self.data.len() +1550 } 1551} 1552 -1553impl Encodable for AckFrequency { -1554 fn encode<W: BufMut>(&self, buf: &mut W) { -1555 buf.write(FrameType::AckFrequency); -1556 buf.write(self.sequence); -1557 buf.write(self.ack_eliciting_threshold); -1558 buf.write(self.request_max_ack_delay); -1559 buf.write(self.reordering_threshold); -1560 } -1561} -1562 -1563/* Address Discovery https://datatracker.ietf.org/doc/draft-seemann-quic-address-discovery/ */ -1564 -1565/// Conjunction of the information contained in the address discovery frames -1566/// ([`FrameType::ObservedIpv4Addr`], [`FrameType::ObservedIpv6Addr`]). -1567#[derive(Debug, PartialEq, Eq, Clone)] -1568pub(crate) struct ObservedAddr { -1569 /// Monotonically increasing integer within the same connection. -1570 pub(crate) seq_no: VarInt, -1571 /// Reported observed address. -1572 pub(crate) ip: IpAddr, -1573 /// Reported observed port. -1574 pub(crate) port: u16, -1575} -1576 -1577impl ObservedAddr { -1578 pub(crate) fn new<N: Into<VarInt>>(remote: std::net::SocketAddr, seq_no: N) -> Self { -1579 Self { -1580 ip: remote.ip(), -1581 port: remote.port(), -1582 seq_no: seq_no.into(), -1583 } -1584 } +1553impl Encodable for Datagram { +1554 fn encode<B: BufMut>(&self, out: &mut B) { +1555 // A datagram is encoded only after this is verified. +1556 const ENCODE_LEN: bool = true; +1557 out.write(FrameType::Datagram(DatagramInfo( +1558 *DatagramInfo::VALUES.start() as u8 | u8::from(ENCODE_LEN), +1559 ))); // 1 byte +1560 // Safe to unwrap because we check length sanity before queueing datagrams +1561 out.write(VarInt::from_u64(self.data.len() as u64).unwrap()); // <= 8 bytes +1562 out.put_slice(&self.data); +1563 } +1564} +1565 +1566#[derive(Debug, Copy, Clone, PartialEq, Eq)] +1567pub(crate) struct AckFrequency { +1568 pub(crate) sequence: VarInt, +1569 pub(crate) ack_eliciting_threshold: VarInt, +1570 pub(crate) request_max_ack_delay: VarInt, +1571 pub(crate) reordering_threshold: VarInt, +1572} +1573 +1574impl Encodable for AckFrequency { +1575 fn encode<W: BufMut>(&self, buf: &mut W) { +1576 buf.write(FrameType::AckFrequency); +1577 buf.write(self.sequence); +1578 buf.write(self.ack_eliciting_threshold); +1579 buf.write(self.request_max_ack_delay); +1580 buf.write(self.reordering_threshold); +1581 } +1582} +1583 +1584/* Address Discovery https://datatracker.ietf.org/doc/draft-seemann-quic-address-discovery/ */ 1585 -1586 /// Get the [`FrameType`] for this frame. -1587 pub(crate) fn get_type(&self) -> FrameType { -1588 if self.ip.is_ipv6() { -1589 FrameType::ObservedIpv6Addr -1590 } else { -1591 FrameType::ObservedIpv4Addr -1592 } -1593 } -1594 -1595 /// Compute the number of bytes needed to encode the frame. -1596 pub(crate) fn size(&self) -> usize { -1597 let type_size = self.get_type().size(); -1598 let req_id_bytes = self.seq_no.size(); -1599 let ip_bytes = if self.ip.is_ipv6() { 16 } else { 4 }; -1600 let port_bytes = 2; -1601 type_size + req_id_bytes + ip_bytes + port_bytes -1602 } -1603 -1604 /// Reads the frame contents from the buffer. -1605 /// -1606 /// Should only be called when the frame type has been identified as -1607 /// [`FrameType::ObservedIpv4Addr`] or [`FrameType::ObservedIpv6Addr`]. -1608 pub(crate) fn read<R: Buf>(bytes: &mut R, is_ipv6: bool) -> coding::Result<Self> { -1609 let seq_no = bytes.get()?; -1610 let ip = if is_ipv6 { -1611 IpAddr::V6(bytes.get()?) -1612 } else { -1613 IpAddr::V4(bytes.get()?) -1614 }; -1615 let port = bytes.get()?; -1616 Ok(Self { seq_no, ip, port }) -1617 } -1618 -1619 /// Gives the [`SocketAddr`] reported in the frame. -1620 pub(crate) fn socket_addr(&self) -> SocketAddr { -1621 (self.ip, self.port).into() -1622 } -1623} +1586/// Conjunction of the information contained in the address discovery frames +1587/// ([`FrameType::ObservedIpv4Addr`], [`FrameType::ObservedIpv6Addr`]). +1588#[derive(Debug, PartialEq, Eq, Clone)] +1589pub(crate) struct ObservedAddr { +1590 /// Monotonically increasing integer within the same connection. +1591 pub(crate) seq_no: VarInt, +1592 /// Reported observed address. +1593 pub(crate) ip: IpAddr, +1594 /// Reported observed port. +1595 pub(crate) port: u16, +1596} +1597 +1598impl ObservedAddr { +1599 pub(crate) fn new<N: Into<VarInt>>(remote: std::net::SocketAddr, seq_no: N) -> Self { +1600 Self { +1601 ip: remote.ip(), +1602 port: remote.port(), +1603 seq_no: seq_no.into(), +1604 } +1605 } +1606 +1607 /// Get the [`FrameType`] for this frame. +1608 pub(crate) fn get_type(&self) -> FrameType { +1609 if self.ip.is_ipv6() { +1610 FrameType::ObservedIpv6Addr +1611 } else { +1612 FrameType::ObservedIpv4Addr +1613 } +1614 } +1615 +1616 /// Compute the number of bytes needed to encode the frame. +1617 pub(crate) fn size(&self) -> usize { +1618 let type_size = self.get_type().size(); +1619 let req_id_bytes = self.seq_no.size(); +1620 let ip_bytes = if self.ip.is_ipv6() { 16 } else { 4 }; +1621 let port_bytes = 2; +1622 type_size + req_id_bytes + ip_bytes + port_bytes +1623 } 1624 -1625impl Encodable for ObservedAddr { -1626 fn encode<W: BufMut>(&self, buf: &mut W) { -1627 buf.write(self.get_type()); -1628 buf.write(self.seq_no); -1629 match self.ip { -1630 IpAddr::V4(ipv4_addr) => { -1631 buf.write(ipv4_addr); -1632 } -1633 IpAddr::V6(ipv6_addr) => { -1634 buf.write(ipv6_addr); -1635 } -1636 } -1637 buf.write::<u16>(self.port); +1625 /// Reads the frame contents from the buffer. +1626 /// +1627 /// Should only be called when the frame type has been identified as +1628 /// [`FrameType::ObservedIpv4Addr`] or [`FrameType::ObservedIpv6Addr`]. +1629 pub(crate) fn read<R: Buf>(bytes: &mut R, is_ipv6: bool) -> coding::Result<Self> { +1630 let seq_no = bytes.get()?; +1631 let ip = if is_ipv6 { +1632 IpAddr::V6(bytes.get()?) +1633 } else { +1634 IpAddr::V4(bytes.get()?) +1635 }; +1636 let port = bytes.get()?; +1637 Ok(Self { seq_no, ip, port }) 1638 } -1639} -1640 -1641/* Multipath <https://datatracker.ietf.org/doc/draft-ietf-quic-multipath/> */ -1642 -1643#[derive(Debug, PartialEq, Eq)] -1644pub(crate) struct PathAbandon { -1645 pub(crate) path_id: PathId, -1646 pub(crate) error_code: TransportErrorCode, -1647} -1648 -1649impl PathAbandon { -1650 pub(crate) const SIZE_BOUND: usize = FrameType::PathAbandon.size() + 8 + 8; -1651} -1652 -1653impl Encodable for PathAbandon { -1654 fn encode<W: BufMut>(&self, buf: &mut W) { -1655 buf.write(FrameType::PathAbandon); -1656 buf.write(self.path_id); -1657 buf.write(self.error_code); -1658 } -1659} -1660 -1661impl Decodable for PathAbandon { -1662 fn decode<R: Buf>(bytes: &mut R) -> coding::Result<Self> { -1663 Ok(Self { -1664 path_id: bytes.get()?, -1665 error_code: bytes.get()?, -1666 }) -1667 } +1639 +1640 /// Gives the [`SocketAddr`] reported in the frame. +1641 pub(crate) fn socket_addr(&self) -> SocketAddr { +1642 (self.ip, self.port).into() +1643 } +1644} +1645 +1646impl Encodable for ObservedAddr { +1647 fn encode<W: BufMut>(&self, buf: &mut W) { +1648 buf.write(self.get_type()); +1649 buf.write(self.seq_no); +1650 match self.ip { +1651 IpAddr::V4(ipv4_addr) => { +1652 buf.write(ipv4_addr); +1653 } +1654 IpAddr::V6(ipv6_addr) => { +1655 buf.write(ipv6_addr); +1656 } +1657 } +1658 buf.write::<u16>(self.port); +1659 } +1660} +1661 +1662/* Multipath <https://datatracker.ietf.org/doc/draft-ietf-quic-multipath/> */ +1663 +1664#[derive(Debug, PartialEq, Eq)] +1665pub(crate) struct PathAbandon { +1666 pub(crate) path_id: PathId, +1667 pub(crate) error_code: TransportErrorCode, 1668} 1669 -1670#[derive(Debug, PartialEq, Eq)] -1671pub(crate) struct PathStatusAvailable { -1672 pub(crate) path_id: PathId, -1673 pub(crate) status_seq_no: VarInt, -1674} -1675 -1676impl PathStatusAvailable { -1677 const TYPE: FrameType = FrameType::PathStatusAvailable; -1678 pub(crate) const SIZE_BOUND: usize = FrameType::PathStatusAvailable.size() + 8 + 8; -1679} -1680 -1681impl Encodable for PathStatusAvailable { -1682 fn encode<W: BufMut>(&self, buf: &mut W) { -1683 buf.write(Self::TYPE); -1684 buf.write(self.path_id); -1685 buf.write(self.status_seq_no); -1686 } -1687} -1688 -1689impl Decodable for PathStatusAvailable { -1690 fn decode<R: Buf>(bytes: &mut R) -> coding::Result<Self> { -1691 Ok(Self { -1692 path_id: bytes.get()?, -1693 status_seq_no: bytes.get()?, -1694 }) -1695 } -1696} -1697 -1698#[derive(Debug, PartialEq, Eq)] -1699pub(crate) struct PathStatusBackup { -1700 pub(crate) path_id: PathId, -1701 pub(crate) status_seq_no: VarInt, -1702} -1703 -1704impl PathStatusBackup { -1705 const TYPE: FrameType = FrameType::PathStatusBackup; -1706} -1707 -1708impl Encodable for PathStatusBackup { -1709 fn encode<W: BufMut>(&self, buf: &mut W) { -1710 buf.write(Self::TYPE); -1711 buf.write(self.path_id); -1712 buf.write(self.status_seq_no); -1713 } -1714} -1715 -1716impl Decodable for PathStatusBackup { -1717 fn decode<R: Buf>(bytes: &mut R) -> coding::Result<Self> { -1718 Ok(Self { -1719 path_id: bytes.get()?, -1720 status_seq_no: bytes.get()?, -1721 }) -1722 } +1670impl PathAbandon { +1671 pub(crate) const SIZE_BOUND: usize = FrameType::PathAbandon.size() + 8 + 8; +1672} +1673 +1674impl Encodable for PathAbandon { +1675 fn encode<W: BufMut>(&self, buf: &mut W) { +1676 buf.write(FrameType::PathAbandon); +1677 buf.write(self.path_id); +1678 buf.write(self.error_code); +1679 } +1680} +1681 +1682impl Decodable for PathAbandon { +1683 fn decode<R: Buf>(bytes: &mut R) -> coding::Result<Self> { +1684 Ok(Self { +1685 path_id: bytes.get()?, +1686 error_code: bytes.get()?, +1687 }) +1688 } +1689} +1690 +1691#[derive(Debug, PartialEq, Eq)] +1692pub(crate) struct PathStatusAvailable { +1693 pub(crate) path_id: PathId, +1694 pub(crate) status_seq_no: VarInt, +1695} +1696 +1697impl PathStatusAvailable { +1698 const TYPE: FrameType = FrameType::PathStatusAvailable; +1699 pub(crate) const SIZE_BOUND: usize = FrameType::PathStatusAvailable.size() + 8 + 8; +1700} +1701 +1702impl Encodable for PathStatusAvailable { +1703 fn encode<W: BufMut>(&self, buf: &mut W) { +1704 buf.write(Self::TYPE); +1705 buf.write(self.path_id); +1706 buf.write(self.status_seq_no); +1707 } +1708} +1709 +1710impl Decodable for PathStatusAvailable { +1711 fn decode<R: Buf>(bytes: &mut R) -> coding::Result<Self> { +1712 Ok(Self { +1713 path_id: bytes.get()?, +1714 status_seq_no: bytes.get()?, +1715 }) +1716 } +1717} +1718 +1719#[derive(Debug, PartialEq, Eq)] +1720pub(crate) struct PathStatusBackup { +1721 pub(crate) path_id: PathId, +1722 pub(crate) status_seq_no: VarInt, 1723} 1724 -1725/* Nat traversal frames */ -1726 -1727/// Conjunction of the information contained in the add address frames -1728/// ([`FrameType::AddIpv4Address`], [`FrameType::AddIpv6Address`]). -1729#[derive(Debug, PartialEq, Eq, Copy, Clone, PartialOrd, Ord)] -1730// TODO(@divma): remove -1731#[allow(dead_code)] -1732pub(crate) struct AddAddress { -1733 /// Monotonically increasing integer within the same connection -1734 // TODO(@divma): both assumed, the draft has no mention of this but it's standard -1735 pub(crate) seq_no: VarInt, -1736 /// Address to include in the known set -1737 pub(crate) ip: IpAddr, -1738 /// Port to use with this address -1739 pub(crate) port: u16, -1740} -1741 -1742// TODO(@divma): remove -1743#[allow(dead_code)] -1744impl AddAddress { -1745 /// Smallest number of bytes this type of frame is guaranteed to fit within. -1746 pub(crate) const SIZE_BOUND: usize = Self { -1747 ip: IpAddr::V6(std::net::Ipv6Addr::LOCALHOST), -1748 port: u16::MAX, -1749 seq_no: VarInt::MAX, -1750 } -1751 .size(); -1752 -1753 pub(crate) const fn new((ip, port): (IpAddr, u16), seq_no: VarInt) -> Self { -1754 Self { ip, port, seq_no } -1755 } -1756 -1757 /// Get the [`FrameType`] for this frame. -1758 pub(crate) const fn get_type(&self) -> FrameType { -1759 if self.ip.is_ipv6() { -1760 FrameType::AddIpv6Address -1761 } else { -1762 FrameType::AddIpv4Address -1763 } -1764 } -1765 -1766 /// Compute the number of bytes needed to encode the frame -1767 pub(crate) const fn size(&self) -> usize { -1768 let type_size = self.get_type().size(); -1769 let seq_no_bytes = self.seq_no.size(); -1770 let ip_bytes = if self.ip.is_ipv6() { 16 } else { 4 }; -1771 let port_bytes = 2; -1772 type_size + seq_no_bytes + ip_bytes + port_bytes -1773 } -1774 -1775 /// Read the frame contents from the buffer -1776 /// -1777 /// Should only be called when the frame type has been identified as -1778 /// [`FrameType::AddIpv4Address`] or [`FrameType::AddIpv6Address`]. -1779 pub(crate) fn read<R: Buf>(bytes: &mut R, is_ipv6: bool) -> coding::Result<Self> { -1780 let seq_no = bytes.get()?; -1781 let ip = if is_ipv6 { -1782 IpAddr::V6(bytes.get()?) -1783 } else { -1784 IpAddr::V4(bytes.get()?) -1785 }; -1786 let port = bytes.get()?; -1787 Ok(Self { seq_no, ip, port }) -1788 } -1789 -1790 /// Give the [`SocketAddr`] encoded in the frame -1791 pub(crate) fn socket_addr(&self) -> SocketAddr { -1792 self.ip_port().into() -1793 } -1794 -1795 pub(crate) fn ip_port(&self) -> (IpAddr, u16) { -1796 (self.ip, self.port) -1797 } -1798} -1799 -1800impl Encodable for AddAddress { -1801 fn encode<W: BufMut>(&self, buf: &mut W) { -1802 buf.write(self.get_type()); -1803 buf.write(self.seq_no); -1804 match self.ip { -1805 IpAddr::V4(ipv4_addr) => { -1806 buf.write(ipv4_addr); -1807 } -1808 IpAddr::V6(ipv6_addr) => { -1809 buf.write(ipv6_addr); -1810 } -1811 } -1812 buf.write::<u16>(self.port); -1813 } -1814} +1725impl PathStatusBackup { +1726 const TYPE: FrameType = FrameType::PathStatusBackup; +1727} +1728 +1729impl Encodable for PathStatusBackup { +1730 fn encode<W: BufMut>(&self, buf: &mut W) { +1731 buf.write(Self::TYPE); +1732 buf.write(self.path_id); +1733 buf.write(self.status_seq_no); +1734 } +1735} +1736 +1737impl Decodable for PathStatusBackup { +1738 fn decode<R: Buf>(bytes: &mut R) -> coding::Result<Self> { +1739 Ok(Self { +1740 path_id: bytes.get()?, +1741 status_seq_no: bytes.get()?, +1742 }) +1743 } +1744} +1745 +1746/* Nat traversal frames */ +1747 +1748/// Conjunction of the information contained in the add address frames +1749/// ([`FrameType::AddIpv4Address`], [`FrameType::AddIpv6Address`]). +1750#[derive(Debug, PartialEq, Eq, Copy, Clone, PartialOrd, Ord)] +1751// TODO(@divma): remove +1752#[allow(dead_code)] +1753pub(crate) struct AddAddress { +1754 /// Monotonically increasing integer within the same connection +1755 // TODO(@divma): both assumed, the draft has no mention of this but it's standard +1756 pub(crate) seq_no: VarInt, +1757 /// Address to include in the known set +1758 pub(crate) ip: IpAddr, +1759 /// Port to use with this address +1760 pub(crate) port: u16, +1761} +1762 +1763// TODO(@divma): remove +1764#[allow(dead_code)] +1765impl AddAddress { +1766 /// Smallest number of bytes this type of frame is guaranteed to fit within. +1767 pub(crate) const SIZE_BOUND: usize = Self { +1768 ip: IpAddr::V6(std::net::Ipv6Addr::LOCALHOST), +1769 port: u16::MAX, +1770 seq_no: VarInt::MAX, +1771 } +1772 .size(); +1773 +1774 pub(crate) const fn new((ip, port): (IpAddr, u16), seq_no: VarInt) -> Self { +1775 Self { ip, port, seq_no } +1776 } +1777 +1778 /// Get the [`FrameType`] for this frame. +1779 pub(crate) const fn get_type(&self) -> FrameType { +1780 if self.ip.is_ipv6() { +1781 FrameType::AddIpv6Address +1782 } else { +1783 FrameType::AddIpv4Address +1784 } +1785 } +1786 +1787 /// Compute the number of bytes needed to encode the frame +1788 pub(crate) const fn size(&self) -> usize { +1789 let type_size = self.get_type().size(); +1790 let seq_no_bytes = self.seq_no.size(); +1791 let ip_bytes = if self.ip.is_ipv6() { 16 } else { 4 }; +1792 let port_bytes = 2; +1793 type_size + seq_no_bytes + ip_bytes + port_bytes +1794 } +1795 +1796 /// Read the frame contents from the buffer +1797 /// +1798 /// Should only be called when the frame type has been identified as +1799 /// [`FrameType::AddIpv4Address`] or [`FrameType::AddIpv6Address`]. +1800 pub(crate) fn read<R: Buf>(bytes: &mut R, is_ipv6: bool) -> coding::Result<Self> { +1801 let seq_no = bytes.get()?; +1802 let ip = if is_ipv6 { +1803 IpAddr::V6(bytes.get()?) +1804 } else { +1805 IpAddr::V4(bytes.get()?) +1806 }; +1807 let port = bytes.get()?; +1808 Ok(Self { seq_no, ip, port }) +1809 } +1810 +1811 /// Give the [`SocketAddr`] encoded in the frame +1812 pub(crate) fn socket_addr(&self) -> SocketAddr { +1813 self.ip_port().into() +1814 } 1815 -1816/// Conjunction of the information contained in the reach out frames -1817/// ([`FrameType::ReachOutAtIpv4`], [`FrameType::ReachOutAtIpv6`]) -1818#[derive(Debug, PartialEq, Eq, Clone)] -1819// TODO(@divma): remove -1820#[allow(dead_code)] -1821pub(crate) struct ReachOut { -1822 /// The sequence number of the NAT Traversal attempts -1823 pub(crate) round: VarInt, -1824 /// Address to use -1825 pub(crate) ip: IpAddr, -1826 /// Port to use with this address -1827 pub(crate) port: u16, -1828} -1829 -1830// TODO(@divma): remove -1831#[allow(dead_code)] -1832impl ReachOut { -1833 /// Smallest number of bytes this type of frame is guaranteed to fit within -1834 pub(crate) const SIZE_BOUND: usize = Self { -1835 round: VarInt::MAX, -1836 ip: IpAddr::V6(std::net::Ipv6Addr::LOCALHOST), -1837 port: u16::MAX, -1838 } -1839 .size(); -1840 -1841 pub(crate) const fn new(round: VarInt, (ip, port): (IpAddr, u16)) -> Self { -1842 Self { round, ip, port } -1843 } -1844 -1845 /// Get the [`FrameType`] for this frame -1846 pub(crate) const fn get_type(&self) -> FrameType { -1847 if self.ip.is_ipv6() { -1848 FrameType::ReachOutAtIpv6 -1849 } else { -1850 FrameType::ReachOutAtIpv4 -1851 } -1852 } -1853 -1854 /// Compute the number of bytes needed to encode the frame -1855 pub(crate) const fn size(&self) -> usize { -1856 let type_size = self.get_type().size(); -1857 let round_bytes = self.round.size(); -1858 let ip_bytes = if self.ip.is_ipv6() { 16 } else { 4 }; -1859 let port_bytes = 2; -1860 type_size + round_bytes + ip_bytes + port_bytes -1861 } -1862 -1863 /// Read the frame contents from the buffer -1864 /// -1865 /// Should only be called when the frame type has been identified as -1866 /// [`FrameType::ReachOutAtIpv4`] or [`FrameType::ReachOutAtIpv6`]. -1867 pub(crate) fn read<R: Buf>(bytes: &mut R, is_ipv6: bool) -> coding::Result<Self> { -1868 let round = bytes.get()?; -1869 let ip = if is_ipv6 { -1870 IpAddr::V6(bytes.get()?) -1871 } else { -1872 IpAddr::V4(bytes.get()?) -1873 }; -1874 let port = bytes.get()?; -1875 Ok(Self { round, ip, port }) -1876 } -1877 -1878 /// Give the [`SocketAddr`] encoded in the frame -1879 pub(crate) fn socket_addr(&self) -> SocketAddr { -1880 (self.ip, self.port).into() -1881 } -1882} +1816 pub(crate) fn ip_port(&self) -> (IpAddr, u16) { +1817 (self.ip, self.port) +1818 } +1819} +1820 +1821impl Encodable for AddAddress { +1822 fn encode<W: BufMut>(&self, buf: &mut W) { +1823 buf.write(self.get_type()); +1824 buf.write(self.seq_no); +1825 match self.ip { +1826 IpAddr::V4(ipv4_addr) => { +1827 buf.write(ipv4_addr); +1828 } +1829 IpAddr::V6(ipv6_addr) => { +1830 buf.write(ipv6_addr); +1831 } +1832 } +1833 buf.write::<u16>(self.port); +1834 } +1835} +1836 +1837/// Conjunction of the information contained in the reach out frames +1838/// ([`FrameType::ReachOutAtIpv4`], [`FrameType::ReachOutAtIpv6`]) +1839#[derive(Debug, PartialEq, Eq, Clone)] +1840// TODO(@divma): remove +1841#[allow(dead_code)] +1842pub(crate) struct ReachOut { +1843 /// The sequence number of the NAT Traversal attempts +1844 pub(crate) round: VarInt, +1845 /// Address to use +1846 pub(crate) ip: IpAddr, +1847 /// Port to use with this address +1848 pub(crate) port: u16, +1849} +1850 +1851// TODO(@divma): remove +1852#[allow(dead_code)] +1853impl ReachOut { +1854 /// Smallest number of bytes this type of frame is guaranteed to fit within +1855 pub(crate) const SIZE_BOUND: usize = Self { +1856 round: VarInt::MAX, +1857 ip: IpAddr::V6(std::net::Ipv6Addr::LOCALHOST), +1858 port: u16::MAX, +1859 } +1860 .size(); +1861 +1862 pub(crate) const fn new(round: VarInt, (ip, port): (IpAddr, u16)) -> Self { +1863 Self { round, ip, port } +1864 } +1865 +1866 /// Get the [`FrameType`] for this frame +1867 pub(crate) const fn get_type(&self) -> FrameType { +1868 if self.ip.is_ipv6() { +1869 FrameType::ReachOutAtIpv6 +1870 } else { +1871 FrameType::ReachOutAtIpv4 +1872 } +1873 } +1874 +1875 /// Compute the number of bytes needed to encode the frame +1876 pub(crate) const fn size(&self) -> usize { +1877 let type_size = self.get_type().size(); +1878 let round_bytes = self.round.size(); +1879 let ip_bytes = if self.ip.is_ipv6() { 16 } else { 4 }; +1880 let port_bytes = 2; +1881 type_size + round_bytes + ip_bytes + port_bytes +1882 } 1883 -1884impl Encodable for ReachOut { -1885 fn encode<W: BufMut>(&self, buf: &mut W) { -1886 buf.write(self.get_type()); -1887 buf.write(self.round); -1888 match self.ip { -1889 IpAddr::V4(ipv4_addr) => { -1890 buf.write(ipv4_addr); -1891 } -1892 IpAddr::V6(ipv6_addr) => { -1893 buf.write(ipv6_addr); -1894 } -1895 } -1896 buf.write::<u16>(self.port); +1884 /// Read the frame contents from the buffer +1885 /// +1886 /// Should only be called when the frame type has been identified as +1887 /// [`FrameType::ReachOutAtIpv4`] or [`FrameType::ReachOutAtIpv6`]. +1888 pub(crate) fn read<R: Buf>(bytes: &mut R, is_ipv6: bool) -> coding::Result<Self> { +1889 let round = bytes.get()?; +1890 let ip = if is_ipv6 { +1891 IpAddr::V6(bytes.get()?) +1892 } else { +1893 IpAddr::V4(bytes.get()?) +1894 }; +1895 let port = bytes.get()?; +1896 Ok(Self { round, ip, port }) 1897 } -1898} -1899 -1900/// Frame signaling an address is no longer being advertised -1901#[derive(Debug, PartialEq, Eq, Copy, Clone, PartialOrd, Ord)] -1902// TODO(@divma): remove -1903#[allow(dead_code)] -1904pub(crate) struct RemoveAddress { -1905 /// The sequence number of the address advertisement to be removed -1906 pub(crate) seq_no: VarInt, -1907} -1908 -1909// TODO(@divma): remove -1910#[allow(dead_code)] -1911impl RemoveAddress { -1912 /// [`FrameType`] of this frame -1913 pub(crate) const TYPE: FrameType = FrameType::RemoveAddress; -1914 -1915 /// Smallest number of bytes this type of frame is guaranteed to fit within -1916 pub(crate) const SIZE_BOUND: usize = Self::new(VarInt::MAX).size(); -1917 -1918 pub(crate) const fn new(seq_no: VarInt) -> Self { -1919 Self { seq_no } -1920 } -1921 -1922 /// Compute the number of bytes needed to encode the frame -1923 pub(crate) const fn size(&self) -> usize { -1924 let type_size = Self::TYPE.size(); -1925 let seq_no_bytes = self.seq_no.size(); -1926 type_size + seq_no_bytes -1927 } -1928 -1929 /// Read the frame contents from the buffer -1930 /// -1931 /// Should only be called when the frame type has been identified as -1932 /// [`FrameType::RemoveAddress`]. -1933 pub(crate) fn read<R: Buf>(bytes: &mut R) -> coding::Result<Self> { -1934 Ok(Self { -1935 seq_no: bytes.get()?, -1936 }) -1937 } -1938} -1939 -1940impl Encodable for RemoveAddress { -1941 fn encode<W: BufMut>(&self, buf: &mut W) { -1942 buf.write(Self::TYPE); -1943 buf.write(self.seq_no); -1944 } -1945} -1946 -1947#[cfg(test)] -1948mod test { -1949 use super::*; -1950 use crate::coding::Encodable; -1951 use assert_matches::assert_matches; -1952 -1953 #[track_caller] -1954 fn frames(buf: Vec<u8>) -> Vec<Frame> { -1955 Iter::new(Bytes::from(buf)) -1956 .unwrap() -1957 .collect::<Result<Vec<_>, _>>() -1958 .unwrap() -1959 } +1898 +1899 /// Give the [`SocketAddr`] encoded in the frame +1900 pub(crate) fn socket_addr(&self) -> SocketAddr { +1901 (self.ip, self.port).into() +1902 } +1903} +1904 +1905impl Encodable for ReachOut { +1906 fn encode<W: BufMut>(&self, buf: &mut W) { +1907 buf.write(self.get_type()); +1908 buf.write(self.round); +1909 match self.ip { +1910 IpAddr::V4(ipv4_addr) => { +1911 buf.write(ipv4_addr); +1912 } +1913 IpAddr::V6(ipv6_addr) => { +1914 buf.write(ipv6_addr); +1915 } +1916 } +1917 buf.write::<u16>(self.port); +1918 } +1919} +1920 +1921/// Frame signaling an address is no longer being advertised +1922#[derive(Debug, PartialEq, Eq, Copy, Clone, PartialOrd, Ord)] +1923// TODO(@divma): remove +1924#[allow(dead_code)] +1925pub(crate) struct RemoveAddress { +1926 /// The sequence number of the address advertisement to be removed +1927 pub(crate) seq_no: VarInt, +1928} +1929 +1930// TODO(@divma): remove +1931#[allow(dead_code)] +1932impl RemoveAddress { +1933 /// [`FrameType`] of this frame +1934 pub(crate) const TYPE: FrameType = FrameType::RemoveAddress; +1935 +1936 /// Smallest number of bytes this type of frame is guaranteed to fit within +1937 pub(crate) const SIZE_BOUND: usize = Self::new(VarInt::MAX).size(); +1938 +1939 pub(crate) const fn new(seq_no: VarInt) -> Self { +1940 Self { seq_no } +1941 } +1942 +1943 /// Compute the number of bytes needed to encode the frame +1944 pub(crate) const fn size(&self) -> usize { +1945 let type_size = Self::TYPE.size(); +1946 let seq_no_bytes = self.seq_no.size(); +1947 type_size + seq_no_bytes +1948 } +1949 +1950 /// Read the frame contents from the buffer +1951 /// +1952 /// Should only be called when the frame type has been identified as +1953 /// [`FrameType::RemoveAddress`]. +1954 pub(crate) fn read<R: Buf>(bytes: &mut R) -> coding::Result<Self> { +1955 Ok(Self { +1956 seq_no: bytes.get()?, +1957 }) +1958 } +1959} 1960 -1961 #[test] -1962 fn ack_coding() { -1963 const PACKETS: &[u64] = &[1, 2, 3, 5, 10, 11, 14]; -1964 let mut ranges = ArrayRangeSet::new(); -1965 for &packet in PACKETS { -1966 ranges.insert(packet..packet + 1); -1967 } -1968 let mut buf = Vec::new(); -1969 const ECN: EcnCounts = EcnCounts { -1970 ect0: 42, -1971 ect1: 24, -1972 ce: 12, -1973 }; -1974 Ack::encoder(42, &ranges, Some(&ECN)).encode(&mut buf); -1975 let frames = frames(buf); -1976 assert_eq!(frames.len(), 1); -1977 match frames[0] { -1978 Frame::Ack(ref ack) => { -1979 let mut packets = ack.iter().flatten().collect::<Vec<_>>(); -1980 packets.sort_unstable(); -1981 assert_eq!(&packets[..], PACKETS); -1982 assert_eq!(ack.ecn, Some(ECN)); -1983 } -1984 ref x => panic!("incorrect frame {x:?}"), -1985 } -1986 } -1987 -1988 #[test] -1989 #[allow(clippy::range_plus_one)] -1990 fn path_ack_coding() { -1991 const PACKETS: &[u64] = &[1, 2, 3, 5, 10, 11, 14]; -1992 let mut ranges = ArrayRangeSet::new(); -1993 for &packet in PACKETS { -1994 ranges.insert(packet..packet + 1); -1995 } -1996 let mut buf = Vec::new(); -1997 const ECN: EcnCounts = EcnCounts { -1998 ect0: 42, -1999 ect1: 24, -2000 ce: 12, -2001 }; -2002 const PATH_ID: PathId = PathId::MAX; -2003 PathAck::encoder(PATH_ID, 42, &ranges, Some(&ECN)).encode(&mut buf); -2004 let frames = frames(buf); -2005 assert_eq!(frames.len(), 1); -2006 match frames[0] { -2007 Frame::PathAck(ref ack) => { -2008 assert_eq!(ack.path_id, PATH_ID); -2009 let mut packets = ack.into_iter().flatten().collect::<Vec<_>>(); -2010 packets.sort_unstable(); -2011 assert_eq!(&packets[..], PACKETS); -2012 assert_eq!(ack.ecn, Some(ECN)); -2013 } -2014 ref x => panic!("incorrect frame {x:?}"), -2015 } -2016 } -2017 -2018 #[test] -2019 fn ack_frequency_coding() { -2020 let mut buf = Vec::new(); -2021 let original = AckFrequency { -2022 sequence: VarInt(42), -2023 ack_eliciting_threshold: VarInt(20), -2024 request_max_ack_delay: VarInt(50_000), -2025 reordering_threshold: VarInt(1), -2026 }; -2027 original.encode(&mut buf); -2028 let frames = frames(buf); -2029 assert_eq!(frames.len(), 1); -2030 match &frames[0] { -2031 Frame::AckFrequency(decoded) => assert_eq!(decoded, &original), -2032 x => panic!("incorrect frame {x:?}"), -2033 } -2034 } -2035 -2036 #[test] -2037 fn immediate_ack_coding() { -2038 let mut buf = Vec::new(); -2039 FrameType::ImmediateAck.encode(&mut buf); -2040 let frames = frames(buf); -2041 assert_eq!(frames.len(), 1); -2042 assert_matches!(&frames[0], Frame::ImmediateAck); -2043 } -2044 -2045 /// Test that encoding and decoding [`ObservedAddr`] produces the same result. -2046 #[test] -2047 fn test_observed_addr_roundrip() { -2048 let observed_addr = ObservedAddr { -2049 seq_no: VarInt(42), -2050 ip: std::net::Ipv4Addr::LOCALHOST.into(), -2051 port: 4242, -2052 }; -2053 let mut buf = Vec::with_capacity(observed_addr.size()); -2054 observed_addr.encode(&mut buf); -2055 -2056 assert_eq!( -2057 observed_addr.size(), -2058 buf.len(), -2059 "expected written bytes and actual size differ" -2060 ); -2061 -2062 let mut decoded = frames(buf); -2063 assert_eq!(decoded.len(), 1); -2064 match decoded.pop().expect("non empty") { -2065 Frame::ObservedAddr(decoded) => assert_eq!(decoded, observed_addr), -2066 x => panic!("incorrect frame {x:?}"), -2067 } -2068 } -2069 -2070 #[test] -2071 fn test_path_abandon_roundtrip() { -2072 let abandon = PathAbandon { -2073 path_id: PathId(42), -2074 error_code: TransportErrorCode::NO_ERROR, -2075 }; -2076 let mut buf = Vec::new(); -2077 abandon.encode(&mut buf); -2078 -2079 let mut decoded = frames(buf); -2080 assert_eq!(decoded.len(), 1); -2081 match decoded.pop().expect("non empty") { -2082 Frame::PathAbandon(decoded) => assert_eq!(decoded, abandon), -2083 x => panic!("incorrect frame {x:?}"), -2084 } -2085 } -2086 -2087 #[test] -2088 fn test_path_status_available_roundtrip() { -2089 let path_status_available = PathStatusAvailable { -2090 path_id: PathId(42), -2091 status_seq_no: VarInt(73), -2092 }; -2093 let mut buf = Vec::new(); -2094 path_status_available.encode(&mut buf); -2095 -2096 let mut decoded = frames(buf); -2097 assert_eq!(decoded.len(), 1); -2098 match decoded.pop().expect("non empty") { -2099 Frame::PathStatusAvailable(decoded) => assert_eq!(decoded, path_status_available), -2100 x => panic!("incorrect frame {x:?}"), -2101 } -2102 } -2103 -2104 #[test] -2105 fn test_path_status_backup_roundtrip() { -2106 let path_status_backup = PathStatusBackup { -2107 path_id: PathId(42), -2108 status_seq_no: VarInt(73), -2109 }; -2110 let mut buf = Vec::new(); -2111 path_status_backup.encode(&mut buf); -2112 -2113 let mut decoded = frames(buf); -2114 assert_eq!(decoded.len(), 1); -2115 match decoded.pop().expect("non empty") { -2116 Frame::PathStatusBackup(decoded) => assert_eq!(decoded, path_status_backup), -2117 x => panic!("incorrect frame {x:?}"), -2118 } -2119 } -2120 -2121 #[test] -2122 fn test_path_new_connection_id_roundtrip() { -2123 let cid = NewConnectionId { -2124 path_id: Some(PathId(22)), -2125 sequence: 31, -2126 retire_prior_to: 13, -2127 id: ConnectionId::new(&[0xAB; 8]), -2128 reset_token: ResetToken::from([0xCD; crate::RESET_TOKEN_SIZE]), -2129 }; -2130 let mut buf = Vec::new(); -2131 cid.encode(&mut buf); -2132 -2133 let mut decoded = frames(buf); -2134 assert_eq!(decoded.len(), 1); -2135 match decoded.pop().expect("non empty") { -2136 Frame::NewConnectionId(decoded) => assert_eq!(decoded, cid), -2137 x => panic!("incorrect frame {x:?}"), -2138 } -2139 } -2140 -2141 #[test] -2142 fn test_path_retire_connection_id_roundtrip() { -2143 let retire_cid = RetireConnectionId { -2144 path_id: Some(PathId(22)), -2145 sequence: 31, -2146 }; -2147 let mut buf = Vec::new(); -2148 retire_cid.encode(&mut buf); -2149 -2150 let mut decoded = frames(buf); -2151 assert_eq!(decoded.len(), 1); -2152 match decoded.pop().expect("non empty") { -2153 Frame::RetireConnectionId(decoded) => assert_eq!(decoded, retire_cid), -2154 x => panic!("incorrect frame {x:?}"), -2155 } -2156 } -2157 -2158 #[test] -2159 fn test_paths_blocked_path_cids_blocked_roundtrip() { -2160 let mut buf = Vec::new(); -2161 -2162 let frame0 = PathsBlocked(PathId(22)); -2163 frame0.encode(&mut buf); -2164 let frame1 = PathCidsBlocked { -2165 path_id: PathId(23), -2166 next_seq: VarInt(32), -2167 }; -2168 frame1.encode(&mut buf); -2169 -2170 let mut decoded = frames(buf); -2171 assert_eq!(decoded.len(), 2); -2172 match decoded.pop().expect("non empty") { -2173 Frame::PathCidsBlocked(decoded) => assert_eq!(decoded, frame1), -2174 x => panic!("incorrect frame {x:?}"), -2175 } -2176 match decoded.pop().expect("non empty") { -2177 Frame::PathsBlocked(decoded) => assert_eq!(decoded, frame0), -2178 x => panic!("incorrect frame {x:?}"), -2179 } -2180 } -2181 -2182 /// Test that encoding and decoding [`AddAddress`] produces the same result -2183 #[test] -2184 fn test_add_address_roundrip() { -2185 let add_address = AddAddress { -2186 seq_no: VarInt(42), -2187 ip: std::net::Ipv4Addr::LOCALHOST.into(), -2188 port: 4242, -2189 }; -2190 let mut buf = Vec::with_capacity(add_address.size()); -2191 add_address.encode(&mut buf); -2192 -2193 assert_eq!( -2194 add_address.size(), -2195 buf.len(), -2196 "expected written bytes and actual size differ" -2197 ); -2198 -2199 let mut decoded = frames(buf); -2200 assert_eq!(decoded.len(), 1); -2201 match decoded.pop().expect("non empty") { -2202 Frame::AddAddress(decoded) => assert_eq!(decoded, add_address), -2203 x => panic!("incorrect frame {x:?}"), -2204 } -2205 } -2206 -2207 /// Test that encoding and decoding [`AddAddress`] produces the same result -2208 #[test] -2209 fn test_reach_out_roundrip() { -2210 let reach_out = ReachOut { -2211 round: VarInt(42), -2212 ip: std::net::Ipv6Addr::LOCALHOST.into(), -2213 port: 4242, -2214 }; -2215 let mut buf = Vec::with_capacity(reach_out.size()); -2216 reach_out.encode(&mut buf); -2217 -2218 assert_eq!( -2219 reach_out.size(), -2220 buf.len(), -2221 "expected written bytes and actual size differ" -2222 ); -2223 -2224 let mut decoded = frames(buf); -2225 assert_eq!(decoded.len(), 1); -2226 match decoded.pop().expect("non empty") { -2227 Frame::ReachOut(decoded) => assert_eq!(decoded, reach_out), -2228 x => panic!("incorrect frame {x:?}"), -2229 } -2230 } +1961impl Encodable for RemoveAddress { +1962 fn encode<W: BufMut>(&self, buf: &mut W) { +1963 buf.write(Self::TYPE); +1964 buf.write(self.seq_no); +1965 } +1966} +1967 +1968#[cfg(test)] +1969mod test { +1970 use super::*; +1971 use crate::coding::Encodable; +1972 use assert_matches::assert_matches; +1973 +1974 #[test] +1975 fn frame_type() { +1976 assert_eq!( +1977 FrameType::try_from(FrameType::Padding.to_u64()), +1978 Ok(FrameType::Padding), +1979 ); +1980 +1981 assert_eq!( +1982 FrameType::try_from(FrameType::Datagram(DatagramInfo(0x30)).to_u64()), +1983 Ok(FrameType::Datagram(DatagramInfo(0x30))), +1984 ); +1985 +1986 assert_eq!( +1987 FrameType::try_from(FrameType::Stream(StreamInfo(0x08)).to_u64()), +1988 Ok(FrameType::Stream(StreamInfo(0x08))), +1989 ); +1990 } +1991 +1992 #[track_caller] +1993 fn frames(buf: Vec<u8>) -> Vec<Frame> { +1994 Iter::new(Bytes::from(buf)) +1995 .unwrap() +1996 .collect::<Result<Vec<_>, _>>() +1997 .unwrap() +1998 } +1999 +2000 #[test] +2001 fn ack_coding() { +2002 const PACKETS: &[u64] = &[1, 2, 3, 5, 10, 11, 14]; +2003 let mut ranges = ArrayRangeSet::new(); +2004 for &packet in PACKETS { +2005 ranges.insert(packet..packet + 1); +2006 } +2007 let mut buf = Vec::new(); +2008 const ECN: EcnCounts = EcnCounts { +2009 ect0: 42, +2010 ect1: 24, +2011 ce: 12, +2012 }; +2013 Ack::encoder(42, &ranges, Some(&ECN)).encode(&mut buf); +2014 let frames = frames(buf); +2015 assert_eq!(frames.len(), 1); +2016 match frames[0] { +2017 Frame::Ack(ref ack) => { +2018 let mut packets = ack.iter().flatten().collect::<Vec<_>>(); +2019 packets.sort_unstable(); +2020 assert_eq!(&packets[..], PACKETS); +2021 assert_eq!(ack.ecn, Some(ECN)); +2022 } +2023 ref x => panic!("incorrect frame {x:?}"), +2024 } +2025 } +2026 +2027 #[test] +2028 #[allow(clippy::range_plus_one)] +2029 fn path_ack_coding() { +2030 const PACKETS: &[u64] = &[1, 2, 3, 5, 10, 11, 14]; +2031 let mut ranges = ArrayRangeSet::new(); +2032 for &packet in PACKETS { +2033 ranges.insert(packet..packet + 1); +2034 } +2035 let mut buf = Vec::new(); +2036 const ECN: EcnCounts = EcnCounts { +2037 ect0: 42, +2038 ect1: 24, +2039 ce: 12, +2040 }; +2041 const PATH_ID: PathId = PathId::MAX; +2042 PathAck::encoder(PATH_ID, 42, &ranges, Some(&ECN)).encode(&mut buf); +2043 let frames = frames(buf); +2044 assert_eq!(frames.len(), 1); +2045 match frames[0] { +2046 Frame::PathAck(ref ack) => { +2047 assert_eq!(ack.path_id, PATH_ID); +2048 let mut packets = ack.into_iter().flatten().collect::<Vec<_>>(); +2049 packets.sort_unstable(); +2050 assert_eq!(&packets[..], PACKETS); +2051 assert_eq!(ack.ecn, Some(ECN)); +2052 } +2053 ref x => panic!("incorrect frame {x:?}"), +2054 } +2055 } +2056 +2057 #[test] +2058 fn ack_frequency_coding() { +2059 let mut buf = Vec::new(); +2060 let original = AckFrequency { +2061 sequence: VarInt(42), +2062 ack_eliciting_threshold: VarInt(20), +2063 request_max_ack_delay: VarInt(50_000), +2064 reordering_threshold: VarInt(1), +2065 }; +2066 original.encode(&mut buf); +2067 let frames = frames(buf); +2068 assert_eq!(frames.len(), 1); +2069 match &frames[0] { +2070 Frame::AckFrequency(decoded) => assert_eq!(decoded, &original), +2071 x => panic!("incorrect frame {x:?}"), +2072 } +2073 } +2074 +2075 #[test] +2076 fn immediate_ack_coding() { +2077 let mut buf = Vec::new(); +2078 FrameType::ImmediateAck.encode(&mut buf); +2079 let frames = frames(buf); +2080 assert_eq!(frames.len(), 1); +2081 assert_matches!(&frames[0], Frame::ImmediateAck); +2082 } +2083 +2084 /// Test that encoding and decoding [`ObservedAddr`] produces the same result. +2085 #[test] +2086 fn test_observed_addr_roundrip() { +2087 let observed_addr = ObservedAddr { +2088 seq_no: VarInt(42), +2089 ip: std::net::Ipv4Addr::LOCALHOST.into(), +2090 port: 4242, +2091 }; +2092 let mut buf = Vec::with_capacity(observed_addr.size()); +2093 observed_addr.encode(&mut buf); +2094 +2095 assert_eq!( +2096 observed_addr.size(), +2097 buf.len(), +2098 "expected written bytes and actual size differ" +2099 ); +2100 +2101 let mut decoded = frames(buf); +2102 assert_eq!(decoded.len(), 1); +2103 match decoded.pop().expect("non empty") { +2104 Frame::ObservedAddr(decoded) => assert_eq!(decoded, observed_addr), +2105 x => panic!("incorrect frame {x:?}"), +2106 } +2107 } +2108 +2109 #[test] +2110 fn test_path_abandon_roundtrip() { +2111 let abandon = PathAbandon { +2112 path_id: PathId(42), +2113 error_code: TransportErrorCode::NO_ERROR, +2114 }; +2115 let mut buf = Vec::new(); +2116 abandon.encode(&mut buf); +2117 +2118 let mut decoded = frames(buf); +2119 assert_eq!(decoded.len(), 1); +2120 match decoded.pop().expect("non empty") { +2121 Frame::PathAbandon(decoded) => assert_eq!(decoded, abandon), +2122 x => panic!("incorrect frame {x:?}"), +2123 } +2124 } +2125 +2126 #[test] +2127 fn test_path_status_available_roundtrip() { +2128 let path_status_available = PathStatusAvailable { +2129 path_id: PathId(42), +2130 status_seq_no: VarInt(73), +2131 }; +2132 let mut buf = Vec::new(); +2133 path_status_available.encode(&mut buf); +2134 +2135 let mut decoded = frames(buf); +2136 assert_eq!(decoded.len(), 1); +2137 match decoded.pop().expect("non empty") { +2138 Frame::PathStatusAvailable(decoded) => assert_eq!(decoded, path_status_available), +2139 x => panic!("incorrect frame {x:?}"), +2140 } +2141 } +2142 +2143 #[test] +2144 fn test_path_status_backup_roundtrip() { +2145 let path_status_backup = PathStatusBackup { +2146 path_id: PathId(42), +2147 status_seq_no: VarInt(73), +2148 }; +2149 let mut buf = Vec::new(); +2150 path_status_backup.encode(&mut buf); +2151 +2152 let mut decoded = frames(buf); +2153 assert_eq!(decoded.len(), 1); +2154 match decoded.pop().expect("non empty") { +2155 Frame::PathStatusBackup(decoded) => assert_eq!(decoded, path_status_backup), +2156 x => panic!("incorrect frame {x:?}"), +2157 } +2158 } +2159 +2160 #[test] +2161 fn test_path_new_connection_id_roundtrip() { +2162 let cid = NewConnectionId { +2163 path_id: Some(PathId(22)), +2164 sequence: 31, +2165 retire_prior_to: 13, +2166 id: ConnectionId::new(&[0xAB; 8]), +2167 reset_token: ResetToken::from([0xCD; crate::RESET_TOKEN_SIZE]), +2168 }; +2169 let mut buf = Vec::new(); +2170 cid.encode(&mut buf); +2171 +2172 let mut decoded = frames(buf); +2173 assert_eq!(decoded.len(), 1); +2174 match decoded.pop().expect("non empty") { +2175 Frame::NewConnectionId(decoded) => assert_eq!(decoded, cid), +2176 x => panic!("incorrect frame {x:?}"), +2177 } +2178 } +2179 +2180 #[test] +2181 fn test_path_retire_connection_id_roundtrip() { +2182 let retire_cid = RetireConnectionId { +2183 path_id: Some(PathId(22)), +2184 sequence: 31, +2185 }; +2186 let mut buf = Vec::new(); +2187 retire_cid.encode(&mut buf); +2188 +2189 let mut decoded = frames(buf); +2190 assert_eq!(decoded.len(), 1); +2191 match decoded.pop().expect("non empty") { +2192 Frame::RetireConnectionId(decoded) => assert_eq!(decoded, retire_cid), +2193 x => panic!("incorrect frame {x:?}"), +2194 } +2195 } +2196 +2197 #[test] +2198 fn test_paths_blocked_path_cids_blocked_roundtrip() { +2199 let mut buf = Vec::new(); +2200 +2201 let frame0 = PathsBlocked(PathId(22)); +2202 frame0.encode(&mut buf); +2203 let frame1 = PathCidsBlocked { +2204 path_id: PathId(23), +2205 next_seq: VarInt(32), +2206 }; +2207 frame1.encode(&mut buf); +2208 +2209 let mut decoded = frames(buf); +2210 assert_eq!(decoded.len(), 2); +2211 match decoded.pop().expect("non empty") { +2212 Frame::PathCidsBlocked(decoded) => assert_eq!(decoded, frame1), +2213 x => panic!("incorrect frame {x:?}"), +2214 } +2215 match decoded.pop().expect("non empty") { +2216 Frame::PathsBlocked(decoded) => assert_eq!(decoded, frame0), +2217 x => panic!("incorrect frame {x:?}"), +2218 } +2219 } +2220 +2221 /// Test that encoding and decoding [`AddAddress`] produces the same result +2222 #[test] +2223 fn test_add_address_roundrip() { +2224 let add_address = AddAddress { +2225 seq_no: VarInt(42), +2226 ip: std::net::Ipv4Addr::LOCALHOST.into(), +2227 port: 4242, +2228 }; +2229 let mut buf = Vec::with_capacity(add_address.size()); +2230 add_address.encode(&mut buf); 2231 -2232 /// Test that encoding and decoding [`RemoveAddress`] produces the same result -2233 #[test] -2234 fn test_remove_address_roundrip() { -2235 let remove_addr = RemoveAddress::new(VarInt(10)); -2236 let mut buf = Vec::with_capacity(remove_addr.size()); -2237 remove_addr.encode(&mut buf); -2238 -2239 assert_eq!( -2240 remove_addr.size(), -2241 buf.len(), -2242 "expected written bytes and actual size differ" -2243 ); -2244 -2245 let mut decoded = frames(buf); -2246 assert_eq!(decoded.len(), 1); -2247 match decoded.pop().expect("non empty") { -2248 Frame::RemoveAddress(decoded) => assert_eq!(decoded, remove_addr), -2249 x => panic!("incorrect frame {x:?}"), -2250 } -2251 } -2252}
      \ No newline at end of file +2232 assert_eq!( +2233 add_address.size(), +2234 buf.len(), +2235 "expected written bytes and actual size differ" +2236 ); +2237 +2238 let mut decoded = frames(buf); +2239 assert_eq!(decoded.len(), 1); +2240 match decoded.pop().expect("non empty") { +2241 Frame::AddAddress(decoded) => assert_eq!(decoded, add_address), +2242 x => panic!("incorrect frame {x:?}"), +2243 } +2244 } +2245 +2246 /// Test that encoding and decoding [`AddAddress`] produces the same result +2247 #[test] +2248 fn test_reach_out_roundrip() { +2249 let reach_out = ReachOut { +2250 round: VarInt(42), +2251 ip: std::net::Ipv6Addr::LOCALHOST.into(), +2252 port: 4242, +2253 }; +2254 let mut buf = Vec::with_capacity(reach_out.size()); +2255 reach_out.encode(&mut buf); +2256 +2257 assert_eq!( +2258 reach_out.size(), +2259 buf.len(), +2260 "expected written bytes and actual size differ" +2261 ); +2262 +2263 let mut decoded = frames(buf); +2264 assert_eq!(decoded.len(), 1); +2265 match decoded.pop().expect("non empty") { +2266 Frame::ReachOut(decoded) => assert_eq!(decoded, reach_out), +2267 x => panic!("incorrect frame {x:?}"), +2268 } +2269 } +2270 +2271 /// Test that encoding and decoding [`RemoveAddress`] produces the same result +2272 #[test] +2273 fn test_remove_address_roundrip() { +2274 let remove_addr = RemoveAddress::new(VarInt(10)); +2275 let mut buf = Vec::with_capacity(remove_addr.size()); +2276 remove_addr.encode(&mut buf); +2277 +2278 assert_eq!( +2279 remove_addr.size(), +2280 buf.len(), +2281 "expected written bytes and actual size differ" +2282 ); +2283 +2284 let mut decoded = frames(buf); +2285 assert_eq!(decoded.len(), 1); +2286 match decoded.pop().expect("non empty") { +2287 Frame::RemoveAddress(decoded) => assert_eq!(decoded, remove_addr), +2288 x => panic!("incorrect frame {x:?}"), +2289 } +2290 } +2291}
      \ No newline at end of file