moonbitstack/moonquic/conn does not have a README file

    Config

    pub(all) struct Config {
    version : UInt
    idle_timeout : Int64
    close_period : Int64
    max_datagram : Int64
    max_ack_delay : Int64
    granularity : Int64
    initial_max_data : UInt64
    initial_max_stream_data : UInt64
    max_frame : UInt64
    }

    What a server gives each new connection: the QUIC version its long headers carry, 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.

    Config::default

    fn Config::default() -> Config

    QUIC version 1, a 30-second idle timeout, a 3-second closing period, 1200-byte datagrams, a 25-millisecond ACK delay, and a mebibyte of flow-control credit on the connection and on each stream.

    Conn

    A QUIC connection's per-space numbering/ACK state and per-level CRYPTO streams.

    Conn::build_ack

    fn Conn::build_ack(self : Conn, level : Level, ack_delay : UInt64) ->
    Frame
    ?

    Build the ACK frame owed at level, or None if nothing has been received there.

    Conn::crypto_stream

    fn Conn::crypto_stream(self : Conn, level : Level) ->
    Assembler

    The CRYPTO reassembler for level.

    Conn::is_server

    fn Conn::is_server(self : Conn) -> Bool

    Whether this endpoint is the server.

    Conn::new

    fn Conn::new(is_server : Bool) -> Conn

    A fresh connection (client or server) with empty spaces and CRYPTO streams.

    Conn::next_packet_number

    fn Conn::next_packet_number(self : Conn, level : Level) -> Int64

    Allocate the next packet number to send at level.

    Conn::on_ack_received

    fn Conn::on_ack_received(self : Conn, level : Level, largest : Int64) -> Unit

    Record the peer's acknowledgement of up to largest at level.

    Conn::on_crypto_frame

    fn Conn::on_crypto_frame(self : Conn, level : Level, offset : UInt64, data : Bytes) -> Bytes raise
    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.

    Conn::on_packet_received

    fn Conn::on_packet_received(self : Conn, level : Level, pn : Int64, ack_eliciting : Bool) -> Unit

    Record that a packet numbered pn arrived at level; ack_eliciting marks one that must be acknowledged.

    Conn::space

    The packet-number space for level.

    Endpoint

    pub struct Endpoint[A] {
    conns : Map[Bytes, Session[A]]
    cfg : Config
    }

    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.

    Endpoint::close

    fn[A] Endpoint::close(self : Endpoint[A], cid : Bytes, error_code : UInt64, reason : Bytes, now : Int64) -> Unit

    Close the connection cid addresses with error_code and reason, if the server holds one (RFC 9000 §10.2).

    Endpoint::conn

    fn[A] Endpoint::conn(self : Endpoint[A], cid : Bytes) -> Session[A]?

    The connection cid addresses, or None if the server is not holding one.

    Endpoint::conn_ids

    fn[A] Endpoint::conn_ids(self : Endpoint[A]) -> Array[Bytes]

    The connection ids the server is holding.

    Endpoint::count

    fn[A] Endpoint::count(self : Endpoint[A]) -> Int

    How many connections the server is holding.

    Endpoint::new

    fn[A] Endpoint::new(cfg : Config) -> Endpoint[A]

    A server holding no connections, handing cfg to each one it opens.

    Endpoint::poll_out

    fn[A] Endpoint::poll_out(self : Endpoint[A], now : 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.

    Endpoint::recv

    fn[A] Endpoint::recv(self : Endpoint[A], datagram : Bytes, from : A, now : 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.

    Endpoint::tick

    fn[A] Endpoint::tick(self : Endpoint[A], now : 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).

    Kind

    pub(all) enum Kind {
    OriginalDcid
    MaxIdleTimeout
    StatelessResetToken
    MaxUdpPayload
    MaxData
    MaxStreamDataBidiLocal
    MaxStreamDataBidiRemote
    MaxStreamDataUni
    MaxStreamsBidi
    MaxStreamsUni
    AckDelayExponent
    MaxAckDelay
    DisableActiveMigration
    PreferredAddress
    ActiveConnectionIdLimit
    InitialScid
    RetryScid
    MaxDatagramFrameSize
    Other(UInt64)
    } derive(Eq,
    Debug
    )

    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.

    Kind::code

    fn Kind::code(self : Kind) -> UInt64

    The identifier on the wire.

    Kind::equal

    fn Kind::equal(Kind, Kind) -> Bool

    Kind::not_equal

    fn Kind::not_equal(x : Kind, y : Kind) -> Bool

    Kind::of

    fn Kind::of(code : UInt64) -> Kind

    The parameter a wire identifier names.

    Kind::server_only

    fn Kind::server_only(self : Kind) -> 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.

    Kind::to_repr

    Level

    pub(all) enum Level {
    Initial
    Handshake
    Application
    } derive(Eq,
    Debug
    )

    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.

    Level::equal

    fn Level::equal(Level, Level) -> Bool

    Level::not_equal

    fn Level::not_equal(x : Level, y : Level) -> Bool

    Level::to_repr

    Limits

    pub(all) struct Limits {
    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
    } derive(Eq,
    Debug
    )

    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.

    Limits::equal

    fn Limits::equal(Limits, Limits) -> Bool

    Limits::new

    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) -> Limits

    Limits by name, each defaulting to RFC 9000 §18.2's.

    Limits::not_equal

    fn Limits::not_equal(x : Limits, y : Limits) -> Bool

    Limits::params

    fn Limits::params(self : Limits) -> Array[Param]

    The block these limits amount to, leaving out everything still at its default so a handshake carries only what it changes.

    Limits::read

    fn Limits::read(params : ArrayView[Param], base? : Limits) -> Limits

    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.

    Limits::to_repr

    Param

    pub(all) struct Param {
    kind : Kind
    value : Bytes
    } derive(Eq,
    Debug
    )

    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.

    Param::as_int

    fn Param::as_int(self : Param) -> UInt64?

    The integer a varint-valued parameter carries, or None when its value is not exactly one well-formed varint.

    Param::equal

    fn Param::equal(Param, Param) -> Bool

    Param::flag

    fn Param::flag(kind : Kind) -> Param

    A parameter with no value, which is how the flag parameters are carried.

    Param::int

    fn Param::int(kind : Kind, value : UInt64) -> Param

    A parameter whose value is one varint (RFC 9000 §18.2).

    Param::not_equal

    fn Param::not_equal(x : Param, y : Param) -> Bool

    Param::to_repr

    Phase

    pub(all) enum Phase {
    Active
    Closing
    Draining
    } derive(Eq,
    Debug
    )

    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.

    Phase::equal

    fn Phase::equal(Phase, Phase) -> Bool

    Phase::not_equal

    fn Phase::not_equal(x : Phase, y : Phase) -> Bool

    Phase::to_repr

    Sender

    A connection's send state for one packet-number space.

    Sender::advance_past

    fn Sender::advance_past(self : Sender, pn : 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.

    Sender::new

    fn Sender::new(initial_max_data : UInt64, initial_max_stream_data : UInt64, max_datagram_size : Int64, max_ack_delay : Int64, granularity : Int64, max_frame : UInt64) -> Sender

    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.

    Sender::on_ack

    fn Sender::on_ack(self : Sender, frame :
    Frame
    , now : Int64) -> Unit raise

    Process a received ACK frame at now: clear acknowledged packets from the recovery state and re-queue the stream data of any packet the ACK reveals as lost, to be retransmitted by a later poll_send (RFC 9002 §6). Raises on a malformed ACK.

    Sender::on_max_data

    fn Sender::on_max_data(self : Sender, new_max : UInt64) -> Unit

    Raise the connection-wide send limit from a received MAX_DATA frame.

    Sender::on_pto_timeout

    fn Sender::on_pto_timeout(self : Sender, now : 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 oldest outstanding packet's stream data as a probe — a later poll_send puts it back on the wire — and back off the timer for the next arming. Unlike loss detection, this neither declares packets lost nor reduces the congestion window. Returns whether a probe was armed.

    Sender::outstanding

    fn Sender::outstanding(self : Sender) -> Array[Int64]

    The packet numbers still outstanding (sent, not yet acknowledged or declared lost).

    Sender::poll_send

    fn Sender::poll_send(self : Sender, now : Int64) -> (Int64, Array[
    Frame
    ])? raise

    The next packet to send at now, or None when the congestion window is closed or nothing is queued (RFC 9002 §7). Retransmissions go first, then freshly scheduled stream data; the packet is recorded in the recovery state and its stream sends remembered for retransmission.

    Sender::queue_fin

    fn Sender::queue_fin(self : Sender, id : UInt64) -> Unit

    Mark stream id finished.

    Sender::queue_stream

    fn Sender::queue_stream(self : Sender, id : UInt64, bytes : Bytes) -> Unit

    Queue bytes of application data to send on stream id.

    Sender::window

    fn Sender::window(self : Sender) -> Int64

    The current congestion window (bytes).

    Server

    pub struct Server {
    initial_keys :
    Keys

    handshake :
    Handshake

    conn : Conn
    }

    A QUIC server connection mid-handshake: the Initial keys, the packet-number/CRYPTO bookkeeping, and the TLS handshake it is driving.

    Server::client_hello

    fn Server::client_hello(self : Server) -> 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.

    Server::handshake_state

    fn Server::handshake_state(self : Server) ->
    Server

    The current TLS handshake state.

    Server::initial_ack_pending

    fn Server::initial_ack_pending(self : Server) -> Bool

    Whether an ACK is owed in the Initial space.

    Server::negotiate

    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.

    Server::new

    fn Server::new(dcid : Bytes) -> Server

    A server connection for a client whose Destination Connection ID is dcid (the Initial secret and keys derive from it, RFC 9001 §5.2).

    Server::on_frames

    fn Server::on_frames(self : Server, level : Level, frames : Array[
    Frame
    ], pn : Int64) -> Array[
    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.

    Server::on_handshake_frames

    fn Server::on_handshake_frames(self : Server, frames : Array[
    Frame
    ], pn : Int64, client_hs_secret : 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.

    Server::receive_handshake

    fn Server::receive_handshake(self : Server, packet : Bytes, client_hs_keys :
    Keys
    , client_hs_secret : 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.

    Server::receive_initial

    fn Server::receive_initial(self : Server, packet : Bytes) -> Array[
    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.

    Server::send_handshake_flight

    fn Server::send_handshake_flight(self : Server, server_hs_secret : Bytes, encrypted_extensions : Bytes, certificate : Bytes, verify : (Bytes) -> Bytes, out_dcid : Bytes, out_scid : Bytes, pn : 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 throughCertificateVerify) 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.

    Server::send_server_hello

    fn Server::send_server_hello(self : Server, server_hello :
    Server
    , out_dcid : Bytes, out_scid : Bytes, pn : 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.

    Server::transcript_hash

    fn Server::transcript_hash(self : Server) -> Bytes

    The transcript hash over the handshake messages processed so far.

    Session

    pub struct Session[A] {
    peer : A
    cid : Bytes
    peer_cid : Bytes
    core : Server
    sender : Sender
    cfg : Config
    out : Array[Bytes]
    received : Array[(Level,
    Frame
    )]
    rx : Int64
    tx : Int64
    packets : Int
    validated : Bool
    last_rx : Int64
    idle_timeout : Int64
    phase : Phase
    close_at : Int64
    close_frame :
    Frame
    ?
    close_level : Level
    hs_rx :
    Keys
    ?
    hs_rx_secret : Bytes
    hs_tx :
    Keys
    ?
    app_rx :
    Keys
    ?
    app_tx :
    Keys
    ?
    }

    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.

    Session::apply_peer_params

    fn[A] Session::apply_peer_params(self : Session[A], params : 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.

    Session::can_send

    fn[A] Session::can_send(self : Session[A], n : Int) -> 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).

    Session::cid

    fn[A] Session::cid(self : Session[A]) -> Bytes

    The connection id the peer addresses this server by — the table's key.

    Session::close

    fn[A] Session::close(self : Session[A], error_code : UInt64, reason : Bytes, now : Int64) -> 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.

    Session::core

    fn[A] Session::core(self : Session[A]) -> Server

    The handshake state machine underneath, for a caller driving the TLS flights.

    Session::idle_timeout

    fn[A] Session::idle_timeout(self : Session[A]) -> Int64

    The idle timeout in force, in microseconds; zero means none.

    Session::install_app_keys

    fn[A] Session::install_app_keys(self : Session[A], client_secret : Bytes, server_secret : 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.

    Session::install_handshake_keys

    fn[A] Session::install_handshake_keys(self : Session[A], client_secret : Bytes, server_secret : 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.

    Session::largest_acked

    fn[A] Session::largest_acked(self : Session[A], level : Level) -> Int64?

    The largest packet number the peer has acknowledged at level, or None before its first ACK there.

    Session::packets_received

    fn[A] Session::packets_received(self : Session[A]) -> Int

    Datagrams received on this connection.

    Session::peer

    fn[A] Session::peer(self : Session[A]) -> A

    The peer this connection answers.

    Session::pending

    fn[A] Session::pending(self : Session[A]) -> Int

    Datagrams built and waiting to go out — non-zero while the amplification limit or a closed congestion window is holding them back.

    Session::phase

    fn[A] Session::phase(self : Session[A]) -> Phase

    Where this connection is in its lifecycle.

    Session::queue_stream

    fn[A] Session::queue_stream(self : Session[A], id : UInt64, bytes : 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.

    Session::rx_bytes

    fn[A] Session::rx_bytes(self : Session[A]) -> Int64

    Bytes received from the peer, the numerator of the amplification limit.

    Session::send

    fn[A] Session::send(self : Session[A], level : Level, frames : Array[
    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.

    Session::send_level

    fn[A] Session::send_level(self : Session[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.

    Session::take_received

    fn[A] Session::take_received(self : Session[A]) -> Array[(Level,
    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.

    Session::tx_bytes

    fn[A] Session::tx_bytes(self : Session[A]) -> Int64

    Bytes sent to the peer, the quantity the amplification limit caps.

    Session::validated

    fn[A] Session::validated(self : Session[A]) -> Bool

    Whether the peer's address has been validated (RFC 9000 §8.1), which lifts the amplification limit.

    amplification

    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.

    decode

    fn decode(b : BytesView) -> Array[Param]?

    Decode a block, keeping the order and any duplicates so the caller can apply RFC 9000 §7.4's rules itself. None on a truncated parameter.

    encode

    fn encode(params : ArrayView[Param]) -> Bytes

    Encode a block: each parameter as its identifier varint, a length varint, then its value (RFC 9000 §18).

    extension

    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.

    find

    fn find(params : ArrayView[Param], kind : Kind) -> Param?

    The parameter in a block, or None. A repeated parameter is a connection error, so the first one is what counts.

    idle_timeout

    fn idle_timeout(ours : Int64, theirs : 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.

    limits

    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.

    min_datagram

    let min_datagram : Int

    The smallest a datagram carrying an ack-eliciting Initial packet may be (RFC 9000 §14.1).

    of_extensions

    fn of_extensions(extensions : ArrayView[
    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.

    recv_long

    The frames a protected long-header packet carries, and its packet number. None when the tag does not match, which is a packet to drop rather than an error to report.

    recv_short

    The same for a 1-RTT packet, whose connection-id length only the receiver knows.

    seal_long

    fn seal_long(kind :
    Kind
    , version : UInt, dcid : Bytes, scid : Bytes, number : Int64, size : Int, payload : Bytes, keys :
    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).

    send_long

    fn send_long(kind :
    Kind
    , version : UInt, dcid : Bytes, scid : Bytes, number : Int64, size : Int, frames : Array[
    Frame
    ], keys :
    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.

    send_short

    fn send_short(dcid : Bytes, number : Int64, size : Int, frames : Array[
    Frame
    ], keys :
    Keys
    , spin? : Bool, key_phase? : Bool) -> Bytes

    A protected 1-RTT packet carrying frames.

    signed

    fn signed(signer : &
    Signer
    , scheme? : Int) -> ((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.

    Source Files