quic_packet (quic v0.11.0)

View Source

QUIC packet encoding and decoding.

This module handles encoding and decoding of QUIC packets including: - Long header packets (Initial, Handshake, 0-RTT, Retry) - Short header packets (1-RTT)

Packet Header Format

Long Header:

   +-+-+-+-+-+-+-+-+
   |1|1|T T|X X X X|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                         Version (32)                          |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   | DCID Len (8)  |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |               Destination Connection ID (0..160)            ...
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   | SCID Len (8)  |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                 Source Connection ID (0..160)               ...
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Short Header:

   +-+-+-+-+-+-+-+-+
   |0|1|S|R|R|K|P P|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                Destination Connection ID (0..160)           ...
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Summary

Functions

Decode a QUIC packet. DCIDLen is used for short header packets where DCID length is implicit. Returns {ok, Packet, Rest} or {error, Reason}.

Decode a packet number.

Extract the key phase bit from a short header first byte. The key phase bit is bit 2 of the first byte (after header protection removal). Returns 0 or 1.

Encode a long header packet. Type is one of: initial, handshake, zero_rtt, retry Returns the encoded packet header + payload. Note: For Initial packets, Token is required. Note: Packet number and payload should already be encrypted.

Encode a packet number.

Encode a short header (1-RTT) packet with default key phase 0. DCIDLen is the expected DCID length (from connection state). Returns the encoded packet.

Encode a short header (1-RTT) packet with explicit key phase. KeyPhase is 0 or 1, indicating which set of keys was used for encryption. Returns the encoded packet.

Encode a Version Negotiation packet. RFC 9000 Section 17.2.1 - Version Negotiation Packet The server sends this when it receives a packet with an unsupported version. The DCID and SCID are copied from the received packet (swapped). Versions is a list of supported version numbers.

Calculate the minimum number of bytes needed for a packet number.

Types

packet/0

-type packet() ::
          #quic_packet{type :: initial | handshake | zero_rtt | one_rtt | retry,
                       version :: non_neg_integer() | undefined,
                       dcid :: binary(),
                       scid :: binary() | undefined,
                       token :: binary() | undefined,
                       pn :: non_neg_integer() | undefined,
                       payload :: binary() | [term()]}.

packet_type/0

-type packet_type() :: initial | handshake | zero_rtt | one_rtt | retry.

Functions

decode(Bin, DCIDLen)

-spec decode(binary(), non_neg_integer()) -> {ok, packet(), binary()} | {error, term()}.

Decode a QUIC packet. DCIDLen is used for short header packets where DCID length is implicit. Returns {ok, Packet, Rest} or {error, Reason}.

decode_pn(_, _)

-spec decode_pn(binary(), 1..4) -> {non_neg_integer(), binary()}.

Decode a packet number.

decode_short_key_phase(FirstByte)

-spec decode_short_key_phase(non_neg_integer()) -> 0 | 1.

Extract the key phase bit from a short header first byte. The key phase bit is bit 2 of the first byte (after header protection removal). Returns 0 or 1.

encode_long(Type, Version, DCID, SCID, Opts)

-spec encode_long(packet_type(),
                  non_neg_integer(),
                  binary(),
                  binary(),
                  #{token => binary(), pn => non_neg_integer(), payload => binary()}) ->
                     binary().

Encode a long header packet. Type is one of: initial, handshake, zero_rtt, retry Returns the encoded packet header + payload. Note: For Initial packets, Token is required. Note: Packet number and payload should already be encrypted.

encode_pn(PN, _)

-spec encode_pn(non_neg_integer(), 1..4) -> binary().

Encode a packet number.

encode_short(DCID, PN, Payload, SpinBit)

-spec encode_short(binary(), non_neg_integer(), binary(), boolean()) -> binary().

Encode a short header (1-RTT) packet with default key phase 0. DCIDLen is the expected DCID length (from connection state). Returns the encoded packet.

encode_short(DCID, PN, Payload, SpinBit, KeyPhase)

-spec encode_short(binary(), non_neg_integer(), binary(), boolean(), 0 | 1) -> binary().

Encode a short header (1-RTT) packet with explicit key phase. KeyPhase is 0 or 1, indicating which set of keys was used for encryption. Returns the encoded packet.

encode_version_negotiation(DCID, SCID, Versions)

-spec encode_version_negotiation(binary(), binary(), [non_neg_integer()]) -> binary().

Encode a Version Negotiation packet. RFC 9000 Section 17.2.1 - Version Negotiation Packet The server sends this when it receives a packet with an unsupported version. The DCID and SCID are copied from the received packet (swapped). Versions is a list of supported version numbers.

pn_length(PN)

-spec pn_length(non_neg_integer()) -> 1..4.

Calculate the minimum number of bytes needed for a packet number.