reference · generated
Every public name
Read out of each package's interface and the comments beside it, so the page cannot drift from the code. 598 public items across 6 packages.
frame
Frames and acknowledgements: the payload of a packet.
moonbitstack/moonquic/frame · 22 public items
Types
pub(all) enum Frame {
A decoded QUIC frame. Padding collapses a run of zero bytes to its length; Stream carries application data on a stream, with a byte offset and a fin flag marking the end of the stream (RFC 9000 §19.8).
PaddingInt32PingCryptooffset~ : UInt64, data~ : BytesStreamid~ : UInt64, offset~ : UInt64, fin~ : Bool, data~ : BytesDatagramdata~ : BytesAcklargest~ : UInt64, delay~ : UInt64, first_range~ : UInt64, ranges~ : Array[(UInt64, UInt64)]AckEcnlargest~ : UInt64, delay~ : UInt64, first_range~ : UInt64, ranges~ : Array[(UInt64, UInt64)], ect0~ : UInt64, ect1~ : UInt64, ce~ : UInt64ResetStreamid~ : UInt64, error_code~ : UInt64, final_size~ : UInt64StopSendingid~ : UInt64, error_code~ : UInt64NewTokentoken~ : BytesMaxDataUInt64MaxStreamDataid~ : UInt64, max~ : UInt64MaxStreamsbidi~ : Bool, max~ : UInt64DataBlockedUInt64StreamDataBlockedid~ : UInt64, max~ : UInt64StreamsBlockedbidi~ : Bool, max~ : UInt64NewConnectionIdseq~ : UInt64, retire_prior_to~ : UInt64, conn_id~ : Bytes, reset_token~ : BytesRetireConnectionIdUInt64PathChallengeBytesPathResponseBytesHandshakeDoneConnectionCloseerror_code~ : UInt64, frame_type~ : UInt64?, reason~ : BytesPathAckpath_id~ : UInt64, largest~ : UInt64, delay~ : UInt64, first_range~ : UInt64, ranges~ : Array[(UInt64, UInt64)]PathAckEcnpath_id~ : UInt64, largest~ : UInt64, delay~ : UInt64, first_range~ : UInt64, ranges~ : Array[(UInt64, UInt64)], ect0~ : UInt64, ect1~ : UInt64, ce~ : UInt64PathAbandonpath_id~ : UInt64, error_code~ : UInt64PathStatuspath_id~ : UInt64, seq~ : UInt64, available~ : BoolPathNewConnectionIdpath_id~ : UInt64, seq~ : UInt64, retire_prior_to~ : UInt64, conn_id~ : Bytes, reset_token~ : BytesPathRetireConnectionIdpath_id~ : UInt64, seq~ : UInt64MaxPathIdmax~ : UInt64PathsBlockedmax~ : UInt64PathCidsBlockedpath_id~ : UInt64, next~ : UInt64
pub(all) suberror Refused {
A malformed ACK frame: its fields do not describe a packet-number set.
MalformedString
pub struct Seen {
The packet numbers seen, held as ascending, non-overlapping, non-adjacent inclusive runs [lo, hi].
Functions
pub fn decode(BytesView) -> (Frame, Int32) raise Refused
Read one frame at the start of b, returning it and the bytes it occupied, or raise Refused when it is truncated or of a type this codec does not know. A PADDING frame absorbs the whole run of leading zero bytes. This is the strict face; a caller that would rather branch on the outcome can keep the Option form, but the connection reads payloads through this so a malformed frame is one error path rather than two.
pub fn elicits_ack(Frame) -> Bool
Whether a single frame is ack-eliciting (RFC 9000 §13.2.1): every frame except PADDING, ACK, ACK_ECN, and CONNECTION_CLOSE obliges the peer to acknowledge the packet.
pub fn encode(Frame) -> Bytes
Encode a frame to its wire bytes.
pub fn Frame::acked(Self) -> Array[(UInt64, UInt64)] raise Refused
The packet numbers an ACK or ACK_ECN frame acknowledges, as ascending inclusive ranges; empty for every other frame.
pub fn Frame::equal(Self, Self) -> Boolfrom a trait
pub fn Frame::not_equal(Self, Self) -> Boolfrom a trait
pub fn Frame::to_repr(Self) -> @debug.Reprfrom a trait
pub fn Refused::equal(Self, Self) -> Boolfrom a trait
pub fn Refused::not_equal(Self, Self) -> Boolfrom a trait
pub fn Refused::output(Self, &Logger) -> Unitfrom a trait
pub fn Refused::to_string(Self) -> Stringfrom a trait
pub fn Seen::add(Self, UInt64) -> Unit
Record that packet number pn arrived. Out-of-order and duplicate numbers are absorbed: the runs stay ascending and disjoint however they come in.
pub fn Seen::contains(Self, UInt64) -> Bool
Whether packet number pn has been received.
pub fn Seen::fields(Self) -> (UInt64, UInt64, Array[(UInt64, UInt64)])?
The ACK frame fields for the current set: the Largest Acknowledged, the First ACK Range (how many contiguous packets below the largest are acked), and the descending (Gap, ACK Range Length) list. None when nothing has been received.
pub fn Seen::is_empty(Self) -> Bool
Whether nothing has been received.
pub fn Seen::largest(Self) -> UInt64?
The largest packet number received, or None when empty.
pub fn Seen::new() -> Self
An empty set: nothing received yet.
pub fn Seen::ranges(Self) -> Array[(UInt64, UInt64)]
The packet numbers as ascending inclusive ranges.
pub fn Seen::read(UInt64, UInt64, Array[(UInt64, UInt64)]) -> Self raise Refused
The set an ACK frame's fields describe, the inverse of fields.
packet
Headers, packet numbers and the spaces they live in.
moonbitstack/moonquic/packet · 56 public items
Types
pub(all) enum Kind {
The four long-header packet types (RFC 9000 §17.2).
InitialZeroRttHandshakeRetry
pub(all) struct Long {
A long packet header's invariant fields: its type, the type-specific low four bits of the first byte (the packet-number length for Initial/Handshake/0-RTT, unused by Retry), the 32-bit version, and the destination and source connection IDs.
packet_typeKindtype_specificInt32versionUInt32dcidBytesscidBytes
pub(all) suberror Refused {
A truncated or unparsable frame in a packet payload.
MalformedString
pub(all) struct Short {
A short header's fields: the latency spin bit, the key-phase bit, the packet-number length (1–4 bytes, from the low two bits of the first byte plus one), and the destination connection ID.
spinBoolkey_phaseBoolpn_lengthInt32dcidBytes
pub struct Space {
One packet-number space's send/receive numbering and acknowledgement state.
pub(all) struct Tail {
What follows a long header's invariant part in an Initial, 0-RTT or Handshake packet: the Initial token (empty for the two types that carry none), the Length field covering the packet number and the payload, and where in the packet the packet number starts.
tokenByteslengthUInt64atInt32
Values
pub let version1 : UInt32
QUIC version 1 (RFC 9000 §15).
pub let version2 : UInt32
QUIC version 2 (RFC 9369 §3): the version number is the first four bytes of the SHA-256 of the string "QUICv2 version number", so no decimal 2 appears on the wire.
Functions
pub fn encode_long(Long) -> Bytes
Encode a long header: first byte (1 header-form, 1 fixed bit, 2-bit type, 4 type-specific bits), the version big-endian, then each connection ID prefixed by its one-byte length.
pub fn encode_short(Short) -> Bytes
Encode a short header: first byte (0 header-form, 1 fixed bit, spin, two reserved zero bits, key phase, and the 2-bit packet-number length minus one), then the destination connection ID with no length prefix. The (protected) packet number follows, encoded separately.
pub fn Kind::code(Self, UInt32) -> Int32
The first byte's 2-bit type code for a packet type under version (RFC 9000 §17.2, RFC 9369 §3.2). Version 1 numbers the four types Initial 0, 0-RTT 1, Handshake 2, Retry 3; version 2 rotates them by one, so a middlebox that learned one version's numbers rejects the other's rather than guessing. A version this library does not know is written with version 1's codes, which is what a version-independent header — a Version Negotiation packet — leaves unread.
pub fn Kind::equal(Self, Self) -> Boolfrom a trait
pub fn Kind::not_equal(Self, Self) -> Boolfrom a trait
pub fn Kind::of(UInt32, Int32) -> Self
The packet type a 2-bit code names under version, the inverse of Kind::code.
pub fn Kind::to_repr(Self) -> @debug.Reprfrom a trait
pub fn Long::equal(Self, Self) -> Boolfrom a trait
pub fn Long::header(Self, BytesView, payload~ : Int32, token? : Bytes) -> Bytes
The header a protected packet is sealed under: the invariant header, the Initial token, the Length covering the packet number and payload bytes, then number. number is the truncated packet number already encoded, so the first byte's low bits follow from its length and the truncation is decided once, where number is built. payload counts the sealed payload, AEAD tag included, because that is what a receiver subtracts from Length to find where the payload ends. A token on a type that carries none is written anyway: only Initial has the field, so passing one elsewhere is a caller's error rather than something to paper over.
pub fn Long::not_equal(Self, Self) -> Boolfrom a trait
pub fn Long::to_repr(Self) -> @debug.Reprfrom a trait
pub fn number(Int64, Int64?, size? : Int32) -> Bytes
Encode full_pn as its truncated big-endian packet number, using the shortest length that is unambiguous given largest_acked (RFC 9000 A.2). size writes that many bytes instead. A sender that has already decided how long its packet numbers are — a handshake that fixes four, a test with a vector to match — says so rather than having the length inferred back.
pub fn number_size(Int64, Int64?) -> Int32
The number of bytes (1–4) needed to encode full_pn given the largest packet number the peer has acknowledged (RFC 9000 §17.1 / A.2): enough bytes to cover twice the number of unacknowledged packets, so wraparound is unambiguous. With no acknowledgement yet, the count is full_pn + 1.
pub fn pad(Bytes, Int32) -> Bytes
Pad payload out to at least min_size bytes with PADDING frames (zero octets); a payload already that long is returned unchanged (RFC 9000 §14.1 — an Initial packet's payload is padded so the datagram reaches the 1200-byte minimum).
pub fn payload(Array[@frame.Frame]) -> Bytes
Encode a list of frames into a packet payload — their wire encodings concatenated.
pub fn payload_elicits_ack(Array[@frame.Frame]) -> Bool
Whether a payload's frames make the packet ack-eliciting — true if any frame is.
pub fn read_header(BytesView) -> (Long, Tail)?
A long header and its tail in one read, for the common case of taking a packet apart from the front.
pub fn read_long(BytesView) -> (Long, Int32)?
Parse a long header at the start of b, returning it and the number of bytes it occupied, or None if the first byte is not a long header or b is truncated before the header ends.
pub fn read_number(Int64, Int64, Int32) -> Int64
Recover the full packet number from a truncated_pn of pn_nbits bits, given the largest full packet number already received (RFC 9000 A.3): pick the value congruent to truncated_pn that is closest to the next expected number, resolving wraparound with the half-window rule.
pub fn read_payload(Bytes) -> Array[@frame.Frame] raise Refused
Parse a decrypted packet payload into its frames, consuming the whole payload. A frame that does not parse, or that consumes no bytes, is a payload error.
pub fn read_retry(BytesView) -> (Long, Bytes, Bytes)?
A Retry packet's header, token and integrity tag. Everything after the invariant header is the token save the trailing 16 bytes, so a packet shorter than that, or one that is not a Retry, reads as None.
pub fn read_short(BytesView, Int32) -> (Short, Int32)?
Parse a short header at the start of b, given the length of the destination connection ID this endpoint issued. Returns the header and the bytes consumed (first byte plus the connection ID), or None if the first byte is a long header or b is shorter than that.
pub fn read_tail(Long, BytesView, Int32) -> Tail?
The tail following the invariant header that ended at bytes into b. None when the packet is truncated inside the token or the length field, or when h is a Retry — a Retry has no Length and no packet number, so read_retry reads it.
pub fn read_versions(BytesView) -> (Bytes, Bytes, Array[UInt32])?
The connection IDs and offered versions a Version Negotiation packet carries. None unless the version field is zero, which is what marks the packet, and unless the version list is a whole number of four-byte versions.
pub fn Refused::equal(Self, Self) -> Boolfrom a trait
pub fn Refused::not_equal(Self, Self) -> Boolfrom a trait
pub fn Refused::output(Self, &Logger) -> Unitfrom a trait
pub fn Refused::to_string(Self) -> Stringfrom a trait
pub fn retry(Long, token~ : Bytes, tag~ : Bytes) -> Bytes
A Retry packet (RFC 9000 §17.2.5): the invariant header, the retry token, and the 16-byte integrity tag that binds the packet to the original connection ID.
pub fn Short::equal(Self, Self) -> Boolfrom a trait
pub fn Short::header(Self, BytesView) -> Bytes
The header a protected 1-RTT packet is sealed under (RFC 9000 §17.3): the first byte, the destination connection ID, and the packet number. As on the long side the first byte's low bits come from number, so pn_length on the struct is what a reader found rather than something a writer must agree with. A short header has no length field: the payload runs to the end of the datagram.
pub fn Short::not_equal(Self, Self) -> Boolfrom a trait
pub fn Short::to_repr(Self) -> @debug.Reprfrom a trait
pub fn Space::ack_pending(Self) -> Bool
Whether an ACK is owed — an ack-eliciting packet has arrived since the last ACK was built.
pub fn Space::advance_past(Self, Int64) -> Unit
Skip the send counter past pn, so a packet another sender numbered in this space — the recovery loop's, which keeps its own counter — is not handed out again here. A pn this space is already past leaves it alone.
pub fn Space::build_ack(Self, UInt64) -> @frame.Frame?
Build the ACK frame acknowledging everything received so far with the given ack_delay, and clear the pending flag. None when nothing has been received.
pub fn Space::issued(Self) -> Int64
One past the highest packet number this space has handed out: the first number the peer cannot have seen, so an acknowledgement of it or anything above names a packet that was never sent (RFC 9000 §13.1).
pub fn Space::largest_acked(Self) -> Int64?
The largest packet number the peer has acknowledged, or None.
pub fn Space::largest_received(Self) -> Int64
The largest packet number received in this space, or -1 before the first: what the next number on the wire is expanded against (RFC 9000 A.3).
pub fn Space::new() -> Self
A fresh space: next packet number 0, nothing received or acknowledged.
pub fn Space::next_packet_number(Self) -> Int64
Allocate the next packet number to send, advancing the counter.
pub fn Space::on_ack_received(Self, Int64) -> Unit
Record that the peer acknowledged up to largest, advancing the high-water mark (an older ACK never lowers it).
pub fn Space::on_packet_received(Self, Int64, Bool) -> Unit
Record that packet number pn arrived. ack_eliciting marks a packet that must be acknowledged (RFC 9000 §13.2.1); a pure-ACK packet is recorded but does not itself oblige a new ACK.
pub fn Space::seen(Self, Int64) -> Bool
Whether packet pn has been processed already, which a receiver must not do twice (RFC 9000 §12.3).
pub fn Tail::equal(Self, Self) -> Boolfrom a trait
pub fn Tail::not_equal(Self, Self) -> Boolfrom a trait
pub fn Tail::to_repr(Self) -> @debug.Reprfrom a trait
pub fn versions(dcid~ : Bytes, scid~ : Bytes, ArrayView[UInt32], first? : Int32) -> Bytes
A Version Negotiation packet (RFC 9000 §17.2.1): version zero and the versions the server will speak, with the connection IDs swapped from the packet that provoked it. first is the whole first byte. The RFC leaves every bit but the header form arbitrary and asks a server to vary them, so it is the caller's to choose; the default sets the form bit alone.
crypto
Packet protection, header protection and the keys that drive them.
moonbitstack/moonquic/crypto · 41 public items
Types
pub(all) struct Keys {
One direction's packet-protection keys (RFC 9001 §5.1): the AEAD key, the IV each packet's nonce is built from, and the header-protection key.
keyBytesivByteshpBytessuiteSuiteAEAD_AES_128_GCM with SHA-256 (RFC 9001 §5.2).
pub(all) struct Suite {
The cipher a packet is protected with (RFC 9001 §5.1, §5.3, §5.4.3): how many bytes of key, IV, header-protection key and authentication tag a traffic secret expands to, which hash the expansion runs under, the AEAD that seals a payload, and the cipher that turns a ciphertext sample into a header-protection mask. The preset is AEAD_AES_128_GCM with SHA-256, which §5.2 fixes for Initial packets and every space uses until TLS negotiates otherwise. aes256 and chacha20 are the other two; a suite beyond these is a @spec.Aead implementation away and needs no change here.
digest@keys.DigestkeyInt32ivInt32hpInt32tagInt32aead(Bytes) -> &@spec.Aeadmask(Bytes, BytesView) -> Bytes
pub(all) struct Version {
The constants a QUIC version fixes (RFC 9001 §5.2, §5.8): the Initial salt, the four HKDF labels, and the key and nonce a Retry's integrity tag is computed under. The preset is version 1. RFC 9369 changes every one of them for version 2 — the salt and the Retry key and nonce by its §3.3, and all four labels by prefixing them with quicv2 — which is why a version is a value here and not a constant in the code.
saltByteskeyBytesivByteshpByteskuBytesretryBytesnonceBytes
Values
pub let aes256 : Suite
AEAD_AES_256_GCM with SHA-384 (RFC 9001 §5.3).
pub let chacha20 : Suite
AEAD_CHACHA20_POLY1305 with SHA-256 (RFC 9001 §5.3, §5.4.4).
pub let sample : Int32
How many bytes of ciphertext a header-protection mask is sampled from (RFC 9001 §5.4.2). Every AEAD QUIC defines samples sixteen, so this is the protocol's number rather than a suite's.
pub let suite : Suite
AEAD_AES_128_GCM with SHA-256 (RFC 9001 §5.2).
pub let version : Version
QUIC version 1 (RFC 9001 §5.2 and §5.8).
pub let version2 : Version
QUIC version 2 (RFC 9369 §3.3, Appendix A.5): a different Initial salt, four labels with v2 in front of the word they carry, and a Retry tag under its own key and nonce.
Functions
pub fn aes_gcm(Bytes) -> &@spec.Aead
AES-GCM over a key of the length the caller passes: AES-128 for sixteen bytes, AES-256 for thirty-two. A key of another length aborts rather than raising. Key lengths come from a suite, which is a constant of the program, so a wrong one is a mistake in the code and not something a peer can provoke.
pub fn aes_mask(Bytes, BytesView) -> Bytes
The AES header-protection mask: the first five bytes of one ECB block over the sample (RFC 9001 §5.4.3).
pub fn application(BytesView, BytesView, client~ : Bool, suite? : Suite, version? : Version) -> Keys
This endpoint's Application (1-RTT) keys, from the master secret over the ClientHello..server Finished transcript (RFC 9001 §5.2).
pub fn chacha_mask(Bytes, BytesView) -> Bytes
The ChaCha20 header-protection mask (RFC 9001 §5.4.4): the sample's first four bytes are the block counter, little-endian, the other twelve the nonce, and the mask the first five bytes of that keystream block.
pub fn chacha_poly(Bytes) -> &@spec.Aead
ChaCha20-Poly1305 over a 32-byte key.
pub fn handshake(BytesView, BytesView, client~ : Bool, suite? : Suite, version? : Version) -> Keys
This endpoint's Handshake-space keys, from the handshake traffic secret over the ClientHello..ServerHello transcript (RFC 9001 §5.2).
pub fn initial(BytesView, suite? : Suite, version? : Version) -> (Keys, Keys)
The client's and server's Initial keys, in that order (RFC 9001 §5.2). These are the one part of the handshake that needs no TLS exchange: both sides can compute them from the connection ID alone, which is also why Initial packets are protected against off-path observers rather than against anybody at all.
pub fn Keys::equal(Self, Self) -> Boolfrom a trait
pub fn Keys::mask(Self, BytesView) -> Bytes
The header-protection mask for a ciphertext sample (RFC 9001 §5.4.2).
pub fn Keys::nonce(Self, Int64) -> Bytes
The AEAD nonce for a packet number: the number, left-padded to the IV's length, XORed with the IV (RFC 9001 §5.3). The number occupies the low eight bytes and any higher IV bytes pass through.
pub fn Keys::nonce_at(Self, UInt64, Int64) -> Bytes
The AEAD nonce for a packet on path path, whose packet numbers start over at zero (draft-ietf-quic-multipath §2.4). The draft composes a 96-bit Path-and-Packet-Number from the 32 bits of the path id in network byte order, two zero bits, and the 62-bit packet number, and XORs it with the IV: two paths may then use the same number without using the same nonce. Path 0 gives the number RFC 9001 §5.3 describes, so a connection with one path computes exactly what it did before.
pub fn Keys::not_equal(Self, Self) -> Boolfrom a trait
pub fn Keys::of(BytesView, suite? : Suite, version? : Version) -> Self
The keys a traffic secret expands to (RFC 9001 §5.1), under the three labels the version fixes and at the lengths the suite fixes.
pub fn Keys::open(Self, BytesView, largest~ : Int64, at? : Int32, path? : UInt64) -> (Bytes, Int64)?
A received packet opened: header protection removed, the packet number recovered against largest, and the payload AEAD-opened with the recovered header as associated data (RFC 9001 §5.3–§5.4). largest is the largest packet number already received in this space, or -1 when none has been: the number on the wire is truncated, and RFC 9000 §A.3 recovers the full one from what the receiver has seen. at is where the packet number starts. Leave it out for a long header, whose own Length field says where; a short header needs it, because how long the connection ID is is something only the receiver knows. None when the packet is too short to sample, when a long header does not parse, or when the tag does not match — one answer for every way of being unreadable, because a receiver's response to all of them is to drop the packet.
pub fn Keys::protect(Self, BytesView, at~ : Int32, size~ : Int32) -> Bytes
Apply header protection: XOR the first byte's protected bits and the size packet-number bytes at at with the mask (RFC 9001 §5.4.1). The sample starts at at + 4, the fixed position that assumes the longest packet-number field whatever this packet's is, so a receiver can take the sample before it knows how long the field is.
pub fn Keys::seal(Self, BytesView, BytesView, number~ : Int64, path? : UInt64) -> Bytes
A protected packet: seal payload with header as associated data, then protect the header (RFC 9001 §5.3–§5.4). header ends in the packet number, and its first byte's low two bits say how many bytes that is, so both header forms are handled without being told which is which — build it with @packet.Long::header or @packet.Short::header.
pub fn Keys::to_repr(Self) -> @debug.Reprfrom a trait
pub fn Keys::unprotect(Self, BytesView, at~ : Int32) -> (Bytes, Int32)
Remove header protection: recover the first byte, read the packet-number length from its low two bits, and unmask that many bytes. Returns the unprotected packet and the recovered length (RFC 9001 §5.4.1).
pub fn next(BytesView, suite? : Suite, version? : Version) -> (Bytes, Keys)
Roll to the next key generation: the updated traffic secret and the keys it expands to, which is what an endpoint installs when it flips the Key Phase bit.
pub fn retry_ok(BytesView, BytesView, suite? : Suite, version? : Version) -> Bool
Whether a Retry packet's trailing integrity tag is the right one for odcid. The comparison accumulates the difference rather than stopping at the first byte that differs, so how long it takes says nothing about how much of the tag was right.
pub fn retry_tag(BytesView, BytesView, suite? : Suite, version? : Version) -> Bytes
A Retry packet's integrity tag (RFC 9001 §5.8), over everything up to but not including the tag, bound to the original Destination Connection ID. The associated data is the Retry Pseudo-Packet: the ODCID's length byte, the ODCID, then the Retry packet. The plaintext is empty, so the AEAD's output is the tag alone.
pub fn secret(BytesView, suite? : Suite, version? : Version) -> Bytes
The Initial secret both endpoints share: HKDF-Extract(salt, dcid) over the Destination Connection ID from the client's first packet (RFC 9001 §5.2).
pub fn Suite::new(digest? : @keys.Digest, key? : Int32, iv? : Int32, hp? : Int32, tag? : Int32, aead? : (Bytes) -> &@spec.Aead, mask? : (Bytes, BytesView) -> Bytes) -> Self
A suite by name, each part defaulting to the AES-128-GCM preset.
pub fn token_ok(BytesView, BytesView, suite? : Suite) -> Bool
Whether a token's trailing tag is the one key gives for everything before it. As with the Retry tag, the comparison accumulates, so its duration says nothing about the match.
pub fn token_tag(BytesView, BytesView, suite? : Suite) -> Bytes
A tag binding body to key, for a token an endpoint hands out and takes back (RFC 9000 §8.1.2's address validation token). The construction is the Retry integrity tag's: an AEAD over an empty plaintext with body as associated data, so the answer is the tag alone and a forgery costs a tag forgery.
pub fn update(BytesView, suite? : Suite, version? : Version) -> Bytes
The next generation's 1-RTT traffic secret (RFC 9001 §6.1). Applying it again advances another generation; the Key Phase bit in the short header says which generation protects a packet.
pub fn Version::equal(Self, Self) -> Boolfrom a trait
pub fn Version::new(salt? : Bytes, key? : Bytes, iv? : Bytes, hp? : Bytes, ku? : Bytes, retry? : Bytes, nonce? : Bytes) -> Self
A version's constants by name, each defaulting to version 1's.
pub fn Version::not_equal(Self, Self) -> Boolfrom a trait
pub fn Version::of(UInt32) -> Self?
The constants of the version a long header carries, or None for a version this library does not speak — the answer that decides whether a first flight can be read at all.
pub fn Version::to_repr(Self) -> @debug.Reprfrom a trait
pub fn zero_rtt(BytesView, suite? : Suite, version? : Version) -> Keys
A 0-RTT packet's keys from the client's early traffic secret (RFC 9001 §5.2). The early secret is TLS's to derive; expanding it into key, IV and header-protection key is the same as for any other traffic secret.
recovery
Round-trip time, loss detection, congestion control and pacing.
moonbitstack/moonquic/recovery · 106 public items
Types
pub struct Bbr {
A BBR congestion controller, an implementation of Control.
pub(open) trait Control {
A congestion controller (RFC 9002 §7): how much may be in flight, and what to make of each packet sent, acknowledged or lost. NewReno is the one RFC 9002 specifies, and the reason this is a trait rather than that struct is §7's own opening — an endpoint may use any controller, and Cubic and BBR answer the same questions. Implementing this is all it takes; nothing here changes.
pub struct Cubic {
A CUBIC congestion controller (RFC 9438), an implementation of Control.
pub struct Flight {
What is outstanding in one packet-number space, and the largest number acknowledged so far — -1 before any ACK has arrived.
pub(all) enum Mode {
Where a BBR sender is in its bandwidth-probing cycle.
StartupDrainProbeBwProbeRtt
pub struct NewReno {
NewReno, the controller RFC 9002 §7 specifies.
pub struct Pacer {
A token bucket over bytes, at a rate in bytes per microsecond. A rate of zero means the connection is not paced and everything is allowed.
pub(all) struct Policy {
The constants RFC 9002 leaves as tunables, and the two connection parameters the timers are computed from. Every duration is microseconds and every size is bytes. The presets are the values the RFC itself recommends (§6.1.1, §6.1.2, §6.2.2, §7.2, §7.3, §7.6) together with RFC 9000 §18.2's default max_ack_delay and RFC 9000 §14's minimum datagram size, which is the one every path is required to carry.
packetsInt64timeDoublegranularityInt64initial_rttInt64persistentInt64reductionDoubledatagramInt64ack_delayInt64
pub struct Rtt {
An endpoint's round-trip estimate for one packet-number space (RFC 9002 §5).
pub(all) struct Sent {
A sent, not yet acknowledged ack-eliciting packet (RFC 9002 §A.1): its number, when it went out, and how many bytes it put in flight.
pnInt64atInt64sizeInt64
pub struct State {
A sender's recovery state for one packet-number space: the round-trip estimate, what is outstanding, and the congestion controller, driven by the two events a sender has — a packet went out, an ACK came back.
Values
pub let policy : Policy
RFC 9002's recommended constants.
Functions
pub fn Bbr::bandwidth(Self) -> Double
The maximum delivery rate seen, in bytes per microsecond.
pub fn Bbr::bdp(Self) -> Int64
The bandwidth-delay product in bytes: how much the path can hold in flight at once at the best rate and the smallest round trip seen.
pub fn Bbr::in_flight(Self) -> Int64
pub fn Bbr::min_rtt(Self) -> Int64
The smallest round trip seen, in microseconds.
pub fn Bbr::minimum(Self) -> Int64
The smallest window the controller will set (RFC 9002 §7.2).
pub fn Bbr::mode(Self) -> Mode
Where the controller is in its probing cycle.
pub fn Bbr::new(policy? : Policy) -> Self
A fresh BBR controller at RFC 9002 §7.2's initial window, in startup.
pub fn Bbr::on_ack(Self, Int64) -> Unit
pub fn Bbr::on_ack_at(Self, Int64, now~ : Int64) -> Unit
pub fn Bbr::on_congestion(Self, at~ : Int64, now~ : Int64) -> Unit
pub fn Bbr::on_lost(Self, Int64) -> Unit
pub fn Bbr::on_new_path(Self) -> Unit
pub fn Bbr::on_persistent(Self) -> Unit
pub fn Bbr::on_rtt(Self, sample~ : Int64, now~ : Int64) -> Unit
pub fn Bbr::on_sent(Self, Int64) -> Unit
pub fn Bbr::pacing_rate(Self) -> Double?
pub fn Bbr::target(Self) -> Int64
The window the model asks for: the bandwidth-delay product times the mode's window gain, three datagrams of headroom, floored at the minimum. A loss leaves it unchanged, which is what tells BBR from NewReno. While the round trip is being sampled the window is held at four datagrams whatever the model says, so the queue the last cycle built can drain.
pub fn Bbr::window(Self) -> Int64
pub fn can_send(&Control, Int64) -> Bool
Whether bytes more fit in the window.
pub fn Cubic::in_flight(Self) -> Int64
pub fn Cubic::minimum(Self) -> Int64
The smallest window the controller will reduce to (RFC 9002 §7.2).
pub fn Cubic::new(policy? : Policy) -> Self
A fresh CUBIC controller at RFC 9002 §7.2's initial window: the same start as NewReno, since how a controller begins is not what makes it CUBIC.
pub fn Cubic::on_ack(Self, Int64) -> Unit
pub fn Cubic::on_ack_at(Self, Int64, now~ : Int64) -> Unit
pub fn Cubic::on_congestion(Self, at~ : Int64, now~ : Int64) -> Unit
pub fn Cubic::on_lost(Self, Int64) -> Unit
pub fn Cubic::on_new_path(Self) -> Unit
pub fn Cubic::on_persistent(Self) -> Unit
pub fn Cubic::on_rtt(Self, sample~ : Int64, now~ : Int64) -> Unit
pub fn Cubic::on_sent(Self, Int64) -> Unit
pub fn Cubic::pacing_rate(Self) -> Double?
pub fn Cubic::recovering(Self, Int64) -> Bool
Whether a packet sent at at falls inside the recovery period already under way.
pub fn Cubic::ssthresh(Self) -> Int64
The slow-start threshold in bytes.
pub fn Cubic::target(Self, Int64) -> Int64
The window the cubic and the Reno-friendly estimate ask for at now, in bytes — the larger of the two (RFC 9438 §4.2, §4.3). A test reproduces this arithmetic itself so a change to the curve is visible as a changed window.
pub fn Cubic::window(Self) -> Int64
pub fn Flight::largest_acked(Self) -> Int64
The largest packet number acknowledged, or -1 before any ACK.
pub fn Flight::lost(Self, Int64, packets~ : Int64, time~ : Int64) -> Array[Sent]
Declare lost every outstanding packet that either sits at least packets behind the largest acknowledged (RFC 9002 §6.1.1) or was sent longer than time ago while a later packet has been acknowledged (§6.1.2), and stop tracking them. The records come back whole, sizes included, because the congestion controller has to take those bytes out of flight and only the caller knows which controller that is.
pub fn Flight::new() -> Self
A fresh flight, with nothing outstanding.
pub fn Flight::on_ack(Self, Array[(Int64, Int64)]) -> Int64
Process an ACK's acknowledged ranges: drop every outstanding packet that falls in one, advance the largest acknowledged, and answer with the bytes taken out of flight.
pub fn Flight::on_sent(Self, Int64, at~ : Int64, size~ : Int64) -> Unit
Record that an ack-eliciting packet went out.
pub fn Flight::outstanding(Self) -> Array[Int64]
The packet numbers still outstanding.
pub fn Flight::time_of(Self, Int64) -> Int64?
When the outstanding packet numbered pn was sent, or None if it is not outstanding.
pub fn Mode::equal(Self, Self) -> Boolfrom a trait
pub fn Mode::not_equal(Self, Self) -> Boolfrom a trait
pub fn Mode::to_repr(Self) -> @debug.Reprfrom a trait
pub fn NewReno::in_flight(Self) -> Int64
pub fn NewReno::minimum(Self) -> Int64
The smallest window the controller will reduce to (RFC 9002 §7.2).
pub fn NewReno::new(policy? : Policy) -> Self
A fresh controller (RFC 9002 §7.2): the initial window is min(10·datagram, max(2·datagram, 14720)), the slow-start threshold is unbounded, and nothing is in flight or in recovery.
pub fn NewReno::on_ack(Self, Int64) -> Unit
pub fn NewReno::on_ack_at(Self, Int64, now~ : Int64) -> Unit
pub fn NewReno::on_congestion(Self, at~ : Int64, now~ : Int64) -> Unit
pub fn NewReno::on_lost(Self, Int64) -> Unit
pub fn NewReno::on_new_path(Self) -> Unit
pub fn NewReno::on_persistent(Self) -> Unit
pub fn NewReno::on_rtt(Self, sample~ : Int64, now~ : Int64) -> Unit
pub fn NewReno::on_sent(Self, Int64) -> Unit
pub fn NewReno::pacing_rate(Self) -> Double?
pub fn NewReno::recovering(Self, Int64) -> Bool
Whether a packet sent at at falls inside the recovery period already under way.
pub fn NewReno::ssthresh(Self) -> Int64
The slow-start threshold in bytes.
pub fn NewReno::window(Self) -> Int64
pub fn Pacer::allow(Self, Int64, Int64) -> Bool
Whether bytes may go at now. Unpaced, always.
pub fn Pacer::new(burst_bytes? : Int64) -> Self
A pacer that lets everything through until a rate is set.
pub fn Pacer::next_at(Self, Int64, Int64) -> Int64?
When bytes will have accrued, or None when it already has or nothing is paced. A driver arms a timer on this and comes back for the packet.
pub fn Pacer::rate(Self) -> Double
The rate in bytes per microsecond; zero when unpaced.
pub fn Pacer::set_rate(Self, Double) -> Unit
Set the rate, in bytes per microsecond. Zero turns pacing off. The bucket starts full, so the first burst after a quiet period is not delayed.
pub fn Pacer::spend(Self, Int64, Int64) -> Unit
Take bytes out of the bucket.
pub fn Policy::new(packets? : Int64, time? : Double, granularity? : Int64, initial_rtt? : Int64, persistent? : Int64, reduction? : Double, datagram? : Int64, ack_delay? : Int64) -> Self
A policy by name, each part defaulting to RFC 9002's recommendation. packets is kPacketThreshold, time kTimeThreshold, granularity kGranularity, initial_rtt kInitialRtt, persistent kPersistentCongestionThreshold, reduction kLossReductionFactor. datagram is the sender's maximum datagram size and ack_delay the peer's advertised max_ack_delay, both of which a real connection learns from its transport parameters rather than keeps at the default.
pub fn Rtt::latest(Self) -> Int64
The most recent sample.
pub fn Rtt::min(Self) -> Int64
The smallest sample seen, which is the closest this endpoint has come to measuring the path itself rather than the path plus the peer's delays.
pub fn Rtt::new() -> Self
A fresh estimate, with no sample yet.
pub fn Rtt::pto(Self, policy? : Policy) -> Int64
The Probe Timeout: smoothed + max(4·variation, granularity) + ack_delay (RFC 9002 §6.2.1), or twice the policy's initial RTT before the first sample (§6.2.2).
pub fn Rtt::reset(Self) -> Unit
Back to no sample, for a path nothing is known about.
pub fn Rtt::sample(Self, Int64, ack_delay~ : Int64, policy? : Policy) -> Unit
Fold in a round-trip sample (RFC 9002 §5.3). ack_delay is what the peer said it waited before acknowledging; it is capped at the policy's ack_delay and subtracted only while doing so keeps the sample at or above the minimum seen, so a peer cannot talk the estimate below the path's real latency. The first sample seeds the estimate outright; later ones move the weighted average.
pub fn Rtt::sampled(Self) -> Bool
Whether any sample has arrived. Before the first one the timers fall back to the policy's initial RTT, which is the whole of what an endpoint knows at that point.
pub fn Rtt::smoothed(Self) -> Int64
The smoothed estimate the timers are built on.
pub fn Rtt::threshold(Self, policy? : Policy) -> Int64
The loss time threshold: max(time · max(smoothed, latest), granularity) (RFC 9002 §6.1.2).
pub fn Rtt::variation(Self) -> Int64
The mean deviation of the samples.
pub fn Sent::equal(Self, Self) -> Boolfrom a trait
pub fn Sent::not_equal(Self, Self) -> Boolfrom a trait
pub fn Sent::to_repr(Self) -> @debug.Reprfrom a trait
pub fn State::can_send(Self, Int64) -> Bool
Whether bytes more may go out without exceeding the congestion window.
pub fn State::in_flight(Self) -> Int64
The bytes currently in flight.
pub fn State::new(policy? : Policy, control? : &Control) -> Self
A fresh state. Leave control out for NewReno under the same policy; give one to use another controller.
pub fn State::on_ack(Self, @frame.Frame, Int64, ack_delay~ : Int64) -> Array[Int64] raise @frame.Refused
An ACK arrived (RFC 9002 §5–§7): sample the round trip off the largest newly acknowledged packet, free the acknowledged bytes, then run loss detection over both thresholds. Answers with the packet numbers declared lost — the frames to send again. ack_delay is what the ACK frame said, in microseconds; the frame's own field is in the peer's exponent and decoding it is the connection's job, not this one's. One round of loss is one congestion signal however many packets it covers, and a round spanning more than persistent probe timeouts is persistent congestion (§7.6).
pub fn State::on_new_path(Self) -> Unit
The connection moved to a new path (RFC 9000 §9.4): the round trip and the window start over. What is in flight stays tracked, since those packets can still be acknowledged.
pub fn State::on_pto(Self) -> Unit
The probe timer fired (RFC 9002 §6.2.4): back off for the next arming. Sending the probes is the caller's, because what to put in them is the connection's business.
pub fn State::on_sent(Self, Int64, at~ : Int64, size~ : Int64) -> Unit
An ack-eliciting packet went out: track it for acknowledgement and charge the window.
pub fn State::outstanding(Self) -> Array[Int64]
The packet numbers still outstanding.
pub fn State::pacing_rate(Self) -> Double
The rate to pace at, in bytes per microsecond (RFC 9002 §7.7): what the controller says when it models the path, else the window over one and a quarter round trips, which is what keeps a window from arriving as a burst.
pub fn State::pto(Self) -> Int64
The probe timeout in microseconds, before backoff.
pub fn State::pto_count(Self) -> Int32
How many probe timeouts have fired without an acknowledgement since the last one that did — the backoff exponent.
pub fn State::pto_deadline(Self) -> Int64?
When the probe timer fires: the last ack-eliciting packet's send time plus the timeout backed off by 2^pto_count (RFC 9002 §6.2.1). None when nothing is outstanding, which is the timer disarmed.
pub fn State::rtt(Self) -> Rtt
The round-trip estimate this space has built.
pub fn State::window(Self) -> Int64
The congestion window in bytes.
stream
Streams, both state machines, flow control and the send scheduler.
moonbitstack/moonquic/stream · 112 public items
Types
pub struct Assembler {
A stream's reassembly buffer. consumed is the next offset the reader has not taken; the runs beyond it are sorted, non-overlapping, and each starts at or after it.
pub struct Budget {
A connection's send windows: the connection-wide one and one per stream, each opened at the peer's initial per-stream maximum when the stream is first written to.
pub(all) struct Chunk {
A scheduling decision: send length bytes of stream at offset, ending it when fin.
streamUInt64offsetUInt64lengthUInt64finBool
pub struct Credit {
The send side of one window: how much has gone out against the limit the peer gave.
pub(all) enum Direction {
Whether a stream carries data one way or both.
BidiUni
pub(all) enum Initiator {
Which endpoint opened a stream.
ClientServer
pub(all) struct Out {
What one stream still has to send: how much is queued, where its next frame starts, and whether a FIN is queued and whether it has gone out.
pub struct Quota {
How many streams of one kind the peer may still open (RFC 9000 §4.6), and how many it has. A peer that opens past the limit is a connection error, and without this an endpoint would let one hold open as many as it liked.
pub(all) enum Receiving {
The receiving part's state (§3.2).
RecvSizeKnownDataReceivedDataReadResetReceivedResetRead
pub(all) enum RecvEvent {
What reached the receiving part: a STREAM frame, with fin fixing the final size; all the data up to that size; the application reading it all; a RESET_STREAM; the application being told of that reset.
Receivefin~ : BoolAllReceivedAppReadReceiveResetAppReadReset
pub(all) suberror Refused {
Why a stream operation was refused. Illegal is a transition §3.1 or §3.2 does not allow — a bug on this side. Exceeded is the peer sending past a limit we advertised, or this side being asked to send past one the peer advertised (§4.1, §4.6). Conflict is a retransmission that disagrees with what arrived before, or a final size contradicting one already known (§2.2, §4.5) — which RFC 9000 makes a connection error.
IllegalStringExceededlimit~ : UInt64, got~ : UInt64ConflictString
pub struct Scheduler {
A round-robin scheduler over a connection's sending streams, bounded by the send budget and by how much one frame carries.
pub(all) enum SendEvent {
What the sending part did: wrote a STREAM frame, with fin on the last one; had all its data acknowledged; sent a RESET_STREAM; had that reset acknowledged.
Writefin~ : BoolAllAckedResetStreamResetAcked
pub(all) enum Sending {
The sending part's state (§3.1).
ReadySendDataSentDataRecvdResetSentResetRecvd
pub struct Streams {
pub struct Window {
The receive side of one window: the peer may send up to the limit we advertised, and the limit moves up as the application consumes what arrived.
Values
pub let frame : UInt64
How many bytes of stream data one frame carries at most. A QUIC packet must fit the path, and 1200 is the datagram every path is required to carry (RFC 9000 §14); the rest of that goes to the header and the AEAD tag, so a kilobyte of payload leaves room without needing to know the header's exact shape.
pub let limit : UInt64
How many bytes an assembler will hold ahead of the read cursor before refusing more. A connection's receive window already bounds this, and a megabyte is what quiche advertises per stream by default; the limit is here so an assembler used on its own is bounded too.
pub let ratio : Double
How much of a window must become reclaimable before advertising a new limit is worth a frame. Half a window is what quiche uses; RFC 9000 §4.1 leaves it open, saying only that an endpoint should avoid a frame per byte.
Functions
pub fn Assembler::buffered(Self) -> UInt64
How many bytes are buffered ahead of the cursor.
pub fn Assembler::complete(Self) -> Bool
Whether the whole stream has arrived and been read.
pub fn Assembler::consumed(Self) -> UInt64
The next contiguous offset the reader has taken.
pub fn Assembler::final_size(Self) -> UInt64?
The stream's final size, once a fin has fixed it.
pub fn Assembler::insert(Self, UInt64, Bytes, fin~ : Bool) -> Unit raise Refused
Take a fragment at offset, with fin marking it the last. A fragment wholly behind the cursor is dropped; one that overlaps buffered bytes with different values, or contradicts a known final size, is refused — §2.2 requires a retransmission to carry the same bytes, so disagreement is the peer misbehaving.
pub fn Assembler::limit(Self) -> UInt64
How many bytes this reassembler will hold before refusing more (RFC 9000 §7.5).
pub fn Assembler::new(limit? : UInt64) -> Self
A fresh assembler at the start of a stream.
pub fn Assembler::read(Self) -> Bytes
Take the contiguous run from the cursor, moving it past what comes back. Empty when the next expected offset has not arrived.
pub fn Budget::available(Self, UInt64) -> UInt64
How much may go out on stream id right now: the smaller of the connection's window and the stream's (§4.1).
pub fn Budget::connection(Self) -> UInt64
What may still go out across all streams together.
pub fn Budget::new(UInt64, UInt64) -> Self
A budget at the peer's initial connection-wide and per-stream maxima, which come from its transport parameters (RFC 9000 §18.2).
pub fn Budget::on_max_data(Self, UInt64) -> Unit
Raise the connection-wide limit from a MAX_DATA frame.
pub fn Budget::on_max_stream_data(Self, UInt64, UInt64) -> Unit
Raise stream id's limit from a MAX_STREAM_DATA frame.
pub fn Budget::spend(Self, UInt64, UInt64) -> Unit raise Refused
Account for n bytes on stream id, against both windows. Both are checked before either is charged, so a refusal leaves neither half spent.
pub fn Budget::stream(Self, UInt64) -> Credit
Stream id's window, opened at the initial maximum on first use.
pub fn Chunk::equal(Self, Self) -> Boolfrom a trait
pub fn Chunk::not_equal(Self, Self) -> Boolfrom a trait
pub fn Chunk::to_repr(Self) -> @debug.Reprfrom a trait
pub fn Credit::available(Self) -> UInt64
How much more may go out right now — zero when blocked.
pub fn Credit::blocked(Self) -> Bool
Whether the window is spent, which is the STREAM_DATA_BLOCKED and DATA_BLOCKED condition.
pub fn Credit::grant(Self, UInt64) -> Unit
Adopt a limit from a MAX_DATA or MAX_STREAM_DATA frame. A limit only ever rises, so an old frame arriving late is ignored rather than shrinking the window (§4.1).
pub fn Credit::new(UInt64) -> Self
A send window at the peer's initial maximum.
pub fn Credit::sent(Self) -> UInt64
How much has gone out in total.
pub fn Credit::spend(Self, UInt64) -> Unit raise Refused
Account for n bytes going out. Refused when that would pass the peer's limit, and nothing is charged when it is.
pub fn direction(UInt64) -> Direction
Which way stream id carries data — bit 1.
pub fn Direction::equal(Self, Self) -> Boolfrom a trait
pub fn Direction::not_equal(Self, Self) -> Boolfrom a trait
pub fn Direction::to_repr(Self) -> @debug.Reprfrom a trait
pub fn id_of(Initiator, Direction, UInt64) -> UInt64
The ID of the seq-th stream of that kind, counting from zero.
pub fn initiator(UInt64) -> Initiator
The endpoint that opened stream id — bit 0.
pub fn Initiator::equal(Self, Self) -> Boolfrom a trait
pub fn Initiator::not_equal(Self, Self) -> Boolfrom a trait
pub fn Initiator::to_repr(Self) -> @debug.Reprfrom a trait
pub fn is_bidi(UInt64) -> Bool
Whether stream id carries data both ways.
pub fn is_client(UInt64) -> Bool
Whether the client opened stream id.
pub fn is_local(UInt64, server~ : Bool) -> Bool
Whether this endpoint opened stream id.
pub fn is_writable(UInt64, server~ : Bool) -> Bool
Whether this endpoint may send on stream id: one it opened, or a bidirectional one the peer opened. A peer's unidirectional stream is receive-only (§2.1, §3).
pub fn Out::equal(Self, Self) -> Boolfrom a trait
pub fn Out::not_equal(Self, Self) -> Boolfrom a trait
pub fn Out::to_repr(Self) -> @debug.Reprfrom a trait
pub fn Quota::available(Self) -> UInt64
How many more may be opened.
pub fn Quota::grant(Self, UInt64) -> Unit
Adopt a limit from a MAX_STREAMS frame; as with data, a limit only rises.
pub fn Quota::new(UInt64) -> Self
A quota of limit streams, none opened.
pub fn Quota::open(Self, UInt64) -> Unit raise Refused
Record stream id as opened, by its sequence number. Refused when it is past the limit; opening one already counted changes nothing, because a stream is opened by whichever frame mentions it first and several may.
pub fn Receiving::equal(Self, Self) -> Boolfrom a trait
pub fn Receiving::next(Self, RecvEvent) -> Self raise Refused
The state after event (§3.2). A stream may be reset from any state short of a terminal one; the read events apply only once the data or the reset has arrived.
pub fn Receiving::not_equal(Self, Self) -> Boolfrom a trait
pub fn Receiving::to_repr(Self) -> @debug.Reprfrom a trait
pub fn RecvEvent::equal(Self, Self) -> Boolfrom a trait
pub fn RecvEvent::not_equal(Self, Self) -> Boolfrom a trait
pub fn RecvEvent::to_repr(Self) -> @debug.Reprfrom a trait
pub fn Refused::equal(Self, Self) -> Boolfrom a trait
pub fn Refused::not_equal(Self, Self) -> Boolfrom a trait
pub fn Refused::output(Self, &Logger) -> Unitfrom a trait
pub fn Refused::to_string(Self) -> Stringfrom a trait
pub fn Scheduler::cancel(Self, UInt64) -> Unit
Drop stream id: nothing more of it is scheduled.
pub fn Scheduler::new(Budget, frame? : UInt64) -> Self
A scheduler over budget, with frames capped at frame bytes.
pub fn Scheduler::next(Self) -> Chunk? raise Refused
The next decision, or None when no stream can send — all drained, or every one of them blocked by flow control. Streams take turns: whichever sent last goes to the back, so one stream with a great deal queued cannot starve the rest.
pub fn Scheduler::on_max_data(Self, UInt64) -> Unit
Raise the connection-wide send limit from a MAX_DATA frame.
pub fn Scheduler::on_max_stream_data(Self, UInt64, UInt64) -> Unit
Raise stream id's send limit from a MAX_STREAM_DATA frame.
pub fn Scheduler::on_params(Self, data~ : UInt64, bidi~ : UInt64, uni~ : UInt64) -> Unit
Apply the peer's transport parameters (RFC 9000 §18.2): the connection's limit, and what a new stream starts with by kind.
pub fn Scheduler::opened(Self, UInt64) -> Bool
Whether this end has opened stream id: a STREAM frame from the peer on it would be STREAM_STATE_ERROR (RFC 9000 §19.8).
pub fn Scheduler::queue(Self, UInt64, UInt64) -> Unit
pub fn Scheduler::queue_fin(Self, UInt64) -> Unit
Mark stream id finished: the FIN rides the frame that drains it, or goes alone.
pub fn SendEvent::equal(Self, Self) -> Boolfrom a trait
pub fn SendEvent::not_equal(Self, Self) -> Boolfrom a trait
pub fn SendEvent::to_repr(Self) -> @debug.Reprfrom a trait
pub fn Sending::equal(Self, Self) -> Boolfrom a trait
pub fn Sending::next(Self, SendEvent) -> Self raise Refused
The state after event (§3.1). A stream may be reset from any state short of a terminal one; writing after a terminal or reset state is refused.
pub fn Sending::not_equal(Self, Self) -> Boolfrom a trait
pub fn Sending::to_repr(Self) -> @debug.Reprfrom a trait
pub fn sequence(UInt64) -> UInt64
The stream's sequence number within its kind — the ID with its low two bits dropped.
pub fn Streams::accept(Self, UInt64, UInt64, Bytes, fin~ : Bool) -> Unit raise Refused
Take a STREAM frame and hold its bytes until read asks for them, so that flow-control credit comes back only as the application consumes. Frames for a stream already released are retransmissions, and are dropped. A stream numbered below others already open is not one of those: under loss it is simply late (RFC 9000 §3.2).
pub fn Streams::contains(Self, UInt64) -> Bool
Whether id is being tracked — a stream the peer opened, or one this end opened and the peer has since sent something on.
pub fn Streams::count(Self) -> Int32
How many streams are being tracked.
pub fn Streams::finished(Self, UInt64) -> Bool
Whether stream id has ended and all of it has been read.
pub fn Streams::limit(Self, bidi~ : Bool) -> UInt64
How many streams of that kind the peer may open, which is what a stream ID past it exceeds (RFC 9000 §4.6).
pub fn Streams::max_data(Self) -> UInt64?
The new MAX_DATA to advertise, or None when the gain would not be worth the frame (RFC 9000 §4.1).
pub fn Streams::max_stream_data(Self, UInt64) -> UInt64?
The new MAX_STREAM_DATA to advertise on id, or None.
pub fn Streams::max_streams(Self, bidi~ : Bool) -> UInt64?
The new MAX_STREAMS to advertise, or None when less than half the slots have come back.
pub fn Streams::new(UInt64, UInt64, server~ : Bool, bidi? : Quota, uni? : Quota) -> Self
Streams advertising data of connection-wide credit and stream_data per stream, admitting bidi and uni peer-opened streams of each kind (RFC 9000 §4.6). server says which side this is, so a peer's stream is told from our own. The stream quotas default to a hundred each, which is what quic-go and quiche both start at; leave them out and they apply, or pass a Quota to set them from the transport parameters that were actually negotiated.
pub fn Streams::on_reset(Self, UInt64, UInt64) -> Unit raise Refused
The peer abandoned stream id at final_size (RFC 9000 §3.2): what it would have sent still counts against the connection, and what is buffered is dropped.
pub fn Streams::on_stream(Self, UInt64, UInt64, Bytes, fin~ : Bool) -> Bytes raise Refused
Take a STREAM frame for id carrying data at offset, fin on the last fragment. Enforces the stream quota, then both flow-control windows, then reassembles, and answers with the bytes now readable — charged against both windows as they go out, because from the connection's point of view delivered is consumed.
pub fn Streams::read(Self, UInt64) -> Bytes
Any further contiguous bytes readable on id, empty when the stream is unknown or nothing new is contiguous.
pub fn Streams::release(Self, UInt64) -> Unit
Forget stream id; a stream the peer opened gives its slot back for max_streams to offer.
pub fn Streams::window(Self, UInt64) -> Window
Stream id's receive window, for the MAX_STREAM_DATA a reader's progress earns.
pub fn Window::arrived(Self, UInt64) -> Unit raise Refused
Record that data up to absolute offset offset has arrived. Refused when the peer passed the limit we advertised, which §4.1 makes a connection error.
pub fn Window::consume(Self, UInt64) -> Unit
Account for the application taking n more bytes, which frees window space.
pub fn Window::consumed(Self) -> UInt64
How much the application has taken.
pub fn Window::grant(Self) -> UInt64
Issue a new limit — what has been consumed plus a window — and answer with it: the MAX_DATA or MAX_STREAM_DATA value to send. The mirror of Credit::grant, which is how the other end takes it.
pub fn Window::limit(Self) -> UInt64
The limit currently advertised.
pub fn Window::new(UInt64, ratio? : Double) -> Self
A receive window of size bytes, which is also the initial advertised limit.
pub fn Window::should_grant(Self) -> Bool
Whether a new limit is worth advertising: what we could offer is at least ratio of a window beyond what we have.
conn
The transport itself: parameters, handshakes, paths and the event loop.
moonbitstack/moonquic/conn · 261 public items
Types
pub struct Client {
A client connection mid-handshake.
pub struct ClientEndpoint {
A set of client connections sharing an id space. It holds no socket: recv takes what a socket read, poll_out gives back what to write, and tick runs every connection's timers.
pub(all) struct Config {
What a server gives each new connection: the QUIC versions it speaks, the idle timeout it advertises, how long a closing or draining connection lingers, and the datagram size, timer tuning and flow-control credit the send loop starts from. Every duration is in microseconds, the unit the recovery code measures in.
versionsArray[UInt32]idle_timeoutInt64The idle timeout in force on a connection (RFC 9000 §10.1): the smaller of the two endpoints' advertisedmax_idle_timeouts, where zero on either side means that end asks for no limit at all.close_periodInt64max_datagramInt64max_ack_delayInt64granularityInt64initial_max_dataUInt64initial_max_stream_dataUInt64max_frameUInt64streams_bidiUInt64streams_uniUInt64max_datagram_frame_sizeUInt64connection_idsUInt64zero_rtt_dataUInt64zero_rtt_stream_dataUInt64retryBoolmax_path_idUInt64The largest path id a peer may name: it is folded into the packet nonce, which is twelve bytes wide, so the id has to fit in the low 32 bits (draft-ietf-quic-multipath §3.1).
pub struct Conn {
A QUIC connection's per-space numbering/ACK state and per-level CRYPTO streams.
pub struct Endpoint[A] {
A QUIC server: the connections it is holding, keyed by the connection id peers address each by, and the settings a new one starts from. A is the peer-address type — a socket address under the native event loop, whatever a test finds convenient under a fake sink.
pub(all) enum Event {
Something a connection has to tell its application.
ConnectedReadableUInt64ResetUInt64, UInt64StoppedUInt64, UInt64ClosedUInt64Datagram
pub(all) enum Kind {
A transport parameter's identifier (RFC 9000 §18.2, and RFC 9221's datagram extension). Other carries anything else: the block is read and written generically, so a parameter this build has no name for survives a round trip intact.
OriginalDcidMaxIdleTimeoutStatelessResetTokenMaxUdpPayloadMaxDataMaxStreamDataBidiLocalMaxStreamDataBidiRemoteMaxStreamDataUniMaxStreamsBidiMaxStreamsUniAckDelayExponentMaxAckDelayDisableActiveMigrationPreferredAddressActiveConnectionIdLimitInitialScidRetryScidMaxDatagramFrameSizeInitialMaxPathIdVersionInformationOtherUInt64
pub struct Lane[A] {
One path's sending state. space is the path's packet-number space, which is the same object the connection's core numbers that path's received packets in, so a number is used once whichever end asks. recovery is this path's alone: a path that loses a packet says nothing about the congestion on another.
pub(all) enum Level {
A QUIC encryption level / packet-number space (RFC 9001 §4.1.1). 0-RTT shares the Application space, so the three long-lived spaces are Initial, Handshake, and Application.
InitialHandshakeApplication
pub(all) struct Limits {
What a block says, with RFC 9000 §18.2's default for everything it leaves out. The integer parameters only; the connection IDs, the preferred address and the stateless reset token stay in the block, because they are identifiers and addresses rather than limits and the connection reads them where it needs them.
idle_timeoutUInt64The idle timeout in force on a connection (RFC 9000 §10.1): the smaller of the two endpoints' advertisedmax_idle_timeouts, where zero on either side means that end asks for no limit at all.udp_payloadUInt64dataUInt64stream_data_bidi_localUInt64stream_data_bidi_remoteUInt64stream_data_uniUInt64streams_bidiUInt64streams_uniUInt64ack_delay_exponentUInt64max_ack_delayUInt64active_connection_idsUInt64migrationBooldatagram_frameUInt64
pub(all) struct Param {
One transport parameter: what it is, and its value bytes. An integer parameter's value is a single varint — Param::int writes one and Param::as_int reads one.
kindKindvalueBytes
pub struct Path {
One path's validation state: the challenge outstanding, if any, and whether the path has ever been proven.
pub struct Paths {
The paths of one connection, path 0 being the one the handshake ran on.
pub(all) struct PathState {
One path: the id both ends use for it, the connection id traffic on it is addressed by, and what each end has said about it.
idUInt64
pub(all) enum Phase {
Where a connection is in its lifecycle (RFC 9000 §10.2): exchanging packets, closing — this endpoint sent a CONNECTION_CLOSE and answers anything further with it — or draining, where the peer closed and nothing more goes out.
ActiveClosingDraining
pub(all) suberror Refused {
A malformed transport-parameter block: a truncated parameter, or a length running past the block. decode raises it rather than answering with an empty list, so a caller cannot mistake a broken block for a peer that declared nothing.
MalformedString
pub(all) struct Remembered {
A ticket and the transport parameters the server declared when it issued it: what a client keeps from one connection to resume the next with early data.
session@tls.SessionparamsBytes
pub struct Sender {
A connection's send state for one packet-number space.
pub struct Server {
A QUIC server connection mid-handshake: the Initial keys, the packet-number/CRYPTO bookkeeping, and the TLS handshake it is driving.
pub struct Session[A] {
One server-side connection: the peer it answers, the connection ids the two ends address each other by, the handshake and send state machines it drives, and the counters the amplification limit, the idle timer and the closing period are read from. A is the peer-address type the enclosing Endpoint was built with.
pub struct Token {
What a token says: the address it was issued for, and the connection id the first Initial named (the Retry's tag and the Initial keys are bound to it).
Values
pub let amplification : Int64
The anti-amplification factor (RFC 9000 §8.1): until it has validated a peer's address, a server may send it at most this many times the bytes it has received from it.
pub let cid_size : Int32
How long a connection id this server issues is. A fixed length is what lets a short header, which does not say how long its id is, be read at all (RFC 9000 §5.2).
pub let limits : Limits
RFC 9000 §18.2's defaults: no idle timeout, the largest UDP payload the protocol permits, no flow-control credit and no streams until the peer says otherwise, an acknowledgement delay exponent of three, twenty-five milliseconds of acknowledgement delay, two connection IDs, migration allowed, and no datagram frames.
pub let max_path_id : UInt64
The largest path id a peer may name: it is folded into the packet nonce, which is twelve bytes wide, so the id has to fit in the low 32 bits (draft-ietf-quic-multipath §3.1).
pub let min_datagram : Int32
The smallest a datagram carrying an ack-eliciting Initial packet may be (RFC 9000 §14.1).
Functions
pub fn Client::add_path(Self, UInt64, Bytes, Bytes, Int64, nonce~ : Bytes, token~ : Bytes) -> Bool
Start a second path from this client (draft-ietf-quic-multipath §3.1): the caller names the peer's connection id for it, the id this end will answer to on it, and eight bytes for the PATH_CHALLENGE. The datagrams that follow are handed back by poll_paths, tagged with the path they belong on, because which socket each goes out of is the caller's to know.
pub fn Client::alpn(Self) -> String?
The ALPN protocol the handshake settled on.
pub fn Client::buffered(Self, UInt64) -> UInt64
How many bytes written to stream id the server has not acknowledged.
pub fn Client::close(Self, UInt64, Bytes, Int64, application? : Bool) -> Unit
Close the connection (RFC 9000 §10.2), in the shape Session::close has. An application's close before 1-RTT keys exist cannot name its own error code, so it goes as a transport close carrying APPLICATION_ERROR instead (RFC 9000 §10.2.3).
pub fn Client::early_accepted(Self) -> Bool
Whether the server accepted the early data this client offered.
pub fn Client::finished(Self, UInt64) -> Bool
Whether stream id has ended and every byte of it has been read.
pub fn Client::install_zero_rtt(Self, @crypto.Keys) -> Unit
Install the client's 0-RTT (early) keys (RFC 9001 §5.2) by hand. A client given a ticket and early=true has them from its handshake already; this is for keys that came from elsewhere.
pub fn Client::is_connected(Self) -> Bool
Whether the handshake has completed.
pub fn Client::negotiated_version(Self) -> UInt32
The QUIC version this connection settled on. It can differ from the version the first flight went out in: a server that converted that flight (RFC 9368 §2.3) answers in its own preferred version, which this client reads off the long headers and adopts.
pub fn Client::new(@tls.Client, String, Bytes, (Int32) -> Bytes, Bytes, Bytes, Int64, cfg? : Config, resumption? : Remembered) -> Self raise
A client for server_name, with config holding its roots and ALPN protocols. dcid is the connection id the Initial keys derive from (RFC 9001 §5.2) and scid the one this client calls itself; both are the caller's, so a test can make them reproducible.
pub fn Client::next_cid(Self) -> Bool
Start addressing the server by the next id it offered, and retire the one in use. Do this before sending from a new address on purpose, so the two paths cannot be linked (RFC 9000 §9.5). False when it has offered none.
pub fn Client::open_stream(Self, UInt64) -> Bool
Open a bidirectional stream this end initiates, without putting anything on it. A caller that places a stream's frames on a path of its own choosing — send_on — has to say the stream exists first: RFC 9000 §19.8 lets a peer answer only on a bidirectional stream this end opened, and the send loop's record of having opened it is what that turns on. Answers false for a stream this end may not initiate, which is a unidirectional one or the peer's own.
pub fn Client::open_uni(Self) -> UInt64
A new unidirectional stream from this client (RFC 9000 §2.1).
pub fn Client::path_lane(Self, UInt64) -> Lane[Unit]?
The sending state of path path, or None before anything has been sent on it.
pub fn Client::paths(Self) -> Paths
This connection's paths, path 0 being the one the handshake ran on.
pub fn Client::phase(Self) -> Phase
Where this connection is in its lifecycle.
pub fn Client::poll_out(Self, Int64) -> Array[Bytes]
The datagrams to put on the wire: the queued CRYPTO bytes split so no Initial packet runs past a datagram, each Initial padded to the 1200-byte floor (RFC 9000 §14.1), the early data the send loop has ready, then 1-RTT traffic once the handshake is done.
pub fn Client::poll_paths(Self, Int64) -> Array[(UInt64, Bytes)]
The datagrams the further paths have ready, each with the path it belongs on: what a lost packet carried, then a probe a path owes. A client's caller sends each on the socket that path runs over.
pub fn Client::probe(Self, Int64) -> Array[Bytes]
The datagrams to put on the wire for one more attempt at a deadlocked handshake: a PING in a padded Initial, which a server with no amplification budget left can still answer.
pub fn Client::read(Self, UInt64) -> Bytes
The bytes readable on stream id in order, emptied by the call; their flow-control credit goes back to the server here.
pub fn Client::recv(Self, Bytes, Int64) -> Unit raise
Take a datagram from the server: split it into packets, unprotect each at the level its header names, reassemble its CRYPTO stream, and drive the handshake with what becomes contiguous. A server's first datagram may coalesce packets; the keys one brings are installed before the next is read.
pub fn Client::recv_on(Self, UInt64, Bytes, Int64) -> Unit raise
Take a datagram that arrived on path path. A client has no address of its own — its caller owns the sockets — so the path a datagram belongs to is something only the caller knows, and it says so here (draft-ietf-quic-multipath §2.3). The path picks the packet-number space and the nonce the packet was sealed with.
pub fn Client::remembered(Self) -> Remembered?
The ticket this connection received and the parameters it was issued under, for the next connection to resume from. None before the handshake is done, when the server issued no ticket, or when the client was configured without a session store to keep one in.
pub fn Client::send_datagram(Self, Bytes) -> Bool
Queue an unreliable datagram (RFC 9221), answering whether the server will take it.
pub fn Client::send_on(Self, UInt64, Array[@frame.Frame], Int64) -> Bool
Put frames in one 1-RTT packet on path. Path 0 goes out the connection's own way and is picked up by poll_out; any other path is numbered, paced and recovered by its own lane.
pub fn Client::server_cid(Self) -> Bytes
The connection id the client addresses the server by — the server's, once it has named it.
pub fn Client::suite_code(Self) -> Int32
The TLS code of the cipher suite in force, 0 before one is chosen.
pub fn Client::take_datagrams(Self) -> Array[Bytes]
The datagrams that arrived since the last call, emptied by it.
pub fn Client::take_events(Self) -> Array[Event]
What has happened on this connection since the last call, emptied by it.
pub fn Client::tick(Self, Int64) -> Unit
Run the timers at now (RFC 9002 §6.2): the probe timeout on each handshake level, the send loop's own, the idle timeout, the closing period, and the probe a client owes a server it cannot hear — the last of which is what keeps a handshake from wedging when the server's amplification budget is spent (RFC 9002 §6.2.2.1).
pub fn Client::update_keys(Self) -> Bool
Move to the next key phase (RFC 9001 §6). The answer is false when it is not allowed yet: before the handshake is confirmed, or before something written in the current phase has been acknowledged, which is what stops an endpoint outrunning its peer's two sets of keys (§6.1, §6.2).
pub fn Client::versions(Self) -> Array[UInt32]
The versions a Version Negotiation packet offered, empty when none came. A non-empty answer means this attempt is over: RFC 9000 §6.2 leaves the caller to start another with one of them.
pub fn Client::write(Self, UInt64, Bytes, fin? : Bool) -> Unit
Queue data on stream id, ending it after the data when fin. Before the handshake finishes, data queued here leaves in 0-RTT packets when a ticket brought early keys, and the send loop carries it over to 1-RTT if the server refuses them (RFC 9000 §4.6.2).
pub fn ClientEndpoint::client(Self, Bytes) -> Client?
A connection by the id connect answered.
pub fn ClientEndpoint::connect(Self, @tls.Client, String, Bytes, Int64, dcid? : Bytes, scid? : Bytes, cfg? : Config) -> Bytes raise
Start a connection to server_name, answering the id this endpoint knows it by. scid is the id this client calls itself; left out, it is drawn from rand. dcid is what the first Initial is addressed to; left out, it is drawn too, since nothing has named it yet.
pub fn ClientEndpoint::count(Self) -> Int32
How many connections this endpoint holds.
pub fn ClientEndpoint::ids(Self) -> Array[Bytes]
The ids of the connections this endpoint holds.
pub fn ClientEndpoint::new(Config, rand~ : (Int32) -> Bytes) -> Self
An endpoint that holds no connections yet. rand is where a connection's own id comes from when the caller does not pick one.
pub fn ClientEndpoint::poll_out(Self, Int64) -> Array[Bytes]
Every datagram every connection has ready, in connection order. A caller loops until it is empty, sending each to the address it connected to.
pub fn ClientEndpoint::recv(Self, Bytes, Int64) -> Unit raise
Take a datagram from any of this endpoint's servers and hand it to the connection its Destination Connection ID names. One that names nothing here is dropped: another endpoint's traffic is not this one's to answer.
pub fn ClientEndpoint::remove(Self, Bytes) -> Unit
Forget a connection, as after it has closed and drained.
pub fn ClientEndpoint::tick(Self, Int64) -> Unit
Run every connection's timers.
pub fn Config::default() -> Self
QUIC version 1, a 30-second idle timeout, a 3-second closing period, 1200-byte datagrams, a 25-millisecond ACK delay, a mebibyte of flow-control credit on the connection and on each stream, and a hundred streams of each kind at a time, as HTTP/2 servers commonly allow.
pub fn Conn::build_ack(Self, Level, UInt64) -> @frame.Frame?
Build the ACK frame owed at level, or None if nothing has been received there.
pub fn Conn::crypto_stream(Self, Level) -> @stream.Assembler
The CRYPTO reassembler for level.
pub fn Conn::is_server(Self) -> Bool
Whether this endpoint is the server.
pub fn Conn::new(Bool) -> Self
A fresh connection (client or server) with empty spaces and CRYPTO streams.
pub fn Conn::next_packet_number(Self, Level) -> Int64
Allocate the next packet number to send at level.
pub fn Conn::on_ack_received(Self, Level, Int64) -> Unit
Record the peer's acknowledgement of up to largest at level.
pub fn Conn::on_crypto_frame(Self, Level, UInt64, Bytes) -> Bytes raise @stream.Refused
Feed a CRYPTO frame's data at offset and level into that level's handshake stream, returning the newly contiguous TLS handshake bytes now readable (empty while an earlier gap is still outstanding). CRYPTO streams carry no fin.
pub fn Conn::on_packet_received(Self, Level, Int64, Bool) -> Unit
Record that a packet numbered pn arrived at level; ack_eliciting marks one that must be acknowledged.
pub fn Conn::paths(Self) -> Int32
How many paths the connection numbers packets for, path 0 among them.
pub fn Conn::space(Self, Level) -> @packet.Space
The packet-number space for level.
pub fn Conn::space_on(Self, UInt64, Level) -> @packet.Space
The packet-number space for level on path path. Only Application has one per path: the handshake runs on path 0, and the draft gives 0-RTT and 1-RTT a space for each path id (draft-ietf-quic-multipath §2.3). Path 0 is the connection's own space.
pub fn decode(BytesView) -> Array[Param] raise Refused
Decode a block, or raise Refused when a parameter is truncated. The strict face of decode_opt, and what the connection reads a peer's block through.
pub fn encode(ArrayView[Param]) -> Bytes
Encode a block: each parameter as its identifier varint, a length varint, then its value (RFC 9000 §18).
pub fn[A] Endpoint::add_path(Self[A], Bytes, UInt64, A, Bytes, Int64, nonce~ : Bytes) -> Bool
Open a second path on connection cid (draft-ietf-quic-multipath §3.1). This endpoint makes the connection id the path answers to, so a packet for it routes here like any other id the connection holds, and the peer is told which id to use on that path.
pub fn[A] Endpoint::close(Self[A], Bytes, UInt64, Bytes, Int64) -> Unit
Close the connection cid addresses with error_code and reason, if the server holds one (RFC 9000 §10.2).
pub fn[A] Endpoint::conn(Self[A], Bytes) -> Session[A]?
The connection cid addresses, or None if the server is not holding one.
pub fn[A] Endpoint::conn_ids(Self[A]) -> Array[Bytes]
The connection ids the server is holding.
pub fn[A] Endpoint::count(Self[A]) -> Int32
How many connections the server is holding.
pub fn[A] Endpoint::new(Config) -> Self[A]
A server holding no connections, handing cfg to each one it opens.
pub fn[A] Endpoint::poll_out(Self[A], Int64) -> (Bytes, A)? raise
The next datagram to put on the wire and the peer to send it to, or None when no connection has one ready.
pub fn[A : Eq] Endpoint::recv(Self[A], Bytes, A, Int64, wall? : Int64) -> Unit raise
Take a datagram received at now from from: route it to the connection its Destination Connection ID names, opening one when an Initial packet arrives for an id the server does not hold, and drive that connection with it (RFC 9000 §5.2). A datagram naming no connection is dropped — RFC 9000 §10.3's stateless reset is not implemented. now is the timers' clock, in microseconds. wall is the time in seconds since the Unix epoch that tickets and client certificates are judged at, a different clock: left out, this endpoint neither issues nor takes a ticket.
pub fn[A] Endpoint::server(Config, @tls.Server, rand~ : (Int32) -> Bytes, cid? : () -> Bytes, address? : (A) -> Bytes) -> Self[A]
A server that runs the TLS handshake itself: tls holds its certificate chain, key and ALPN protocols, and rand is the source of its handshake randomness. cid makes the connection ids this server issues, cid_size bytes each; by default they are drawn from rand. A server behind something that routes datagrams by connection id (several processes on one port, or a load balancer in the manner of QUIC-LB) puts its own number in them here. An id that is not cid_size bytes, or that is already in use, is drawn again.
pub fn[A] Endpoint::take_busy(Self[A]) -> Array[Session[A]]
The connections with something to tell their application, each once, emptied by the call.
pub fn[A] Endpoint::tick(Self[A], Int64) -> Unit
Run the timers at now. An idle connection is forgotten without a CONNECTION_CLOSE, which is what RFC 9000 §10.1 asks for; a closing or draining one is forgotten when its period ends (§10.2); an active one whose probe timeout has come re-queues its oldest outstanding packet, to go out on the next poll_out (RFC 9002 §6.2.4).
pub fn Event::equal(Self, Self) -> Boolfrom a trait
pub fn Event::not_equal(Self, Self) -> Boolfrom a trait
pub fn Event::to_repr(Self) -> @debug.Reprfrom a trait
pub fn extension(ArrayView[Param]) -> @ext.Ext
The extension a block rides in. RFC 9001 §8.2 makes it mandatory for both endpoints, and moontls carries it without reading it, because the contents are QUIC's.
pub fn find(ArrayView[Param], Kind) -> Param?
The parameter in a block, or None. A repeated parameter is a connection error, so the first one is what counts.
pub fn idle_timeout(Int64, Int64) -> Int64
The idle timeout in force on a connection (RFC 9000 §10.1): the smaller of the two endpoints' advertised max_idle_timeouts, where zero on either side means that end asks for no limit at all.
pub fn is_stateless_reset(BytesView, BytesView) -> Bool
Whether packet is a stateless reset carrying token: a short-header-form datagram of at least 21 bytes whose last sixteen bytes are the token.
pub fn issue_token(Bytes, Bytes, Bytes, Int64) -> Bytes
The token for a client at address whose first Initial named odcid, stamped with now. An endpoint that cannot name an address passes an empty one, and the token then binds the connection id and the time alone.
pub fn Kind::code(Self) -> UInt64
The identifier on the wire.
pub fn Kind::equal(Self, Self) -> Boolfrom a trait
pub fn Kind::not_equal(Self, Self) -> Boolfrom a trait
pub fn Kind::of(UInt64) -> Self
The parameter a wire identifier names.
pub fn Kind::server_only(Self) -> Bool
Whether only a server may send this parameter (RFC 9000 §18.2's closing paragraph). A client that sends one is a TRANSPORT_PARAMETER_ERROR.
pub fn Kind::to_repr(Self) -> @debug.Reprfrom a trait
pub fn[A] Lane::can_send(Self[A], Int64) -> Bool
Whether bytes more may go on this path without exceeding its congestion window.
pub fn[A] Lane::due(Self[A]) -> Array[@frame.Frame]?
The frames waiting to go out again on this path: what a lost packet carried, then a PING if a probe is owed and nothing else waits.
pub fn[A] Lane::id(Self[A]) -> UInt64
The path id this state belongs to.
pub fn[A] Lane::in_flight(Self[A]) -> Int32
How many of this path's packets are outstanding.
pub fn[A] Lane::new(UInt64, A, @packet.Space, @recovery.State, Int64) -> Self[A]
A path's state with nothing on it yet.
pub fn[A] Lane::on_ack(Self[A], @frame.Frame, Int64, Int32) -> Unit raise
An acknowledgement for this path (draft-ietf-quic-multipath §4.1): what it settles leaves the flight, and what it declares lost is queued for this path. Answers with the bytes that are still outstanding, which is what the caller's window is read from.
pub fn[A] Lane::on_pto(Self[A], Int64) -> Bool
The probe timeout fired at now: the two oldest packets still outstanding go out again as probes, and the timer backs off (RFC 9002 §6.2.4). Answers whether this path had anything to send, which is what tells a driver to call due.
pub fn[A] Lane::peer(Self[A]) -> A
The address this path's datagrams go to.
pub fn[A] Lane::rebind(Self[A], A) -> Unit
The address this path's datagrams go to, changed when the peer rebinds it (draft §5.1).
pub fn[A] Lane::recovery(Self[A]) -> @recovery.State
This path's round-trip estimate, loss detection and congestion window.
pub fn[A] Lane::send(Self[A], Int64, Array[@frame.Frame], Int64) -> Int64?
Number frames into a packet on this path at now, or None when its window is closed or its pacing bucket is empty. The caller seals the packet; this keeps the numbering and the record a lost packet is sent again from.
pub fn[A] Lane::space(Self[A]) -> @packet.Space
This path's packet-number space.
pub fn Level::equal(Self, Self) -> Boolfrom a trait
pub fn Level::not_equal(Self, Self) -> Boolfrom a trait
pub fn Level::to_repr(Self) -> @debug.Reprfrom a trait
pub fn Limits::equal(Self, Self) -> Boolfrom a trait
pub fn Limits::new(idle_timeout? : UInt64, udp_payload? : UInt64, data? : UInt64, stream_data_bidi_local? : UInt64, stream_data_bidi_remote? : UInt64, stream_data_uni? : UInt64, streams_bidi? : UInt64, streams_uni? : UInt64, ack_delay_exponent? : UInt64, max_ack_delay? : UInt64, active_connection_ids? : UInt64, migration? : Bool, datagram_frame? : UInt64) -> Self
Limits by name, each defaulting to RFC 9000 §18.2's.
pub fn Limits::not_equal(Self, Self) -> Boolfrom a trait
pub fn Limits::params(Self) -> Array[Param]
The block these limits amount to, leaving out everything still at its default so a handshake carries only what it changes.
pub fn Limits::read(ArrayView[Param], base? : Self) -> Self
The limits a block conveys, starting from base and applying what the block sets. A parameter whose value is not a well-formed varint is left at its default rather than refused: §18.1 makes that a connection error, and deciding to close is the connection's call, not this reader's.
pub fn Limits::to_repr(Self) -> @debug.Reprfrom a trait
pub fn of_extensions(ArrayView[@ext.Ext]) -> Array[Param]
The block a TLS extension list carries (RFC 9001 §8.2), empty when the extension is absent or its block is truncated: an endpoint with no block falls back to RFC 9000 §18.2's defaults, which is what an empty list reads as.
pub fn Param::as_int(Self) -> UInt64?
The integer a varint-valued parameter carries, or None when its value is not exactly one well-formed varint.
pub fn Param::equal(Self, Self) -> Boolfrom a trait
pub fn Param::flag(Kind) -> Self
A parameter with no value, which is how the flag parameters are carried.
pub fn Param::int(Kind, UInt64) -> Self
A parameter whose value is one varint (RFC 9000 §18.2).
pub fn Param::not_equal(Self, Self) -> Boolfrom a trait
pub fn Param::to_repr(Self) -> @debug.Reprfrom a trait
pub fn Path::challenge(Self) -> Bytes
The challenge still outstanding, or empty when there is none.
pub fn Path::check(Self, Bytes) -> Bool
Whether a PATH_RESPONSE's data answers the outstanding challenge. The comparison runs over the whole challenge and accumulates rather than stopping at the first byte, so how long it takes says nothing about how much of the value was guessed. A response with no challenge outstanding, or of another length, never validates.
pub fn Path::new() -> Self
A path nothing has been sent on yet: no challenge, not validated.
pub fn Path::reset(Self) -> Unit
Forget the path: no challenge outstanding and no proof, as after a connection moves to a path that has never answered.
pub fn Path::start(Self, Bytes) -> Bytes
Begin validating the path with the eight-byte nonce, answering the challenge to put in a PATH_CHALLENGE. A new challenge supersedes one still outstanding, and a path that was validated has to prove itself again.
pub fn Path::validated(Self) -> Bool
Whether the path has been proven.
pub fn Paths::abandon(Self, UInt64) -> Bool
Give up a path. Path 0 is the connection's and cannot go (draft-ietf-quic-multipath §3.1).
pub fn Paths::allowed(Self, UInt64) -> Bool
Whether id is a path id the peer may use without a new one being negotiated.
pub fn Paths::bind(Self, UInt64, Bytes) -> Unit
Give the path id the connection id dcid and start it unvalidated: the first thing on it is a PATH_CHALLENGE (draft-ietf-quic-multipath §3.2).
pub fn Paths::bind_local(Self, UInt64, Bytes) -> Bool
Give path id the connection id this end answers to on it (draft-ietf-quic-multipath §3.2). A packet that arrives for that id belongs to this path and to its packet-number space.
pub fn Paths::count(Self) -> Int32
How many paths the connection has, path 0 among them.
pub fn Paths::free(Self) -> UInt64?
The lowest path id nobody is using, if the peer's limit leaves room for one. None means a MAX_PATH_ID has to arrive before this connection can grow another path.
pub fn Paths::get(Self, UInt64) -> PathState?
The path with this id, if the connection has it.
pub fn Paths::ids(Self) -> Array[UInt64]
The ids of the paths the connection has.
pub fn Paths::local_cid(Self, UInt64) -> Bytes
The connection id this end answers to on path id, empty when it has none.
pub fn Paths::local_max(Self) -> UInt64
The largest path id this end will open or accept.
pub fn Paths::new(local_max? : UInt64) -> Self
A connection that has only the path its handshake ran on. local_max is what this end advertises as initial_max_path_id: zero means multipath is not offered at all.
pub fn Paths::next_status(Self, UInt64) -> UInt64?
The next status sequence number to put on a PATH_STATUS for id: the two states share one counter space for each path, and it only rises (draft-ietf-quic-multipath §4.3).
pub fn Paths::on_max_path_id(Self, UInt64) -> Unit
The peer's MAX_PATH_ID: it may only rise, and it is never below what its initial_max_path_id already said (draft-ietf-quic-multipath §4.5).
pub fn Paths::on_peer_cid(Self, UInt64, UInt64, Bytes) -> Bool
Take a connection id the peer offered for id (draft-ietf-quic-multipath §4.4), which is what this end addresses that path by from now on. An older sequence number than the one in use is a reordering, not news. The peer issues the id for a path before anything has been sent on it — that is what the id is for — so a path with no state yet is opened here rather than refused. Without that, a peer that offers its paths on its own initiative, which is what the draft's own example does, leaves the other end unable to open any of them.
pub fn Paths::on_status(Self, UInt64, UInt64, Bool) -> Bool
Take the peer's PATH_STATUS for id: a sequence number at or below one already heard is a reordering, not news (draft-ietf-quic-multipath §4.4).
pub fn Paths::on_validated(Self, UInt64) -> Unit
The peer answered a challenge on id.
pub fn Paths::open(Self) -> Array[UInt64]
The path ids that are carrying traffic: everything bound and not given up.
pub fn Paths::openable(Self, UInt64) -> Bool
Whether id is a path this end may open: the peer said it would maintain that many paths, and this end is willing to as well (draft-ietf-quic-multipath §2.1).
pub fn Paths::path_of(Self, Bytes) -> UInt64
The path a connection id belongs to, or 0 when no path has claimed it. Path 0's id is the connection's own, which the table already routes by.
pub fn Paths::peer_cid(Self, UInt64) -> Bytes
The connection id this end addresses path id by, empty when the path is not bound.
pub fn Paths::peer_max(Self) -> UInt64
The largest path id the peer said it would accept.
pub fn Paths::prove(Self, UInt64, Bytes) -> Bool
Whether data answers the challenge outstanding on path id. The comparison runs over every byte rather than stopping at the first difference, so how long it takes says nothing about how much of the value was right. A path with no challenge outstanding never proves.
pub fn Paths::retire_peer_cid(Self, UInt64, UInt64) -> Bool
The peer gave up sequence number seq on path id (draft-ietf-quic-multipath §4.5). The id in use on a path is the peer's to keep, so this only says it is no longer spare.
pub fn Paths::start(Self, UInt64, Bytes) -> Bytes
Begin proving path id with the eight-byte nonce (draft-ietf-quic-multipath §3.1): answers with the challenge to put in a PATH_CHALLENGE, which goes out on the path itself.
pub fn Paths::validated(Self, UInt64) -> Bool
Whether the path has answered a challenge.
pub fn Phase::equal(Self, Self) -> Boolfrom a trait
pub fn Phase::not_equal(Self, Self) -> Boolfrom a trait
pub fn Phase::to_repr(Self) -> @debug.Reprfrom a trait
pub fn read_token(Bytes, Bytes, Int64, Bytes) -> Token?
What a token says, or None when it is short, of another format, tagged with another key, or older than token_life. now is the same clock the token was stamped from.
pub fn read_version_information(BytesView) -> (UInt32, Array[UInt32])?
The versions a version_information value carries: the chosen one and the list. None when the value is shorter than one version or not a whole number of them, which is what RFC 9368 §4 makes a connection error.
pub fn recv_long(Bytes, @crypto.Keys, largest? : Int64) -> (Array[@frame.Frame], Int64)? raise @packet.Refused
The frames a protected long-header packet carries, and its packet number, expanded against largest, the largest number received in its space. None when the tag does not match, which is a packet to drop rather than an error to report.
pub fn recv_short(Bytes, Int32, @crypto.Keys, largest? : Int64, path? : UInt64) -> (Array[@frame.Frame], Int64)? raise @packet.Refused
The same for a 1-RTT packet, whose connection-id length only the receiver knows.
pub fn Refused::equal(Self, Self) -> Boolfrom a trait
pub fn Refused::not_equal(Self, Self) -> Boolfrom a trait
pub fn Refused::output(Self, &Logger) -> Unitfrom a trait
pub fn Refused::to_string(Self) -> Stringfrom a trait
pub fn reset_token(Bytes, Bytes) -> Bytes
The sixteen-byte stateless reset token for cid, derived from the endpoint's key. The same pair always yields the same token, which is what lets an endpoint answer for a connection it has already forgotten.
pub fn seal_long(@packet.Kind, UInt32, Bytes, Bytes, Int64, Int32, Bytes, @crypto.Keys, token? : Bytes) -> Bytes
The same from a payload already encoded, which is what padding an Initial to the minimum datagram needs (RFC 9000 §14.1).
pub fn send_long(@packet.Kind, UInt32, Bytes, Bytes, Int64, Int32, Array[@frame.Frame], @crypto.Keys, token? : Bytes) -> Bytes
A protected long-header packet carrying frames at this level. The three lines it stands for — build the header, seal the payload, protect the header — are worth writing out once to see, and worth not writing out every time after that. @packet.Long::header and @crypto.Keys::seal are still there for a sender that wants the pieces.
pub fn send_short(Bytes, Int64, Int32, Array[@frame.Frame], @crypto.Keys, spin? : Bool, key_phase? : Bool, path? : UInt64) -> Bytes
A protected 1-RTT packet carrying frames.
pub fn send_zero_rtt(Bytes, Bytes, Int64, Int32, Array[@frame.Frame], @crypto.Keys, version? : UInt32) -> Bytes
A protected 0-RTT packet carrying frames (RFC 9001 §5.2): a long header of the 0-RTT type, no Initial token, the client's early keys, and the Application packet-number space.
pub fn Sender::abandon(Self, UInt64, UInt64) -> Unit
Stop sending on stream id: nothing queued or lost on it goes out from now on, and a RESET_STREAM tells the peer where it ended.
pub fn Sender::advance_past(Self, Int64) -> Unit
Skip the send counter past pn, so a packet this sender did not build — a driver's ACK-only packet in the same space — does not collide with a number it later assigns. A pn the sender is already past leaves it alone.
pub fn Sender::buffered(Self, UInt64) -> UInt64
How many bytes written to stream id the peer has not acknowledged yet.
pub fn Sender::new(UInt64, UInt64, Int64, Int64, Int64, UInt64) -> Self
A fresh sender: initial_max_data/initial_max_stream_data are the peer's advertised flow limits, max_datagram_size sizes the congestion window, max_ack_delay/granularity tune the timers (microseconds), and max_frame caps a STREAM frame's payload.
pub fn Sender::on_ack(Self, @frame.Frame, Int64) -> Unit raise
Process a received ACK frame at now: clear acknowledged packets from the recovery state and re-queue the contents of any packet the ACK reveals as lost, to be retransmitted by a later poll_send (RFC 9002 §6). Raises on a malformed ACK.
pub fn Sender::on_max_data(Self, UInt64) -> Unit
Raise the connection-wide send limit from a received MAX_DATA frame.
pub fn Sender::on_max_stream_data(Self, UInt64, UInt64) -> Unit
Raise stream id's send limit from a received MAX_STREAM_DATA frame.
pub fn Sender::on_peer_datagram(Self, UInt64) -> Unit
Adopt the peer's max_datagram_frame_size (RFC 9221 §3). Zero means the peer will not receive datagrams, and queue_datagram refuses them.
pub fn Sender::on_pto_timeout(Self, Int64) -> Bool
Handle the probe timeout firing at now (RFC 9002 §6.2.4). If the PTO deadline has passed with packets still outstanding, re-queue the contents of the two oldest packets that still hold any as probes (§6.2.4 allows two, so one lost does not cost another timeout) — a later poll_send puts them back on the wire — and back off the timer for the next arming. A packet that went out again at an earlier timeout stays outstanding until an ACK settles it, which is why the oldest alone will not do. Unlike loss detection, this neither declares packets lost nor reduces the congestion window. Returns whether a probe was armed.
pub fn Sender::outstanding(Self) -> Array[Int64]
The packet numbers still outstanding (sent, not yet acknowledged or declared lost).
pub fn Sender::paced_at(Self, Int64) -> Int64?
When the next datagram's worth of credit accrues, or None when it is there now. A driver that got None from poll_send arms a timer on this and comes back.
pub fn Sender::pacing_rate(Self) -> Double
The rate this sender paces at, in bytes per microsecond; zero while it is unpaced.
pub fn Sender::pending_datagrams(Self) -> Int32
How many datagrams are waiting for a packet.
pub fn Sender::poll_send(Self, Int64, zero? : Bool) -> (Int64, Array[@frame.Frame])? raise
The next packet to send at now, or None when the congestion window is closed or nothing is queued (RFC 9002 §7). Control frames go first, then one retransmission or one fresh chunk; the packet is recorded in the recovery state and its contents remembered for retransmission. A probe is sent whatever the window says, since it is how a sender whose whole window was lost finds out (RFC 9002 §7.5), and is a PING when there is nothing else to carry.
pub fn Sender::queue_control(Self, @frame.Frame) -> Unit
Queue a control frame to go out reliably: it is sent again if the packet carrying it is lost.
pub fn Sender::queue_datagram(Self, Bytes) -> Bool
Queue an unreliable datagram for the next 1-RTT packet, answering whether it was taken. It is refused when the peer advertised no datagram support, when it is larger than the peer accepts, or when it would not fit a datagram beside the header, tag and a small ACK. A datagram is never retransmitted.
pub fn Sender::queue_fin(Self, UInt64) -> Unit
Mark stream id finished.
pub fn Sender::queue_stream(Self, UInt64, Bytes) -> Unit
Queue bytes of application data to send on stream id, after anything queued before.
pub fn Sender::requeue_all(Self) -> Unit
Put everything still in flight back in the queue, for the case where a packet space's keys change under it: 0-RTT refused by the server has to go again as 1-RTT (RFC 9000 §4.6.2). The congestion state is left alone; those packets come out of flight when they are declared lost, so the window is not opened twice.
pub fn Sender::window(Self) -> Int64
The current congestion window (bytes).
pub fn Server::client_hello(Self) -> Bytes
The raw ClientHello the connection received (empty before one arrives): the source a server runs the ECDHE key_share from to derive its handshake secrets.
pub fn Server::convert_to(Self, UInt32) -> Unit
Convert the first flight into version (RFC 9368 §2.3): both directions' Initial keys are re-derived from the same connection id under that version's salt, and the long headers this endpoint writes from now on name that version. Version 1 and version 2 first flights differ only in these version-dependent constants, so nothing in the CRYPTO stream has to change. The caller keeps the old receive keys for Initial packets already on the wire.
pub fn Server::handshake_state(Self) -> @hs.Server
The current TLS handshake state.
pub fn Server::initial_ack_pending(Self) -> Bool
Whether an ACK is owed in the Initial space.
pub fn Server::negotiate(Self) -> @hs.Choice raise @alert.Alert
Negotiate the ClientHello this connection received (RFC 8446 §4.1.1): the group and key share to run the ECDHE with, and the signature scheme to sign the CertificateVerify under, read off what the client offered. Raises the §6 alert for a ClientHello this build cannot serve, and returns Retry when the answer is a HelloRetryRequest.
pub fn Server::new(Bytes, version? : UInt32) -> Self
A server connection for a client whose Destination Connection ID is dcid (the Initial secret and keys derive from it, RFC 9001 §5.2).
pub fn Server::on_frames(Self, Level, Array[@frame.Frame], Int64) -> Array[@msg.Kind] raise
Drive an already-unprotected packet's frames at level, numbered pn: record the packet for acknowledgement and feed its CRYPTO frames into that level's reassembler, driving the handshake with whatever handshake bytes become contiguous. Returns the handshake message types processed. A driver that unprotected the packet itself — because it also wants the ACK and CONNECTION_CLOSE frames beside the CRYPTO — enters here rather than through receive_initial.
pub fn Server::on_handshake_frames(Self, Array[@frame.Frame], Int64, Bytes) -> Bool raise
Drive the client's Handshake-space frames, numbered pn, already unprotected: record the packet, reassemble its CRYPTO stream, verify any Finished in it against client_hs_secret over the transcript as it stands, then fold the messages in. Returns whether the handshake is now connected with a Finished that authenticated — the frame-level half of receive_handshake, for a driver holding the decrypted packet.
pub fn Server::receive_handshake(Self, Bytes, @crypto.Keys, Bytes) -> Bool raise
Receive the client's Handshake-space flight — in this no-client-authentication path, the client Finished (RFC 8446 §4.4.4): unprotect the Handshake packet with the client handshake keys, reassemble its CRYPTO stream, verify the Finished verify_data against client_hs_secret over the transcript through the server Finished, then fold it in to advance the handshake to CONNECTED. Returns whether the handshake is now connected with a Finished that authenticated. Raises if the packet fails to authenticate.
pub fn Server::receive_initial(Self, Bytes) -> Array[@msg.Kind] raise
Receive a client Initial packet: unprotect it, record its number for acknowledgement, reassemble its CRYPTO frames, and drive the handshake with the contiguous handshake bytes. Returns the handshake message types processed. Raises if the packet fails to authenticate.
pub fn Server::reply_as(Self, UInt32) -> Unit
Answer under version from now on: the reply keys are re-derived from the same connection id under that version's salt (RFC 9369 §3.3), which is what a version negotiated compatibly does to a server's own Initial packets (RFC 9368 §2.3). The keys the client's packets arrive under are left alone, since it may still be sending the version it started with.
pub fn Server::send_handshake_flight(Self, Bytes, Bytes, Bytes, (Bytes) -> Bytes, Bytes, Bytes, Int64) -> Bytes raise
Send the server's Handshake-space flight (RFC 8446 §4, RFC 9001 §5): encode EncryptedExtensions, Certificate, and CertificateVerify, fold them into the transcript in order, compute the server Finished as HMAC(finished_key, transcript hash through CertificateVerify) over server_hs_secret, fold the Finished too, and advance the state past the whole flight (RECVD_CH → WAIT_FINISHED). The four messages form one contiguous CRYPTO stream, protected into a Handshake packet with the handshake-space keys @crypto.Keys::of(server_hs_secret[:]), addressed to out_dcid from out_scid at Handshake packet number pn. server_hs_secret is the server handshake traffic secret the key schedule derives once ECDHE completes.
pub fn Server::send_server_hello(Self, @msg.Server, Bytes, Bytes, Int64) -> Bytes
Build the server's ServerHello response: encode it, fold it into the transcript, and protect it into an Initial packet addressed to out_dcid (the client's source connection id) from out_scid, at Initial packet number pn (RFC 9001 §5.3). The state stays at RECVD_CH — the server flight is not complete until the Handshake-space messages (EncryptedExtensions, Certificate, CertificateVerify, Finished) are sent by send_handshake_flight, which advances it to WAIT_FINISHED.
pub fn Server::transcript_hash(Self) -> Bytes
The transcript hash over the handshake messages processed so far.
pub fn[A] Session::add_path(Self[A], UInt64, A, Bytes, Bytes, Int64, nonce~ : Bytes, token~ : Bytes) -> Bool
Start a second path: give it path, address its datagrams to peer by the peer's dcid, and answer to lcid on it (draft-ietf-quic-multipath §3.1). A PATH_CHALLENGE goes out on the path at once, and the peer is told which connection id to use for it, so the two ends can tell the path's packets from another's. Answers false when the peer offered no room for that path id, or the handshake is not done.
pub fn[A] Session::alpn(Self[A]) -> String?
The ALPN protocol the handshake settled on.
pub fn[A] Session::apply_peer_params(Self[A], Array[Param]) -> Unit
Apply the peer's transport parameters (RFC 9000 §18): the idle timer settles at the smaller of the two ends' values, and the peer's initial flow-control credit opens the connection-wide send window, which §18.2 says is a MAX_DATA arriving at once.
pub fn[A] Session::buffered(Self[A], UInt64) -> UInt64
How many bytes written to stream id the peer has not acknowledged, which is what an application paces itself by.
pub fn[A] Session::can_send(Self[A], Int32) -> Bool
Whether n more bytes may go to this peer: unrestricted once its address is validated, otherwise at most three times what it has sent this server (RFC 9000 §8.1).
pub fn[A] Session::cid(Self[A]) -> Bytes
The connection id the peer addresses this server by — the table's key.
pub fn[A] Session::close(Self[A], UInt64, Bytes, Int64, application? : Bool) -> Unit
Close the connection (RFC 9000 §10.2): put a CONNECTION_CLOSE carrying error_code and reason on the wire at the highest level with keys, drop whatever else was queued, and enter the closing period — during which every packet the peer sends is answered with the same CONNECTION_CLOSE, and at the end of which tick forgets the connection. Closing a connection that is already closing or draining does nothing.
pub fn[A] Session::core(Self[A]) -> Server
The handshake state machine underneath, for a caller driving the TLS flights.
pub fn[A] Session::finished(Self[A], UInt64) -> Bool
Whether stream id has ended and every byte of it has been read.
pub fn[A] Session::idle_timeout(Self[A]) -> Int64
The idle timeout in force, in microseconds; zero means none.
pub fn[A] Session::install_app_keys(Self[A], Bytes, Bytes) -> Unit
Install the Application-space (1-RTT) keys, derived from the two application traffic secrets. Until they are installed, a short-header packet is dropped and the send loop has nowhere to put stream data.
pub fn[A] Session::install_handshake_keys(Self[A], Bytes, Bytes) -> Unit
Install the Handshake-space keys, derived from the client's and this server's handshake traffic secrets (RFC 9001 §5.1). Until they are installed, a Handshake packet cannot be unprotected and is dropped; after, the connection reads and writes at that level. The client's secret is kept so an arriving Finished can be verified against it.
pub fn[A] Session::install_zero_rtt(Self[A], @crypto.Keys) -> Unit
Install the server's 0-RTT (early) keys (RFC 9001 §5.2), from the early traffic secret the handshake resumed a ticket for. Until they are installed, a 0-RTT packet is dropped.
pub fn[A] Session::largest_acked(Self[A], Level) -> Int64?
The largest packet number the peer has acknowledged at level, or None before its first ACK there.
pub fn[A] Session::negotiated_version(Self[A]) -> UInt32
The QUIC version this connection settled on, as its long headers and its own version_information name it (RFC 9368 §4). A server that converted a first flight may answer in a version other than the one the client sent it in.
pub fn[A] Session::open_uni(Self[A]) -> UInt64
A new unidirectional stream from this server (RFC 9000 §2.1).
pub fn[A] Session::packets_received(Self[A]) -> Int32
Datagrams received on this connection.
pub fn[A] Session::path_lane(Self[A], UInt64) -> Lane[A]?
The sending state of path path, or None before anything has been sent on it.
pub fn[A] Session::path_validated(Self[A]) -> Bool
Whether the path the peer is on has answered a PATH_CHALLENGE (RFC 9000 §8.2). A fresh connection starts unvalidated; the handshake's own return traffic validates the path it arrived on, and a move to a new address starts again.
pub fn[A] Session::paths(Self[A]) -> Paths
This connection's paths (draft-ietf-quic-multipath §3): path 0 is the handshake's, and any others are the ones the two ends have agreed to keep.
pub fn[A] Session::peer(Self[A]) -> A
The peer this connection answers.
pub fn[A] Session::pending(Self[A]) -> Int32
Datagrams built and waiting to go out — non-zero while the amplification limit or a closed congestion window is holding them back.
pub fn[A] Session::phase(Self[A]) -> Phase
Where this connection is in its lifecycle.
pub fn[A] Session::poll_lane(Self[A], Int64) -> (Bytes, A)?
The next datagram on a path other than the connection's own, with the address it belongs on, or None when no path has anything waiting. What a lost packet carried goes first, then a probe the path owes.
pub fn[A] Session::queue_stream(Self[A], UInt64, Bytes) -> Unit
Queue bytes to send on stream id; the send loop frames and paces them out through poll_out once the Application keys are installed.
pub fn[A] Session::read(Self[A], UInt64) -> Bytes
The bytes readable on stream id in order, emptied by the call. Their flow-control credit goes back to the peer here.
pub fn[A] Session::release(Self[A], UInt64) -> Unit
The application is done with stream id: its slot goes back to the peer (RFC 9000 §4.6).
pub fn[A] Session::reset(Self[A], UInt64, UInt64) -> Unit
Abandon sending on stream id with code.
pub fn[A] Session::rx_bytes(Self[A]) -> Int64
Bytes received from the peer, the numerator of the amplification limit.
pub fn[A] Session::send(Self[A], Level, Array[@frame.Frame]) -> Unit
Queue frames to go out at level on the next poll_out, numbered from that level's packet-number space. An Initial packet carrying anything ack-eliciting takes its datagram to the 1200-byte floor (RFC 9000 §14.1); a level whose keys are not installed drops the frames, since there is nothing to protect them with.
pub fn[A] Session::send_datagram(Self[A], Bytes) -> Bool
Queue an unreliable application datagram (RFC 9221), answering whether it was taken. It is refused when the peer did not advertise datagram support or when it would not fit.
pub fn[A] Session::send_level(Self[A]) -> Level
The highest encryption level this connection can send at — Application once its 1-RTT keys are in, else Handshake, else Initial, which is always available.
pub fn[A] Session::send_on(Self[A], UInt64, Array[@frame.Frame], Int64) -> Bool
Put frames in one 1-RTT packet on path: numbered from that path's space, paced and gated by that path's congestion window, and sealed with the nonce its id names (draft-ietf-quic-multipath §2.4). Path 0 keeps the connection's own send loop, so its packets are numbered and recorded there. Answers whether a packet went out.
pub fn[A] Session::server_name(Self[A]) -> String?
The host name the client asked for by SNI.
pub fn[A] Session::stop(Self[A], UInt64, UInt64) -> Unit
Ask the peer to stop sending on stream id with code.
pub fn[A] Session::suite_code(Self[A]) -> Int32
The TLS code of the cipher suite in force, 0 before one is chosen.
pub fn[A] Session::take_datagrams(Self[A]) -> Array[Bytes]
The datagrams that arrived since the last call, emptied by it, in arrival order. A datagram is whole; it is not a byte stream and nothing is retransmitted.
pub fn[A] Session::take_events(Self[A]) -> Array[Event]
What has happened on this connection since the last call, emptied by it.
pub fn[A] Session::take_received(Self[A]) -> Array[(Level, @frame.Frame)]
Take the frames received since the last call, each with the level it arrived at — where an application layer reads its streams out of.
pub fn[A] Session::tx_bytes(Self[A]) -> Int64
Bytes sent to the peer, the quantity the amplification limit caps.
pub fn[A] Session::validated(Self[A]) -> Bool
Whether the peer's address has been validated (RFC 9000 §8.1), which lifts the amplification limit.
pub fn[A] Session::write(Self[A], UInt64, Bytes, fin? : Bool) -> Unit
Queue data on stream id, and end the stream after it when fin.
pub fn signed(&@spec.Signer, scheme? : Int32) -> (Bytes) -> Bytes
A CertificateVerify body signed over the transcript as RFC 8446 §4.4.3 frames it. This is the seam that keeps a signing key out of this library: a flight takes a function from the transcript hash to a CertificateVerify body, and whoever holds the key builds one with this.
pub fn stateless_reset(Bytes, (Int32) -> Bytes, min? : Int32) -> Bytes
A stateless reset carrying token: a short-header-looking packet of at least min bytes whose last sixteen are the token (RFC 9000 §10.3). The bytes before the token are random, so two resets for the same connection do not look alike.
pub fn version_information(UInt32, ArrayView[UInt32]) -> Param
A version_information parameter (RFC 9368 §3): the version chosen, then the versions the sender would accept, four bytes each. Both sides send one, which is what makes a version negotiation the peer cannot forge: the list arrives under the handshake's own authentication.