If an ECT codepoint set in the IP header is not corrupted by a network device, then a received packet contains either the codepoint sent by the peer or the Congestion Experienced (CE) codepoint set by a network device that is experiencing congestion.
If a QUIC packet sent with an ECT codepoint is newly acknowledged by the peer in an ACK frame without ECN feedback, the endpoint stops setting ECT codepoints in subsequent IP packets, with the expectation that either the network path or the peer no longer supports ECN.
Network devices that corrupt or apply non-standard ECN markings might result in reduced throughput or other undesirable side-effects. To reduce this risk, an endpoint uses the following steps to verify the counts it receives in an ACK frame.
An endpoint could miss acknowledgements for a packet when ACK frames are lost. It is therefore possible for the total increase in ECT(0), ECT(1), and CE counts to be greater than the number of packets acknowledged in an ACK frame. When this happens, and if verification succeeds, the local reference counts MUST be increased to match the counts in the ACK frame.
Processing counts out of order can result in verification failure. An endpoint SHOULD NOT perform this verification if the ACK frame is received in a packet with packet number lower than a previously received ACK frame. Verifying based on ACK frames that arrive out of order can result in disabling ECN unnecessarily.
Upon successful verification, an endpoint continues to set ECT codepoints in subsequent packets with the expectation that the path is ECN-capable.
If verification fails, then the endpoint ceases setting ECT codepoints in subsequent IP packets with the expectation that either the network path or the peer does not support ECN.
If an endpoint sets ECT codepoints on outgoing IP packets and encounters a retransmission timeout due to the absence of acknowledgments from the peer (see [QUIC-RECOVERY]), or if an endpoint has reason to believe that an element on the network path might be corrupting ECN codepoints, the endpoint MAY cease setting ECT codepoints in subsequent packets. Doing so allows the connection to be resilient to network elements that corrupt ECN codepoints in the IP header or drop packets with ECT or CE codepoints in the IP header.
The QUIC packet size includes the QUIC header and protected payload, but not the UDP or IP header.
Clients MUST ensure they send the first Initial packet in a single IP packet. Similarly, the first Initial packet sent after receiving a Retry packet MUST be sent in a single IP packet.
The payload of a UDP datagram carrying the first Initial packet MUST be expanded to at least 1200 bytes, by adding PADDING frames to the Initial packet and/or by combining the Initial packet with a 0-RTT packet (see Section 12.2). Sending a UDP datagram of this size ensures that the network path supports a reasonable Maximum Transmission Unit (MTU), and helps reduce the amplitude of amplification attacks caused by server responses toward an unverified client address, see Section 8.
The datagram containing the first Initial packet from a client MAY exceed 1200 bytes if the client believes that the Path Maximum Transmission Unit (PMTU) supports the size that it chooses.
A server MAY send a CONNECTION_CLOSE frame with error code PROTOCOL_VIOLATION in response to the first Initial packet it receives from a client if the UDP datagram is smaller than 1200 bytes. It MUST NOT send any other frame type in response, or otherwise behave as if any part of the offending packet was processed as valid.
The server MUST also limit the number of bytes it sends before validating the address of the client, see Section 8.
The PMTU is the maximum size of the entire IP packet including the IP header, UDP header, and UDP payload. The UDP payload includes the QUIC packet header, protected payload, and any authentication fields. The PMTU can depend upon the current path characteristics. Therefore, the current largest UDP payload an implementation will send is referred to as the QUIC maximum packet size.
QUIC depends on a PMTU of at least 1280 bytes. This is the IPv6 minimum size [RFC8200] and is also supported by most modern IPv4 networks. All QUIC packets (except for PMTU probe packets) SHOULD be sized to fit within the maximum packet size to avoid the packet being fragmented or dropped [RFC8085].
An endpoint SHOULD use Datagram Packetization Layer PMTU Discovery ([DPLPMTUD]) or implement Path MTU Discovery (PMTUD) [RFC1191] [RFC8201] to determine whether the path to a destination will support a desired message size without fragmentation.
In the absence of these mechanisms, QUIC endpoints SHOULD NOT send IP packets larger than 1280 bytes. Assuming the minimum IP header size, this results in a QUIC maximum packet size of 1232 bytes for IPv6 and 1252 bytes for IPv4. A QUIC implementation MAY be more conservative in computing the QUIC maximum packet size to allow for unknown tunnel overheads or IP header options/extensions.
Each pair of local and remote addresses could have a different PMTU. QUIC implementations that implement any kind of PMTU discovery therefore SHOULD maintain a maximum packet size for each combination of local and remote IP addresses.
If a QUIC endpoint determines that the PMTU between any pair of local and remote IP addresses has fallen below the size needed to support the smallest allowed maximum packet size, it MUST immediately cease sending QUIC packets, except for PMTU probe packets, on the affected path. An endpoint MAY terminate the connection if an alternative path cannot be found.
PMTU discovery [RFC1191] [RFC8201] relies on reception of ICMP messages (e.g., IPv6 Packet Too Big messages) that indicate when a packet is dropped because it is larger than the local router MTU. DPLPMTUD can also optionally use these messages. This use of ICMP messages is potentially vulnerable to off-path attacks that successfully guess the addresses used on the path and reduce the PMTU to a bandwidth-inefficient value.
An endpoint MUST ignore an ICMP message that claims the PMTU has decreased below 1280 bytes.
The requirements for generating ICMP ([RFC1812], [RFC4443]) state that the quoted packet should contain as much of the original packet as possible without exceeding the minimum MTU for the IP version. The size of the quoted packet can actually be smaller, or the information unintelligible, as described in Section 1.1 of [DPLPMTUD].
QUIC endpoints SHOULD validate ICMP messages to protect from off-path injection as specified in [RFC8201] and Section 5.2 of [RFC8085]. This validation SHOULD use the quoted packet supplied in the payload of an ICMP message to associate the message with a corresponding transport connection [DPLPMTUD].
ICMP message validation MUST include matching IP addresses and UDP ports [RFC8085] and, when possible, connection IDs to an active QUIC session.
Further validation can also be provided:
The endpoint SHOULD ignore all ICMP messages that fail validation.
An endpoint MUST NOT increase PMTU based on ICMP messages. Any reduction in the QUIC maximum packet size MAY be provisional until QUIC’s loss detection algorithm determines that the quoted packet has actually been lost.
Section 6.4 of [DPLPMTUD] provides considerations for implementing Datagram Packetization Layer PMTUD (DPLPMTUD) with QUIC.
When implementing the algorithm in Section 5.3 of [DPLPMTUD], the initial value of BASE_PMTU SHOULD be consistent with the minimum QUIC packet size (1232 bytes for IPv6 and 1252 bytes for IPv4).
PING and PADDING frames can be used to generate PMTU probe packets. These frames might not be retransmitted if a probe packet containing them is lost. However, these frames do consume congestion window, which could delay the transmission of subsequent application data.
A PING frame can be included in a PMTU probe to ensure that a valid probe is acknowledged.
The considerations for processing ICMP messages in the previous section also apply if these messages are used by DPLPMTUD.
QUIC versions are identified using a 32-bit unsigned number.
The version 0x00000000 is reserved to represent version negotiation. This version of the specification is identified by the number 0x00000001.
Other versions of QUIC might have different properties to this version. The properties of QUIC that are guaranteed to be consistent across all versions of the protocol are described in [QUIC-INVARIANTS].
Version 0x00000001 of QUIC uses TLS as a cryptographic handshake protocol, as described in [QUIC-TLS].
Versions with the most significant 16 bits of the version number cleared are reserved for use in future IETF consensus documents.
Versions that follow the pattern 0x?a?a?a?a are reserved for use in forcing version negotiation to be exercised. That is, any version number where the low four bits of all bytes is 1010 (in binary). A client or server MAY advertise support for any of these reserved versions.
Reserved version numbers will probably never represent a real protocol; a client MAY use one of these version numbers with the expectation that the server will initiate version negotiation; a server MAY advertise support for one of these versions and can expect that clients ignore the value.
[[RFC editor: please remove the remainder of this section before publication.]]
The version number for the final version of this specification (0x00000001), is reserved for the version of the protocol that is published as an RFC.
Version numbers used to identify IETF drafts are created by adding the draft number to 0xff000000. For example, draft-ietf-quic-transport-13 would be identified as 0xff00000D.
Implementors are encouraged to register version numbers of QUIC that they are using for private experimentation on the GitHub wiki at <https://github.com/quicwg/base-drafts/wiki/QUIC-Versions>.
QUIC packets and frames commonly use a variable-length encoding for non-negative integer values. This encoding ensures that smaller integer values need fewer bytes to encode.
The QUIC variable-length integer encoding reserves the two most significant bits of the first byte to encode the base 2 logarithm of the integer encoding length in bytes. The integer value is encoded on the remaining bits, in network byte order.
This means that integers are encoded on 1, 2, 4, or 8 bytes and can encode 6, 14, 30, or 62 bit values respectively. Table 4 summarizes the encoding properties.
| 2Bit | Length | Usable Bits | Range |
|---|---|---|---|
| 00 | 1 | 6 | 0-63 |
| 01 | 2 | 14 | 0-16383 |
| 10 | 4 | 30 | 0-1073741823 |
| 11 | 8 | 62 | 0-4611686018427387903 |
For example, the eight byte sequence c2 19 7c 5e ff 14 e8 8c (in hexadecimal) decodes to the decimal value<PHONE_NUMBER>41952652; the four byte sequence 9d 7f 3e 7d decodes to 494878333; the two byte sequence 7b bd decodes to 15293; and the single byte 25 decodes to 37 (as does the two byte sequence 40 25).
Error codes (Section 20) and versions (Section 15) are described using integers, but do not use this encoding.
All numeric values are encoded in network byte order (that is, big-endian) and all field sizes are in bits. Hexadecimal notation is used for describing the value of fields.
Packet numbers are integers in the range 0 to 2^62-1 (Section 12.3). When present in long or short packet headers, they are encoded in 1 to 4 bytes. The number of bits required to represent the packet number is reduced by including the least significant bits of the packet number.
The encoded packet number is protected as described in Section 5.4 of [QUIC-TLS].
The sender MUST use a packet number size able to represent more than twice as large a range than the difference between the largest acknowledged packet and packet number being sent. A peer receiving the packet will then correctly decode the packet number, unless the packet is delayed in transit such that it arrives after many higher-numbered packets have been received. An endpoint SHOULD use a large enough packet number encoding to allow the packet number to be recovered even if the packet arrives after packets that are sent afterwards.
As a result, the size of the packet number encoding is at least one bit more than the base-2 logarithm of the number of contiguous unacknowledged packet numbers, including the new packet.
For example, if an endpoint has received an acknowledgment for packet 0xabe8bc, sending a packet with a number of 0xac5c02 requires a packet number encoding with 16 bits or more; whereas the 24-bit packet number encoding is needed to send a packet with a number of 0xace8fe.
At a receiver, protection of the packet number is removed prior to recovering the full packet number. The full packet number is then reconstructed based on the number of significant bits present, the value of those bits, and the largest packet number received on a successfully authenticated packet. Recovering the full packet number is necessary to successfully remove packet protection.
Once header protection is removed, the packet number is decoded by finding the packet number value that is closest to the next expected packet. The next expected packet is the highest received packet number plus one. For example, if the highest successfully authenticated packet had a packet number of 0xa82f30ea, then a packet containing a 16-bit value of 0x9b32 will be decoded as 0xa82f9b32. Example pseudo-code for packet number decoding can be found in Appendix A.
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+ |1|1|T T|X X X X| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Version (32) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |DCIL(4)|SCIL(4)| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Destination Connection ID (0/32..144) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Source Connection ID (0/32..144) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Figure 9: Long Header Packet Format
Long headers are used for packets that are sent prior to the establishment of 1-RTT keys. Once both conditions are met, a sender switches to sending packets using the short header (Section 17.3). The long form allows for special packets - such as the Version Negotiation packet - to be represented in this uniform fixed-length packet format. Packets that use the long header contain the following fields:
In this version of QUIC, the following packet types with the long header are defined:
| Type | Name | Section |
|---|---|---|
| 0x0 | Initial | Section 17.2.2 |
| 0x1 | 0-RTT | Section 17.2.3 |
| 0x2 | Handshake | Section 17.2.4 |
| 0x3 | Retry | Section 17.2.5 |
The header form bit, connection ID lengths byte, Destination and Source Connection ID fields, and Version fields of a long header packet are version-independent. The other fields in the first byte are version-specific. See [QUIC-INVARIANTS] for details on how packets from different versions of QUIC are interpreted.
The interpretation of the fields and the payload are specific to a version and packet type. While type-specific semantics for this version are described in the following sections, several long-header packets in this version of QUIC contain these additional fields:
A Version Negotiation packet is inherently not version-specific. Upon receipt by a client, it will be identified as a Version Negotiation packet based on the Version field having a value of 0.
The Version Negotiation packet is a response to a client packet that contains a version that is not supported by the server, and is only sent by servers.
The layout of a Version Negotiation packet is:
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+ |1| Unused (7) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Version (32) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |DCIL(4)|SCIL(4)| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Destination Connection ID (0/32..144) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Source Connection ID (0/32..144) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Supported Version 1 (32) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | [Supported Version 2 (32)] ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | [Supported Version N (32)] ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Figure 10: Version Negotiation Packet
The value in the Unused field is selected randomly by the server. Clients MUST ignore the value of this field. Servers SHOULD set the most significant bit of this field (0x40) to 1 so that Version Negotiation packets appear to have the Fixed Bit field.
The Version field of a Version Negotiation packet MUST be set to 0x00000000.
The server MUST include the value from the Source Connection ID field of the packet it receives in the Destination Connection ID field. The value for Source Connection ID MUST be copied from the Destination Connection ID of the received packet, which is initially randomly selected by a client. Echoing both connection IDs gives clients some assurance that the server received the packet and that the Version Negotiation packet was not generated by an off-path attacker.
The remainder of the Version Negotiation packet is a list of 32-bit versions which the server supports.
A Version Negotiation packet cannot be explicitly acknowledged in an ACK frame by a client. Receiving another Initial packet implicitly acknowledges a Version Negotiation packet.
The Version Negotiation packet does not include the Packet Number and Length fields present in other packets that use the long header form. Consequently, a Version Negotiation packet consumes an entire UDP datagram.
A server MUST NOT send more than one Version Negotiation packet in response to a single UDP datagram.
See Section 6 for a description of the version negotiation process.
An Initial packet uses long headers with a type value of 0x0. It carries the first CRYPTO frames sent by the client and server to perform key exchange, and carries ACKs in either direction.
+-+-+-+-+-+-+-+-+ |1|1| 0 |R R|P P| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Version (32) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |DCIL(4)|SCIL(4)| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Destination Connection ID (0/32..144) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Source Connection ID (0/32..144) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Token Length (i) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Token (*) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Length (i) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Packet Number (8/16/24/32) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Payload (*) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Figure 11: Initial Packet
The Initial packet contains a long header as well as the Length and Packet Number fields. The first byte contains the Reserved and Packet Number Length bits. Between the SCID and Length fields, there are two additional field specific to the Initial packet.
In order to prevent tampering by version-unaware middleboxes, Initial packets are protected with connection- and version-specific keys (Initial keys) as described in [QUIC-TLS]. This protection does not provide confidentiality or integrity against on-path attackers, but provides some level of protection against off-path attackers.
The client and server use the Initial packet type for any packet that contains an initial cryptographic handshake message. This includes all cases where a new packet containing the initial cryptographic message needs to be created, such as the packets sent after receiving a Retry packet (Section 17.2.5).
A server sends its first Initial packet in response to a client Initial. A server may send multiple Initial packets. The cryptographic key exchange could require multiple round trips or retransmissions of this data.
The payload of an Initial packet includes a CRYPTO frame (or frames) containing a cryptographic handshake message, ACK frames, or both. PADDING and CONNECTION_CLOSE frames are also permitted. An endpoint that receives an Initial packet containing other frames can either discard the packet as spurious or treat it as a connection error.
The first packet sent by a client always includes a CRYPTO frame that contains the entirety of the first cryptographic handshake message. This packet, and the cryptographic handshake message, MUST fit in a single UDP datagram (see Section 7). The first CRYPTO frame sent always begins at an offset of 0 (see Section 7).
Note that if the server sends a HelloRetryRequest, the client will send a second Initial packet. This Initial packet will continue the cryptographic handshake and will contain a CRYPTO frame with an offset matching the size of the CRYPTO frame sent in the first Initial packet. Cryptographic handshake messages subsequent to the first do not need to fit within a single UDP datagram.
A client stops both sending and processing Initial packets when it sends its first Handshake packet. A server stops sending and processing Initial packets when it receives its first Handshake packet. Though packets might still be in flight or awaiting acknowledgment, no further Initial packets need to be exchanged beyond this point. Initial packet protection keys are discarded (see Section 4.10 of [QUIC-TLS]) along with any loss recovery and congestion control state (see Sections <IP_ADDRESS> and 6.9 of [QUIC-RECOVERY]).
Any data in CRYPTO frames is discarded - and no longer retransmitted - when Initial keys are discarded.
A 0-RTT packet uses long headers with a type value of 0x1, followed by the Length and Packet Number fields. The first byte contains the Reserved and Packet Number Length bits. It is used to carry “early” data from the client to the server as part of the first flight, prior to handshake completion. As part of the TLS handshake, the server can accept or reject this early data.
See Section 2.3 of [TLS13] for a discussion of 0-RTT data and its limitations.
+-+-+-+-+-+-+-+-+ |1|1| 1 |R R|P P| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Version (32) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |DCIL(4)|SCIL(4)| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Destination Connection ID (0/32..144) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Source Connection ID (0/32..144) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Length (i) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Packet Number (8/16/24/32) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Payload (*) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
0-RTT Packet
Packet numbers for 0-RTT protected packets use the same space as 1-RTT protected packets.
After a client receives a Retry packet, 0-RTT packets are likely to have been lost or discarded by the server. A client MAY attempt to resend data in 0-RTT packets after it sends a new Initial packet.
A client MUST NOT reset the packet number it uses for 0-RTT packets. The keys used to protect 0-RTT packets will not change as a result of responding to a Retry packet unless the client also regenerates the cryptographic handshake message. Sending packets with the same packet number in that case is likely to compromise the packet protection for all 0-RTT packets because the same key and nonce could be used to protect different content.
Receiving a Retry packet, especially a Retry that changes the connection ID used for subsequent packets, indicates a strong possibility that 0-RTT packets could be lost. A client only receives acknowledgments for its 0-RTT packets once the handshake is complete. Consequently, a server might expect 0-RTT packets to start with a packet number of 0. Therefore, in determining the length of the packet number encoding for 0-RTT packets, a client MUST assume that all packets up to the current packet number are in flight, starting from a packet number of 0. Thus, 0-RTT packets could need to use a longer packet number encoding.
A client SHOULD instead generate a fresh cryptographic handshake message and start packet numbers from 0. This ensures that new 0-RTT packets will not use the same keys, avoiding any risk of key and nonce reuse; this also prevents 0-RTT packets from previous handshake attempts from being accepted as part of the connection.
A Handshake packet uses long headers with a type value of 0x2, followed by the Length and Packet Number fields. The first byte contains the Reserved and Packet Number Length bits. It is used to carry acknowledgments and cryptographic handshake messages from the server and client.
+-+-+-+-+-+-+-+-+ |1|1| 2 |R R|P P| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Version (32) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |DCIL(4)|SCIL(4)| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Destination Connection ID (0/32..144) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Source Connection ID (0/32..144) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Length (i) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Packet Number (8/16/24/32) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Payload (*) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Figure 12: Handshake Protected Packet
Once a client has received a Handshake packet from a server, it uses Handshake packets to send subsequent cryptographic handshake messages and acknowledgments to the server.
The Destination Connection ID field in a Handshake packet contains a connection ID that is chosen by the recipient of the packet; the Source Connection ID includes the connection ID that the sender of the packet wishes to use (see Section 7.2).
Handshake packets are their own packet number space, and thus the first Handshake packet sent by a server contains a packet number of 0.
The payload of this packet contains CRYPTO frames and could contain PADDING, or ACK frames. Handshake packets MAY contain CONNECTION_CLOSE frames. Endpoints MUST treat receipt of Handshake packets with other frames as a connection error.
Like Initial packets (see Section <IP_ADDRESS>), data in CRYPTO frames at the Handshake encryption level is discarded - and no longer retransmitted - when Handshake protection keys are discarded.
A Retry packet uses a long packet header with a type value of 0x3. It carries an address validation token created by the server. It is used by a server that wishes to perform a stateless retry (see Section 8.1).
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+ |1|1| 3 | ODCIL | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Version (32) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |DCIL(4)|SCIL(4)| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Destination Connection ID (0/32..144) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Source Connection ID (0/32..144) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Original Destination Connection ID (0/32..144) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Retry Token (*) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Figure 13: Retry Packet
A Retry packet (shown in Figure 13) does not contain any protected fields. In addition to the long header, it contains these additional fields:
The server populates the Destination Connection ID with the connection ID that the client included in the Source Connection ID of the Initial packet.
The server includes a connection ID of its choice in the Source Connection ID field. This value MUST not be equal to the Destination Connection ID field of the packet sent by the client. The client MUST use this connection ID in the Destination Connection ID of subsequent packets that it sends.
A server MAY send Retry packets in response to Initial and 0-RTT packets. A server can either discard or buffer 0-RTT packets that it receives. A server can send multiple Retry packets as it receives Initial or 0-RTT packets. A server MUST NOT send more than one Retry packet in response to a single UDP datagram.
A client MUST accept and process at most one Retry packet for each connection attempt. After the client has received and processed an Initial or Retry packet from the server, it MUST discard any subsequent Retry packets that it receives.
Clients MUST discard Retry packets that contain an Original Destination Connection ID field that does not match the Destination Connection ID from its Initial packet. This prevents an off-path attacker from injecting a Retry packet.
The client responds to a Retry packet with an Initial packet that includes the provided Retry Token to continue connection establishment.
A client sets the Destination Connection ID field of this Initial packet to the value from the Source Connection ID in the Retry packet. Changing Destination Connection ID also results in a change to the keys used to protect the Initial packet. It also sets the Token field to the token provided in the Retry. The client MUST NOT change the Source Connection ID because the server could include the connection ID as part of its token validation logic (see Section 8.1.3).
The next Initial packet from the client uses the connection ID and token values from the Retry packet (see Section 7.2). Aside from this, the Initial packet sent by the client is subject to the same restrictions as the first Initial packet. A client can either reuse the cryptographic handshake message or construct a new one at its discretion.
A client MAY attempt 0-RTT after receiving a Retry packet by sending 0-RTT packets to the connection ID provided by the server. A client that sends additional 0-RTT packets without constructing a new cryptographic handshake message MUST NOT reset the packet number to 0 after a Retry packet, see Section 17.2.3.
A server acknowledges the use of a Retry packet for a connection using the original_connection_id transport parameter (see Section 18.1). If the server sends a Retry packet, it MUST include the value of the Original Destination Connection ID field of the Retry packet (that is, the Destination Connection ID field from the client’s first Initial packet) in the transport parameter.
If the client received and processed a Retry packet, it MUST validate that the original_connection_id transport parameter is present and correct; otherwise, it MUST validate that the transport parameter is absent. A client MUST treat a failed validation as a connection error of type TRANSPORT_PARAMETER_ERROR.
A Retry packet does not include a packet number and cannot be explicitly acknowledged by a client.
This version of QUIC defines a single packet type which uses the short packet header.
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+ |0|1|S|R|R|K|P P| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Destination Connection ID (0..144) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Packet Number (8/16/24/32) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Protected Payload (*) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Figure 14: Short Header Packet Format
The short header can be used after the version and 1-RTT keys are negotiated. Packets that use the short header contain the following fields:
The header form bit and the connection ID field of a short header packet are version-independent. The remaining fields are specific to the selected QUIC version. See [QUIC-INVARIANTS] for details on how packets from different versions of QUIC are interpreted.
The latency spin bit enables passive latency monitoring from observation points on the network path throughout the duration of a connection. The spin bit is only present in the short packet header, since it is possible to measure the initial RTT of a connection by observing the handshake. Therefore, the spin bit is available after version negotiation and connection establishment are completed. On-path measurement and use of the latency spin bit is further discussed in [QUIC-MANAGEABILITY].
The spin bit is an OPTIONAL feature of QUIC. A QUIC stack that chooses to support the spin bit MUST implement it as specified in this section.
Each endpoint unilaterally decides if the spin bit is enabled or disabled for a connection. Implementations MUST allow administrators of clients and servers to disable the spin bit either globally or on a per-connection basis. Even when the spin bit is not disabled by the administrator, implementations MUST disable the spin bit for a given connection with a certain likelihood. The random selection process SHOULD be designed such that on average the spin bit is disabled for at least one eighth of connections. The selection process performed at the beginning of the connection SHOULD be applied for all paths used by the connection.
In case multiple connections share the same five-tuple, that is, have the same source and destination IP address and UDP ports, endpoints should try to co-ordinate across all connections to ensure a clear signal to any on-path measurement points.
When the spin bit is disabled, endpoints MAY set the spin bit to any value, and MUST ignore any incoming value. It is RECOMMENDED that endpoints set the spin bit to a random value either chosen independently for each packet or chosen independently for each connection ID.
If the spin bit is enabled for the connection, the endpoint maintains a spin value and sets the spin bit in the short header to the currently stored value when a packet with a short header is sent out. The spin value is initialized to 0 in the endpoint at connection start. Each endpoint also remembers the highest packet number seen from its peer on the connection.
When a server receives a short header packet that increments the highest packet number seen by the server from the client, it sets the spin value to be equal to the spin bit in the received packet.
When a client receives a short header packet that increments the highest packet number seen by the client from the server, it sets the spin value to the inverse of the spin bit in the received packet.
An endpoint resets its spin value to zero when sending the first packet of a given connection with a new connection ID. This reduces the risk that transient spin bit state can be used to link flows across connection migration or ID change.
With this mechanism, the server reflects the spin value received, while the client ‘spins’ it after one RTT. On-path observers can measure the time between two spin bit toggle events to estimate the end-to-end RTT of a connection.
The format of the transport parameters is the TransportParameters struct from Figure 15. This is described using the presentation language from Section 3 of [TLS13].
enum { original_connection_id(0), idle_timeout(1), stateless_reset_token(2), max_packet_size(3), initial_max_data(4), initial_max_stream_data_bidi_local(5), initial_max_stream_data_bidi_remote(6), initial_max_stream_data_uni(7), initial_max_streams_bidi(8), initial_max_streams_uni(9), ack_delay_exponent(10), max_ack_delay(11), disable_migration(12), preferred_address(13), (65535) } TransportParameterId; struct { TransportParameterId parameter; opaque value<0..2^16-1>; } TransportParameter; TransportParameter TransportParameters<0..2^16-1>;
Figure 15: Definition of TransportParameters
The extension_data field of the quic_transport_parameters extension defined in [QUIC-TLS] contains a TransportParameters value. TLS encoding rules are therefore used to describe the encoding of transport parameters.
QUIC encodes transport parameters into a sequence of bytes, which are then included in the cryptographic handshake.
This section details the transport parameters defined in this document.
Many transport parameters listed here have integer values. Those transport parameters that are identified as integers use a variable-length integer encoding (see Section 16) and have a default value of 0 if the transport parameter is absent, unless otherwise stated.
The following transport parameters are defined:
struct { opaque ipv4Address[4]; uint16 ipv4Port; opaque ipv6Address[16]; uint16 ipv6Port; opaque connectionId<0..18>; opaque statelessResetToken[16]; } PreferredAddress;
Figure 16: Preferred Address format
If present, transport parameters that set initial flow control limits (initial_max_stream_data_bidi_local, initial_max_stream_data_bidi_remote, and initial_max_stream_data_uni) are equivalent to sending a MAX_STREAM_DATA frame (Section 19.10) on every stream of the corresponding type immediately after opening. If the transport parameter is absent, streams of that type start with a flow control limit of 0.
A client MUST NOT include an original connection ID, a stateless reset token, or a preferred address. A server MUST treat receipt of any of these transport parameters as a connection error of type TRANSPORT_PARAMETER_ERROR.
As described in Section 12.4, packets contain one or more frames. This section describes the format and semantics of the core QUIC frame types.
The PADDING frame (type=0x00) has no semantic value. PADDING frames can be used to increase the size of a packet. Padding can be used to increase an initial client packet to the minimum required size, or to provide protection against traffic analysis for protected packets.
A PADDING frame has no content. That is, a PADDING frame consists of the single byte that identifies the frame as a PADDING frame.
Endpoints can use PING frames (type=0x01) to verify that their peers are still alive or to check reachability to the peer. The PING frame contains no additional fields.
The receiver of a PING frame simply needs to acknowledge the packet containing this frame.
The PING frame can be used to keep a connection alive when an application or application protocol wishes to prevent the connection from timing out. An application protocol SHOULD provide guidance about the conditions under which generating a PING is recommended. This guidance SHOULD indicate whether it is the client or the server that is expected to send the PING. Having both endpoints send PING frames without coordination can produce an excessive number of packets and poor performance.
A connection will time out if no packets are sent or received for a period longer than the time specified in the idle_timeout transport parameter (see Section 10). However, state in middleboxes might time out earlier than that. Though REQ-5 in [RFC4787] recommends a 2 minute timeout interval, experience shows that sending packets every 15 to 30 seconds is necessary to prevent the majority of middleboxes from losing state for UDP flows.
Receivers send ACK frames (types 0x02 and 0x03) to inform senders of packets they have received and processed. The ACK frame contains one or more ACK Ranges. ACK Ranges identify acknowledged packets. If the frame type is 0x03, ACK frames also contain the sum of QUIC packets with associated ECN marks received on the connection up until this point. QUIC implementations MUST properly handle both types and, if they have enabled ECN for packets they send, they SHOULD use the information in the ECN section to manage their congestion state.
QUIC acknowledgements are irrevocable. Once acknowledged, a packet remains acknowledged, even if it does not appear in a future ACK frame. This is unlike TCP SACKs ([RFC2018]).
It is expected that a sender will reuse the same packet number across different packet number spaces. ACK frames only acknowledge the packet numbers that were transmitted by the sender in the same packet number space of the packet that the ACK was received in.
Version Negotiation and Retry packets cannot be acknowledged because they do not contain a packet number. Rather than relying on ACK frames, these packets are implicitly acknowledged by the next Initial packet sent by the client.
An ACK frame is as follows:
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Largest Acknowledged (i) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ACK Delay (i) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ACK Range Count (i) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | First ACK Range (i) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ACK Ranges (*) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | [ECN Counts] ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Figure 17: ACK Frame Format
ACK frames contain the following fields:
The ACK Ranges field consists of alternating Gap and ACK Range values in descending packet number order. The number of Gap and ACK Range values is determined by the ACK Range Count field; one of each value is present for each value in the ACK Range Count field.
ACK Ranges are structured as follows:
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | [Gap (i)] ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | [ACK Range (i)] ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | [Gap (i)] ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | [ACK Range (i)] ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | [Gap (i)] ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | [ACK Range (i)] ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Figure 18: ACK Ranges
The fields that form the ACK Ranges are:
Gap and ACK Range value use a relative integer encoding for efficiency. Though each encoded value is positive, the values are subtracted, so that each ACK Range describes progressively lower-numbered packets.
Each ACK Range acknowledges a contiguous range of packets by indicating the number of acknowledged packets that precede the largest packet number in that range. A value of zero indicates that only the largest packet number is acknowledged. Larger ACK Range values indicate a larger range, with corresponding lower values for the smallest packet number in the range. Thus, given a largest packet number for the range, the smallest value is determined by the formula:
smallest = largest - ack_range
An ACK Range acknowledges all packets between the smallest packet number and the largest, inclusive.
The largest value for an ACK Range is determined by cumulatively subtracting the size of all preceding ACK Ranges and Gaps.
Each Gap indicates a range of packets that are not being acknowledged. The number of packets in the gap is one higher than the encoded value of the Gap field.
The value of the Gap field establishes the largest packet number value for the subsequent ACK Range using the following formula:
largest = previous_smallest - gap - 2
If any computed packet number is negative, an endpoint MUST generate a connection error of type FRAME_ENCODING_ERROR indicating an error in an ACK frame.
The ACK frame uses the least significant bit (that is, type 0x03) to indicate ECN feedback and report receipt of QUIC packets with associated ECN codepoints of ECT(0), ECT(1), or CE in the packet’s IP header. ECN Counts are only present when the ACK frame type is 0x03.
ECN Counts are only parsed when the ACK frame type is 0x03. There are 3 ECN counts, as follows:
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ECT(0) Count (i) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ECT(1) Count (i) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ECN-CE Count (i) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
The three ECN Counts are:
ECN counts are maintained separately for each packet number space.
An endpoint uses a RESET_STREAM frame (type=0x04) to abruptly terminate the sending part of a stream.
After sending a RESET_STREAM, an endpoint ceases transmission and retransmission of STREAM frames on the identified stream. A receiver of RESET_STREAM can discard any data that it already received on that stream.
An endpoint that receives a RESET_STREAM frame for a send-only stream MUST terminate the connection with error STREAM_STATE_ERROR.
The RESET_STREAM frame is as follows:
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Stream ID (i) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Application Error Code (16) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Final Size (i) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
RESET_STREAM frames contain the following fields:
An endpoint uses a STOP_SENDING frame (type=0x05) to communicate that incoming data is being discarded on receipt at application request. STOP_SENDING requests that a peer cease transmission on a stream.
A STOP_SENDING frame can be sent for streams in the Recv or Size Known states (see Section 3.1). Receiving a STOP_SENDING frame for a locally-initiated stream that has not yet been created MUST be treated as a connection error of type STREAM_STATE_ERROR. An endpoint that receives a STOP_SENDING frame for a receive-only stream MUST terminate the connection with error STREAM_STATE_ERROR.
The STOP_SENDING frame is as follows:
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Stream ID (i) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Application Error Code (16) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
STOP_SENDING frames contain the following fields:
The CRYPTO frame (type=0x06) is used to transmit cryptographic handshake messages. It can be sent in all packet types. The CRYPTO frame offers the cryptographic protocol an in-order stream of bytes. CRYPTO frames are functionally identical to STREAM frames, except that they do not bear a stream identifier; they are not flow controlled; and they do not carry markers for optional offset, optional length, and the end of the stream.
The CRYPTO frame is as follows:
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Offset (i) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Length (i) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Crypto Data (*) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Figure 19: CRYPTO Frame Format
CRYPTO frames contain the following fields:
There is a separate flow of cryptographic handshake data in each encryption level, each of which starts at an offset of 0. This implies that each encryption level is treated as a separate CRYPTO stream of data.
Unlike STREAM frames, which include a Stream ID indicating to which stream the data belongs, the CRYPTO frame carries data for a single stream per encryption level. The stream does not have an explicit end, so CRYPTO frames do not have a FIN bit.
A server sends a NEW_TOKEN frame (type=0x07) to provide the client with a token to send in the header of an Initial packet for a future connection.
The NEW_TOKEN frame is as follows:
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Token Length (i) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Token (*) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
NEW_TOKEN frames contain the following fields:
STREAM frames implicitly create a stream and carry stream data. The STREAM frame takes the form 0b00001XXX (or the set of values from 0x08 to 0x0f). The value of the three low-order bits of the frame type determine the fields that are present in the frame.
An endpoint that receives a STREAM frame for a send-only stream MUST terminate the connection with error STREAM_STATE_ERROR.
The STREAM frames are as follows:
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Stream ID (i) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | [Offset (i)] ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | [Length (i)] ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Stream Data (*) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Figure 20: STREAM Frame Format
STREAM frames contain the following fields:
When a Stream Data field has a length of 0, the offset in the STREAM frame is the offset of the next byte that would be sent.
The first byte in the stream has an offset of 0. The largest offset delivered on a stream - the sum of the offset and data length - cannot exceed 2^62-1, as it is not possible to provide flow control credit for that data. Receipt of a frame that exceeds this limit will be treated as a connection error of type FLOW_CONTROL_ERROR.
The MAX_DATA frame (type=0x10) is used in flow control to inform the peer of the maximum amount of data that can be sent on the connection as a whole.
The MAX_DATA frame is as follows:
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Maximum Data (i) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
MAX_DATA frames contain the following fields:
All data sent in STREAM frames counts toward this limit. The sum of the largest received offsets on all streams - including streams in terminal states - MUST NOT exceed the value advertised by a receiver. An endpoint MUST terminate a connection with a FLOW_CONTROL_ERROR error if it receives more data than the maximum data value that it has sent, unless this is a result of a change in the initial limits (see Section 7.3.1).
The MAX_STREAM_DATA frame (type=0x11) is used in flow control to inform a peer of the maximum amount of data that can be sent on a stream.
A MAX_STREAM_DATA frame can be sent for streams in the Recv state (see Section 3.1). Receiving a MAX_STREAM_DATA frame for a locally-initiated stream that has not yet been created MUST be treated as a connection error of type STREAM_STATE_ERROR. An endpoint that receives a MAX_STREAM_DATA frame for a receive-only stream MUST terminate the connection with error STREAM_STATE_ERROR.
The MAX_STREAM_DATA frame is as follows:
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Stream ID (i) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Maximum Stream Data (i) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
MAX_STREAM_DATA frames contain the following fields:
When counting data toward this limit, an endpoint accounts for the largest received offset of data that is sent or received on the stream. Loss or reordering can mean that the largest received offset on a stream can be greater than the total size of data received on that stream. Receiving STREAM frames might not increase the largest received offset.
The data sent on a stream MUST NOT exceed the largest maximum stream data value advertised by the receiver. An endpoint MUST terminate a connection with a FLOW_CONTROL_ERROR error if it receives more data than the largest maximum stream data that it has sent for the affected stream, unless this is a result of a change in the initial limits (see Section 7.3.1).
The MAX_STREAMS frames (type=0x12 and 0x13) inform the peer of the cumulative number of streams of a given type it is permitted to open. A MAX_STREAMS frame with a type of 0x12 applies to bidirectional streams, and a MAX_STREAMS frame with a type of 0x13 applies to unidirectional streams.
The MAX_STREAMS frames are as follows:
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Maximum Streams (i) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
MAX_STREAMS frames contain the following fields:
Loss or reordering can cause a MAX_STREAMS frame to be received which states a lower stream limit than an endpoint has previously received. MAX_STREAMS frames which do not increase the stream limit MUST be ignored.
An endpoint MUST NOT open more streams than permitted by the current stream limit set by its peer. For instance, a server that receives a unidirectional stream limit of 3 is permitted to open stream 3, 7, and 11, but not stream 15. An endpoint MUST terminate a connection with a STREAM_LIMIT_ERROR error if a peer opens more streams than was permitted.
Note that these frames (and the corresponding transport parameters) do not describe the number of streams that can be opened concurrently. The limit includes streams that have been closed as well as those that are open.
A sender SHOULD send a DATA_BLOCKED frame (type=0x14) when it wishes to send data, but is unable to due to connection-level flow control (see Section 4). DATA_BLOCKED frames can be used as input to tuning of flow control algorithms (see Section 4.2).
The DATA_BLOCKED frame is as follows:
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Data Limit (i) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
DATA_BLOCKED frames contain the following fields:
A sender SHOULD send a STREAM_DATA_BLOCKED frame (type=0x15) when it wishes to send data, but is unable to due to stream-level flow control. This frame is analogous to DATA_BLOCKED (Section 19.12).
An endpoint that receives a STREAM_DATA_BLOCKED frame for a send-only stream MUST terminate the connection with error STREAM_STATE_ERROR.
The STREAM_DATA_BLOCKED frame is as follows:
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Stream ID (i) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Stream Data Limit (i) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
STREAM_DATA_BLOCKED frames contain the following fields:
A sender SHOULD send a STREAMS_BLOCKED frame (type=0x16 or 0x17) when it wishes to open a stream, but is unable to due to the maximum stream limit set by its peer (see Section 19.11). A STREAMS_BLOCKED frame of type 0x16 is used to indicate reaching the bidirectional stream limit, and a STREAMS_BLOCKED frame of type 0x17 indicates reaching the unidirectional stream limit.
A STREAMS_BLOCKED frame does not open the stream, but informs the peer that a new stream was needed and the stream limit prevented the creation of the stream.
The STREAMS_BLOCKED frames are as follows:
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Stream Limit (i) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
STREAMS_BLOCKED frames contain the following fields:
An endpoint sends a NEW_CONNECTION_ID frame (type=0x18) to provide its peer with alternative connection IDs that can be used to break linkability when migrating connections (see Section 9.5).
The NEW_CONNECTION_ID frame is as follows:
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Sequence Number (i) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Length (8) | | +-+-+-+-+-+-+-+-+ Connection ID (32..144) + | ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | + + | | + Stateless Reset Token (128) + | | + + | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
NEW_CONNECTION_ID frames contain the following fields:
An endpoint MUST NOT send this frame if it currently requires that its peer send packets with a zero-length Destination Connection ID. Changing the length of a connection ID to or from zero-length makes it difficult to identify when the value of the connection ID changed. An endpoint that is sending packets with a zero-length Destination Connection ID MUST treat receipt of a NEW_CONNECTION_ID frame as a connection error of type PROTOCOL_VIOLATION.
Transmission errors, timeouts and retransmissions might cause the same NEW_CONNECTION_ID frame to be received multiple times. Receipt of the same frame multiple times MUST NOT be treated as a connection error. A receiver can use the sequence number supplied in the NEW_CONNECTION_ID frame to identify new connection IDs from old ones.
If an endpoint receives a NEW_CONNECTION_ID frame that repeats a previously issued connection ID with a different Stateless Reset Token or a different sequence number, or if a sequence number is used for different connection IDs, the endpoint MAY treat that receipt as a connection error of type PROTOCOL_VIOLATION.
An endpoint sends a RETIRE_CONNECTION_ID frame (type=0x19) to indicate that it will no longer use a connection ID that was issued by its peer. This may include the connection ID provided during the handshake. Sending a RETIRE_CONNECTION_ID frame also serves as a request to the peer to send additional connection IDs for future use (see Section 5.1). New connection IDs can be delivered to a peer using the NEW_CONNECTION_ID frame (Section 19.15).
Retiring a connection ID invalidates the stateless reset token associated with that connection ID.
The RETIRE_CONNECTION_ID frame is as follows:
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Sequence Number (i) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
RETIRE_CONNECTION_ID frames contain the following fields:
Receipt of a RETIRE_CONNECTION_ID frame containing a sequence number greater than any previously sent to the peer MAY be treated as a connection error of type PROTOCOL_VIOLATION.
The sequence number specified in a RETIRE_CONNECTION_ID frame MUST NOT refer to the Destination Connection ID field of the packet in which the frame is contained. The peer MAY treat this as a connection error of type PROTOCOL_VIOLATION.
An endpoint cannot send this frame if it was provided with a zero-length connection ID by its peer. An endpoint that provides a zero-length connection ID MUST treat receipt of a RETIRE_CONNECTION_ID frame as a connection error of type PROTOCOL_VIOLATION.
Endpoints can use PATH_CHALLENGE frames (type=0x1a) to check reachability to the peer and for path validation during connection migration.
The PATH_CHALLENGE frames are as follows:
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | + Data (64) + | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
PATH_CHALLENGE frames contain the following fields:
A PATH_CHALLENGE frame containing 8 bytes that are hard to guess is sufficient to ensure that it is easier to receive the packet than it is to guess the value correctly.
The recipient of this frame MUST generate a PATH_RESPONSE frame (Section 19.18) containing the same Data.
The PATH_RESPONSE frame (type=0x1b) is sent in response to a PATH_CHALLENGE frame. Its format is identical to the PATH_CHALLENGE frame (Section 19.17).
If the content of a PATH_RESPONSE frame does not match the content of a PATH_CHALLENGE frame previously sent by the endpoint, the endpoint MAY generate a connection error of type PROTOCOL_VIOLATION.
An endpoint sends a CONNECTION_CLOSE frame (type=0x1c or 0x1d) to notify its peer that the connection is being closed. The CONNECTION_CLOSE with a frame type of 0x1c is used to signal errors at only the QUIC layer, or the absence of errors (with the NO_ERROR code). The CONNECTION_CLOSE frame with a type of 0x1d is used to signal an error with the application that uses QUIC.
If there are open streams that haven’t been explicitly closed, they are implicitly closed when the connection is closed.
The CONNECTION_CLOSE frames are as follows:
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Error Code (16) | [ Frame Type (i) ] ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Reason Phrase Length (i) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Reason Phrase (*) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
CONNECTION_CLOSE frames contain the following fields:
QUIC frames do not use a self-describing encoding. An endpoint therefore needs to understand the syntax of all frames before it can successfully process a packet. This allows for efficient encoding of frames, but it means that an endpoint cannot send a frame of a type that is unknown to its peer.
An extension to QUIC that wishes to use a new type of frame MUST first ensure that a peer is able to understand the frame. An endpoint can use a transport parameter to signal its willingness to receive one or more extension frame types with the one transport parameter.
Extension frames MUST be congestion controlled and MUST cause an ACK frame to be sent. The exception is extension frames that replace or supplement the ACK frame. Extension frames are not included in flow control unless specified in the extension.
An IANA registry is used to manage the assignment of frame types, see Section 22.2.
QUIC error codes are 16-bit unsigned integers.
This section lists the defined QUIC transport error codes that may be used in a CONNECTION_CLOSE frame. These errors apply to the entire connection.
See Section 22.3 for details of registering new error codes.
Application protocol error codes are 16-bit unsigned integers, but the management of application error codes are left to application protocols. Application protocol error codes are used for the RESET_STREAM frame (Section 19.4), the STOP_SENDING frame (Section 19.5), and the CONNECTION_CLOSE frame with a type of 0x1d (Section 19.19).
As an encrypted and authenticated transport QUIC provides a range of protections against denial of service. Once the cryptographic handshake is complete, QUIC endpoints discard most packets that are not authenticated, greatly limiting the ability of an attacker to interfere with existing connections.
Once a connection is established QUIC endpoints might accept some unauthenticated ICMP packets (see Section 14.2), but the use of these packets is extremely limited. The only other type of packet that an endpoint might accept is a stateless reset (Section 10.4) which relies on the token being kept secret until it is used.
During the creation of a connection, QUIC only provides protection against attack from off the network path. All QUIC packets contain proof that the recipient saw a preceding packet from its peer.
The first mechanism used is the source and destination connection IDs, which are required to match those set by a peer. Except for an Initial and stateless reset packets, an endpoint only accepts packets that include a destination connection that matches a connection ID the endpoint previously chose. This is the only protection offered for Version Negotiation packets.
The destination connection ID in an Initial packet is selected by a client to be unpredictable, which serves an additional purpose. The packets that carry the cryptographic handshake are protected with a key that is derived from this connection ID and salt specific to the QUIC version. This allows endpoints to use the same process for authenticating packets that they receive as they use after the cryptographic handshake completes. Packets that cannot be authenticated are discarded. Protecting packets in this fashion provides a strong assurance that the sender of the packet saw the Initial packet and understood it.
These protections are not intended to be effective against an attacker that is able to receive QUIC packets prior to the connection being established. Such an attacker can potentially send packets that will be accepted by QUIC endpoints. This version of QUIC attempts to detect this sort of attack, but it expects that endpoints will fail to establish a connection rather than recovering. For the most part, the cryptographic handshake protocol [QUIC-TLS] is responsible for detecting tampering during the handshake.
Endpoints are permitted to use other methods to detect and attempt to recover from interference with the handshake. Invalid packets may be identified and discarded using other methods, but no specific method is mandated in this document.
An attacker might be able to receive an address validation token (Section 8) from a server and then release the IP address it used to acquire that token. At a later time, the attacker may initiate a 0-RTT connection with a server by spoofing this same address, which might now address a different (victim) endpoint. The attacker can thus potentially cause the server to send an initial congestion window’s worth of data towards the victim.
Servers SHOULD provide mitigations for this attack by limiting the usage and lifetime of address validation tokens (see Section 8.1.2).
An endpoint that acknowledges packets it has not received might cause a congestion controller to permit sending at rates beyond what the network supports. An endpoint MAY skip packet numbers when sending packets to detect this behavior. An endpoint can then immediately close the connection with a connection error of type PROTOCOL_VIOLATION (see Section 10.3).
The attacks commonly known as Slowloris [SLOWLORIS] try to keep many connections to the target endpoint open and hold them open as long as possible. These attacks can be executed against a QUIC endpoint by generating the minimum amount of activity necessary to avoid being closed for inactivity. This might involve sending small amounts of data, gradually opening flow control windows in order to control the sender rate, or manufacturing ACK frames that simulate a high loss rate.
QUIC deployments SHOULD provide mitigations for the Slowloris attacks, such as increasing the maximum number of clients the server will allow, limiting the number of connections a single IP address is allowed to make, imposing restrictions on the minimum transfer speed a connection is allowed to have, and restricting the length of time an endpoint is allowed to stay connected.
An adversarial sender might intentionally send fragments of stream data in order to cause disproportionate receive buffer memory commitment and/or creation of a large and inefficient data structure.
An adversarial receiver might intentionally not acknowledge packets containing stream data in order to force the sender to store the unacknowledged stream data for retransmission.
The attack on receivers is mitigated if flow control windows correspond to available memory. However, some receivers will over-commit memory and advertise flow control offsets in the aggregate that exceed actual available memory. The over-commitment strategy can lead to better performance when endpoints are well behaved, but renders endpoints vulnerable to the stream fragmentation attack.
QUIC deployments SHOULD provide mitigations against stream fragmentation attacks. Mitigations could consist of avoiding over-committing memory, limiting the size of tracking data structures, delaying reassembly of STREAM frames, implementing heuristics based on the age and duration of reassembly holes, or some combination.
An adversarial endpoint can open lots of streams, exhausting state on an endpoint. The adversarial endpoint could repeat the process on a large number of connections, in a manner similar to SYN flooding attacks in TCP.
Normally, clients will open streams sequentially, as explained in Section 2.1. However, when several streams are initiated at short intervals, transmission error may cause STREAM DATA frames opening streams to be received out of sequence. A receiver is obligated to open intervening streams if a higher-numbered stream ID is received. Thus, on a new connection, opening stream 2000001 opens 1 million streams, as required by the specification.
The number of active streams is limited by the initial_max_streams_bidi and initial_max_streams_uni transport parameters, as explained in Section 4.5. If chosen judiciously, these limits mitigate the effect of the stream commitment attack. However, setting the limit too low could affect performance when applications expect to open large number of streams.
An on-path attacker could manipulate the value of ECN codepoints in the IP header to influence the sender’s rate. [RFC3168] discusses manipulations and their effects in more detail.
An on-the-side attacker can duplicate and send packets with modified ECN codepoints to affect the sender’s rate. If duplicate packets are discarded by a receiver, an off-path attacker will need to race the duplicate packet against the original to be successful in this attack. Therefore, QUIC receivers ignore ECN codepoints set in duplicate packets (see Section 13.3).
Stateless resets create a possible denial of service attack analogous to a TCP reset injection. This attack is possible if an attacker is able to cause a stateless reset token to be generated for a connection with a selected connection ID. An attacker that can cause this token to be generated can reset an active connection with the same connection ID.
If a packet can be routed to different instances that share a static key, for example by changing an IP address or port, then an attacker can cause the server to send a stateless reset. To defend against this style of denial service, endpoints that share a static key for stateless reset (see Section 10.4.2) MUST be arranged so that packets with a given connection ID always arrive at an instance that has connection state, unless that connection is no longer active.
In the case of a cluster that uses dynamic load balancing, it’s possible that a change in load balancer configuration could happen while an active instance retains connection state; even if an instance retains connection state, the change in routing and resulting stateless reset will result in the connection being terminated. If there is no chance in the packet being routed to the correct instance, it is better to send a stateless reset than wait for connections to time out. However, this is acceptable only if the routing cannot be influenced by an attacker.
This document defines QUIC Version Negotiation packets Section 6, which can be used to negotiate the QUIC version used between two endpoints. However, this document does not specify how this negotiation will be performed between this version and subsequent future versions. In particular, Version Negotiation packets do not contain any mechanism to prevent version downgrade attacks. Future versions of QUIC that use Version Negotiation packets MUST define a mechanism that is robust against version downgrade attacks.
IANA [SHALL add/has added] a registry for “QUIC Transport Parameters” under a “QUIC Protocol” heading.
The “QUIC Transport Parameters” registry governs a 16-bit space. This space is split into two spaces that are governed by different policies. Values with the first byte in the range 0x00 to 0xfe (in hexadecimal) are assigned via the Specification Required policy [RFC8126]. Values with the first byte 0xff are reserved for Private Use [RFC8126].
Registrations MUST include the following fields:
The nominated expert(s) verify that a specification exists and is readily accessible. Expert(s) are encouraged to be biased towards approving registrations unless they are abusive, frivolous, or actively harmful (not merely aesthetically displeasing, or architecturally dubious).
The initial contents of this registry are shown in Table 6.
| Value | Parameter Name | Specification |
|---|---|---|
| 0x0000 | original_connection_id | Section 18.1 |
| 0x0001 | idle_timeout | Section 18.1 |
| 0x0002 | stateless_reset_token | Section 18.1 |
| 0x0003 | max_packet_size | Section 18.1 |
| 0x0004 | initial_max_data | Section 18.1 |
| 0x0005 | initial_max_stream_data_bidi_local | Section 18.1 |
| 0x0006 | initial_max_stream_data_bidi_remote | Section 18.1 |
| 0x0007 | initial_max_stream_data_uni | Section 18.1 |
| 0x0008 | initial_max_streams_bidi | Section 18.1 |
| 0x0009 | initial_max_streams_uni | Section 18.1 |
| 0x000a | ack_delay_exponent | Section 18.1 |
| 0x000b | max_ack_delay | Section 18.1 |
| 0x000c | disable_migration | Section 18.1 |
| 0x000d | preferred_address | Section 18.1 |
IANA [SHALL add/has added] a registry for “QUIC Frame Types” under a “QUIC Protocol” heading.
The “QUIC Frame Types” registry governs a 62-bit space. This space is split into three spaces that are governed by different policies. Values between 0x00 and 0x3f (in hexadecimal) are assigned via the Standards Action or IESG Review policies [RFC8126]. Values from 0x40 to 0x3fff operate on the Specification Required policy [RFC8126]. All other values are assigned to Private Use [RFC8126].
Registrations MUST include the following fields:
The nominated expert(s) verify that a specification exists and is readily accessible. Specifications for new registrations need to describe the means by which an endpoint might determine that it can send the identified type of frame. An accompanying transport parameter registration (see Section 22.1) is expected for most registrations. The specification needs to describe the format and assigned semantics of any fields in the frame.
Expert(s) are encouraged to be biased towards approving registrations unless they are abusive, frivolous, or actively harmful (not merely aesthetically displeasing, or architecturally dubious).
The initial contents of this registry are tabulated in Table 3.
IANA [SHALL add/has added] a registry for “QUIC Transport Error Codes” under a “QUIC Protocol” heading.
The “QUIC Transport Error Codes” registry governs a 16-bit space. This space is split into two spaces that are governed by different policies. Values with the first byte in the range 0x00 to 0xfe (in hexadecimal) are assigned via the Specification Required policy [RFC8126]. Values with the first byte 0xff are reserved for Private Use [RFC8126].
Registrations MUST include the following fields:
The initial contents of this registry are shown in Table 7. Values from 0xFF00 to 0xFFFF are reserved for Private Use [RFC8126].
| Value | Error | Description | Specification |
|---|---|---|---|
| 0x0 | NO_ERROR | No error | Section 20 |
| 0x1 | INTERNAL_ERROR | Implementation error | Section 20 |
| 0x2 | SERVER_BUSY | Server currently busy | Section 20 |
| 0x3 | FLOW_CONTROL_ERROR | Flow control error | Section 20 |
| 0x4 | STREAM_LIMIT_ERROR | Too many streams opened | Section 20 |
| 0x5 | STREAM_STATE_ERROR | Frame received in invalid stream state | Section 20 |
| 0x6 | FINAL_SIZE_ERROR | Change to final size | Section 20 |
| 0x7 | FRAME_ENCODING_ERROR | Frame encoding error | Section 20 |
| 0x8 | TRANSPORT_PARAMETER_ERROR | Error in transport parameters | Section 20 |
| 0xA | PROTOCOL_VIOLATION | Generic protocol violation | Section 20 |
| 0xC | INVALID_MIGRATION | Violated disabled migration | Section 20 |
| [DPLPMTUD] | Fairhurst, G., Jones, T., Tuexen, M., Ruengeler, I. and T. Voelker, "Packetization Layer Path MTU Discovery for Datagram Transports", Internet-Draft draft-ietf-tsvwg-datagram-plpmtud-07, February 2019. |
| [QUIC-RECOVERY] | Iyengar, J. and I. Swett, "QUIC Loss Detection and Congestion Control", Internet-Draft draft-ietf-quic-recovery-20, April 2019. |
| [QUIC-TLS] | Thomson, M. and S. Turner, "Using Transport Layer Security (TLS) to Secure QUIC", Internet-Draft draft-ietf-quic-tls-20, April 2019. |
| [RFC1191] | Mogul, J. and S. Deering, "Path MTU discovery", RFC 1191, DOI 10.17487/RFC1191, November 1990. |
| [RFC2119] | Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997. |
| [RFC3168] | Ramakrishnan, K., Floyd, S. and D. Black, "The Addition of Explicit Congestion Notification (ECN) to IP", RFC 3168, DOI 10.17487/RFC3168, September 2001. |
| [RFC3629] | Yergeau, F., "UTF-8, a transformation format of ISO 10646", STD 63, RFC 3629, DOI 10.17487/RFC3629, November 2003. |
| [RFC4086] | Eastlake 3rd, D., Schiller, J. and S. Crocker, "Randomness Requirements for Security", BCP 106, RFC 4086, DOI 10.17487/RFC4086, June 2005. |
| [RFC5116] | McGrew, D., "An Interface and Algorithms for Authenticated Encryption", RFC 5116, DOI 10.17487/RFC5116, January 2008. |
| [RFC6437] | Amante, S., Carpenter, B., Jiang, S. and J. Rajahalme, "IPv6 Flow Label Specification", RFC 6437, DOI 10.17487/RFC6437, November 2011. |
| [RFC8085] | Eggert, L., Fairhurst, G. and G. Shepherd, "UDP Usage Guidelines", BCP 145, RFC 8085, DOI 10.17487/RFC8085, March 2017. |
| [RFC8126] | Cotton, M., Leiba, B. and T. Narten, "Guidelines for Writing an IANA Considerations Section in RFCs", BCP 26, RFC 8126, DOI 10.17487/RFC8126, June 2017. |
| [RFC8174] | Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, May 2017. |
| [RFC8201] | McCann, J., Deering, S., Mogul, J. and R. Hinden, "Path MTU Discovery for IP version 6", STD 87, RFC 8201, DOI 10.17487/RFC8201, July 2017. |
| [RFC8311] | Black, D., "Relaxing Restrictions on Explicit Congestion Notification (ECN) Experimentation", RFC 8311, DOI 10.17487/RFC8311, January 2018. |
| [TLS13] | Rescorla, E., "The Transport Layer Security (TLS) Protocol Version 1.3", RFC 8446, DOI 10.17487/RFC8446, August 2018. |
The following pseudo-code shows how an implementation can decode packet numbers after header protection has been removed.
DecodePacketNumber(largest_pn, truncated_pn, pn_nbits): expected_pn = largest_pn + 1 pn_win = 1 << pn_nbits pn_hwin = pn_win / 2 pn_mask = pn_win - 1 // The incoming packet number should be greater than // expected_pn - pn_hwin and less than or equal to // expected_pn + pn_hwin // // This means we can't just strip the trailing bits from // expected_pn and add the truncated_pn because that might // yield a value outside the window. // // The following code calculates a candidate value and // makes sure it's within the packet number window. candidate_pn = (expected_pn & ~pn_mask) | truncated_pn if candidate_pn <= expected_pn - pn_hwin: return candidate_pn + pn_win // Note the extra check for underflow when candidate_pn // is near zero. if candidate_pn > expected_pn + pn_hwin and candidate_pn > pn_win: return candidate_pn - pn_win return candidate_pn
Issue and pull request numbers are listed with a leading octothorp.
Substantial editorial reorganization; no technical changes.
Special thanks are due to the following for helping shape pre-IETF QUIC and its deployment: Chris Bentzel, Misha Efimov, Roberto Peon, Alistair Riddoch, Siddharth Vijayakrishnan, and Assar Westerlund.
This document has benefited immensely from various private discussions and public ones on the<EMAIL_ADDRESS>and<EMAIL_ADDRESS>mailing lists. Our thanks to all.
The original authors of this specification were Ryan Hamilton, Jana Iyengar, Ian Swett, and Alyssa Wilk.
The original design and rationale behind this protocol draw significantly from work by Jim Roskind [EARLY-DESIGN]. In alphabetical order, the contributors to the pre-IETF QUIC project at Google are: Britt Cyr, Jeremy Dorfman, Ryan Hamilton, Jana Iyengar, Fedor Kouranov, Charles Krasic, Jo Kulik, Adam Langley, Jim Roskind, Robbie Shade, Satyam Shekhar, Cherie Shi, Ian Swett, Raman Tenneti, Victor Vasiliev, Antonio Vicente, Patrik Westin, Alyssa Wilk, Dale Worley, Fan Yang, Dan Zhang, Daniel Ziegler.


FlexBox is a jQuery plugin that is intended to be a very flexible replacement for html textboxes and dropdowns, optionally using ajax to retrieve and bind JSON data.
It can be used as a:
Please visit the CodePlex Project Page to download FlexBox
Here is a teaser... (click the arrow, or type a character or two in the input box)
To see the power and flexibility of FlexBox, please check out all the demos!
Download the latest version of FlexBox, which includes the following files:
| Please note that by default, FlexBox expects to see files in this directory structure. If you need to move the "sel*.gif" image (which is a sprite for the arrow), be sure to update the css file to point to the new location. |
Add an empty div to the <body> tag wherever you want the FlexBox to appear:
Make sure you have a reference to jQuery, and the FlexBox js and css files in the <head> tag:
Also within the <head> tag, below the references to jQuery and FlexBox, call the jQuery ready() function, and within it, call the FlexBox using the id of the <div> you just created. The only parameter you must pass is the page name that will return the results as a JSON string. You may also pass a second parameter, which is a JSON object containing any of the Configuration Options:
The call to results.aspx is ajax, and should return a JSON string in the format shown below.
This produces the following (when the default css styles are used):
Here are all the available options for customizing the FlexBox:
| Appearance |
|
showArrow : boolean (default = true)
Set to false to simulate Google Suggest, which forces the user to type before results are displayed. |
|
showResults : boolean (default = true)
Set to false to hide the dropdown results. Exact matches appear immediately, and are selected in the input box. |
|
noResultsText : string (default = 'No matching results')
Text to display when there are no results matching what the user typed. Appears as a one-row dropdown below the input box. |
|
width : number (default = 200)
Specifies the overall width of the FlexBox. Automatically adjusts to accommodate the arrow as necessary. |
|
maxVisibleRows : number (default = 0)
When set to 0 (zero), this option is ignored. Otherwise, you can set this value to force scrolling. This can be used in conjunction with paging.pageSize. |
|
watermark : string (default = '')
Helpful text that appears in the input box when it is loaded. Automatically hides when the arrow is clicked, or the input box gets focus. Ignored if initialValue is set. This option can be styled by changing the class '.ffb-input.watermark'. |
|
resultTemplate : string (default = '{name}')
This very flexible property allows you to specify a template that is applied to each row of data returned. The template is a combination of html and JSON properties (in curly braces). For example, to create a two-column result template that displays the id in the first column, and the name in the second column, you might use this: For each object in the JSON results array, the resultTemplate is applied, and the actual value in the JSON data is substituted for the {property}. You can also use dot notation for nested JSON properties (e.g. {Thumbnail.Url}). |
| Behavior |
|
method : string (default = 'GET')
If 'GET', will call jQuery's $.getJSON() function. If 'POST', will call jQuery's $.post() method, with "post" as the fourth parameter. "POST" is useful for ASP.NET Web Services (Script methods). When POSTing to an ASP.NET page, remember to check Request.Form (or just Request) in the code-behind, instead of Request.QueryString. |
|
autoCompleteFirstMatch : boolean (default = false)
If set to true, the input box will automatically populate the first match for the text entered, and highlight the remaining characters. If set to false, the input box will always display only what the user types until a selection is made. |
|
selectFirstMatch : boolean (default = true)
If set to true, the first matching item in the list will appear selected. If set to false, no items will be selected when a match is made. |
|
allowInput : boolean (default = true)
If set to false, behaves more like a standard <select> element, disallowing user input. If set to true (the default), acts like a combobox. |
|
queryDelay : number (default = 100)
The number of milliseconds to wait before the query is executed (after the user clicks or types in the FlexBox). |
|
minChars : number (default = 1)
The minimum number of characters the user must enter before a search is executed. Note that if showArrow = true, and arrowQuery = '', the user can click the arrow to view results (without typing any characters). Zero (0) is an invalid option for this property. |
|
highlightMatches : boolean (default = true)
Specifies whether the text the user types should be highlighted within the results. Use the matchClass option to set the css class for highlighted characters. |
|
highlightMatchesRegExModifier : string (default = 'i')
Specifies the type of RegEx modifier to apply when determining how to highlight matches. Options are:
|
|
arrowQuery : string (default = '')
The query to pass to the server when the arrow is clicked. By default, clicking the arrow will return all results (up to paging.pageSize, which is 10 by default). If you wanted to limit the results returned to those that start with the letter 'a', you can set arrowQuery to 'a', |
|
onSelect : object (default = false)
The function to run when a result is selected. Use the full power of jQuery to write values to divs, or even make another JSON call! Within this function, if you want to get the text displayed in the input box, use this.value, and if you want to get the hidden value (see the hiddenValue configuration options), use this.getAttribute('hiddenValue'). |
|
maxCacheBytes : number (default = 32768)
The amount of data you will allow to be cached on the client side. Setting this value to 0 (zero) disables the cache. maxCacheBytes uses a JavaScript associative array to quickly access data based on query and current page, and uses an array to maintain a list of most recently used items (MRU). |
| CSS Class Overrides |
|
containerClass : string (default = 'ffb')
Overrides the name of the class for the main FlexBox div. |
|
contentClass : string (default = 'content')
Overrides the name of the class for the content div. |
|
inputClass : string (default = 'ffb-input')
Overrides the name of the class for the input element. |
|
arrowClass : string (default = 'ffb-arrow')
Overrides the name of the class for the arrow image. |
|
selectClass : string (default = 'ffb-sel')
Overrides the name of the class for "selected" items (rows). |
|
matchClass : string (default = 'ffb-match')
Overrides the name of the class for showing where your query matches the result. |
|
noResultsClass : string (default = 'ffb-no-results')
Specifies the class to apply to the noResultsText configuration options. |
| Form Field Values |
|
displayValue : string (default = 'name')
JSON property whose value is displayed in the input box when a result is selected. |
|
hiddenValue : string (default = 'id')
JSON property whose value is submitted when the form is submitted. Automatically updated whenever the displayValue changes. |
|
initialValue : string (default = '')
Specifies the value that should appear in the input box when the FlexBox is loaded. You can also set this manually using the setValue() method. |
| JSON Properties |
|
resultsProperty : string (default = 'results')
JSON property in returned results that references the array of JSON objects representing each row of data. |
|
totalProperty : string (default = 'total')
JSON property in returned results that references the total number of results the query returned (used for paging only, so the paging toolbar can properly calculate how many pages of data exist). |
| Paging |
|
paging : object
The paging object contains many properties to customize the appearance of the paging toolbar: |
setValue() is the only method, and allows you to set the display value of the input box after the FlexBox has loaded.
See jquery.flexbox.css for default styles. Important classes and attributes are commented.
Please use the Issue Tracker to view and report issues


3 February 2003
Disease Outbreak Reported
As of January 23, 2003, the Ministry of Public Health of Guinea has reported 43 cases and 24 deaths in Macenta and Kérouane prefectures. Laboratory confirmation was carried out by the Instituts Pasteur in Dakar, Senegal and Lyon, France.
A mass vaccination campaign has begun in Macenta and nearby prefectures, targetting a population of around 600 000 people. WHO and partners including Médecins sans Frontières Belgium, France and Switzerland are assisting the Ministry of Public Health with operational and technical assistance, vaccine and vaccine supplies for the campaign.


Sam Ricketts wary of a Mansfield Cup charge
by Lewis CoxSam Ricketts wants to see his Shrewsbury side back to their resolute best – but warns Mansfield rock up in the FA Cup with ‘nothing to lose’.
Town were uncharacteristically leaky in last weekend’s topsy-turvy 4-3 reverse to Bristol Rovers in League One, writes Lewis Cox.
The boss expects to see the reliable side that managed 10 clean sheets in 22 before that.
“We want to get back to winning ways. The positive was we made it a context but it was a sucker punch.
“We showed fight and spirit and that we’re more than capable of scoring goals.
“But Unlike us we conceded cheap goals,” Ricketts said.
“We want to be hard to beat and keep the goalscoring element going. We want to nullify the goals at the other end.
“We’re very solid but you are going to concede. we have little spates where we don’t concede or just the one then we’ve had three threes (against) and a four this year now.
“You want to knock those on the head as best we can.”
League Two Mansfield, 25 places below Shrews in the pyramid, have endured a sluggish start to the campaign after reaching last season’s play-offs.
On John Dempster’s side’s malaise, the Shrews boss continued: “Possibly (they’re under-performing).
“They’ve got good players we’re very wary of. It just shows in English football there’s big competition among all the teams. There’s not a lot separating teams in the Championship, our league or League Two.
“A couple of points takes you from play-offs to just below mid-table in every league.
“It’s not an easy game. They come here just like if we were going to a side a league above us – with nothing to lose and everything to gain.
“They come with that freedom which allows them to express themselves a little bit more than possibly normally.”
Forward Lenell John-Lewis could feature in Ricketts’ thoughts tomorrow after 11 months on the sidelines with an anterior cruciate ligament injury.
The frontman made his return from the bench against Macclesfield in the EFL Trophy and came on against Rovers in the league before captaining a youthful Town side in the Central League Cup.
John-Lewis, an extremely popular member of the squad, has not once let a third serious injury drag him down.
The 30-year-old ruptured his hamstring at Newport County before an ACL injury in his right knee for the Welsh club, the opposite knee to the damage done against Stoke while playing for Town in the FA Cup in January. John-Lewis, who was given a new six-month deal in the summer, said on his mindset: “I don’t know. People say it’s just me, my mum would say it’s probably from her side! You just have to take things with a pinch of salt.

“The whole family has been fantastic. If this was a thanks speech I could go on for ages. A lot of people have helped me.
“It’s pleasing to know I’ve got so many people around me, going home to kids can take your mind off it.
“My daughter is four, she’s like ‘now we’re ready to watch you play football daddy’, it’s massive motivation.
“She’s been there for both of my injuries, she remembers watching me and now she wants to watch me again.
“It’s positive mental attitude. I wanted to do it quicker than I did it in but things happen.
“You have to get over them quickly.
“It’ll be full-blooded for me, I’ve never been that way (to hold back) and hopefully I’ll put some defenders on the floor.”
Sean Goss and Shaun Whalley are not quite ready to feature, but Daniel Udoh could return.


Naren works smart and has a warm heart. He is mischievous and tries not to take himself too serious. He is a terrible cyclist, What Naren lacks in his sprint and attack skills he more than makes up for in internet skills.
Naren currently works as a back-end engineer at MadStreetDen. He love python and occasionally cheat her with golang. He is opensource hardware user, has done many projects in Embedded Systems, IoT.


Path to the HTML report with coverage data that DotCover will generate. The default path is 'index.html'. This setting will have DotCover produce an index.html in the workspace + a subfolder with the data used in this webpage.


meatspoon
21-Oct-18 03:25 PM
@snowdamn I disagree, if they could (in theory) shut down DEX's, everything would have to go thru the KYC gateways. Dex's mean the possibility to avoid taxes
they wont frame it up that way, jl. they will make it a tax issue, talk about people getting rich trading in dark, shady DEX's
talk about people "not paying their fair share"
its also worth pointing out that the SEC and other government agencies are also used to create near-monopolies by smothering competition of bigger corporations. No reason to think this won't happen in crypto as larger projects start to put lobbyists in washington