blob: 7ea590a75a5f4ec92feff19e6d32673f9eae8b4d [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// Definitions and utility functions related to handling of QUIC versions.
6//
dschinazia98acdf2020-05-21 15:34:16 -07007// QUIC versions are encoded over the wire as an opaque 32bit field. The wire
8// encoding is represented in memory as a QuicVersionLabel type (which is an
9// alias to uint32_t). Conceptual versions are represented in memory as
10// ParsedQuicVersion.
11//
12// We currently support two kinds of QUIC versions, GoogleQUIC and IETF QUIC.
13//
14// All GoogleQUIC versions use a wire encoding that matches the following regex
15// when converted to ASCII: "[QT]0\d\d" (e.g. Q050). Q or T distinguishes the
16// type of handshake used (Q for the QUIC_CRYPTO handshake, T for the QUIC+TLS
17// handshake), and the two digits at the end contain the numeric value of
18// the transport version used.
19//
20// All IETF QUIC versions use the wire encoding described in:
21// https://tools.ietf.org/html/draft-ietf-quic-transport
QUICHE teama6ef0a62019-03-07 20:34:33 -050022
23#ifndef QUICHE_QUIC_CORE_QUIC_VERSIONS_H_
24#define QUICHE_QUIC_CORE_QUIC_VERSIONS_H_
25
vasilvv872e7a32019-03-12 16:42:44 -070026#include <string>
QUICHE teama6ef0a62019-03-07 20:34:33 -050027#include <vector>
28
29#include "net/third_party/quiche/src/quic/core/quic_tag.h"
30#include "net/third_party/quiche/src/quic/core/quic_types.h"
31#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
dschinazicee73cd2020-03-05 18:20:50 -080032#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050033
34namespace quic {
35
dschinazia98acdf2020-05-21 15:34:16 -070036// The list of existing QUIC transport versions. Note that QUIC versions are
37// sent over the wire as an encoding of ParsedQuicVersion, which requires a
38// QUIC transport version and handshake protocol. For transport versions of the
39// form QUIC_VERSION_XX where XX is decimal, the enum numeric value is
40// guaranteed to match the name. Older deprecated transport versions are
41// documented in comments below.
QUICHE teama6ef0a62019-03-07 20:34:33 -050042enum QuicTransportVersion {
43 // Special case to indicate unknown/unsupported QUIC version.
44 QUIC_VERSION_UNSUPPORTED = 0,
45
46 // Version 1 was the first version of QUIC that supported versioning.
47 // Version 2 decoupled versioning of non-cryptographic parameters from the
48 // SCFG.
49 // Version 3 moved public flags into the beginning of the packet.
50 // Version 4 added support for variable-length connection IDs.
51 // Version 5 made specifying FEC groups optional.
52 // Version 6 introduced variable-length packet numbers.
53 // Version 7 introduced a lower-overhead encoding for stream frames.
54 // Version 8 made salt length equal to digest length for the RSA-PSS
55 // signatures.
56 // Version 9 added stream priority.
57 // Version 10 redid the frame type numbering.
58 // Version 11 reduced the length of null encryption authentication tag
59 // from 16 to 12 bytes.
60 // Version 12 made the sequence numbers in the ACK frames variable-sized.
61 // Version 13 added the dedicated header stream.
62 // Version 14 added byte_offset to RST_STREAM frame.
63 // Version 15 added a list of packets recovered using FEC to the ACK frame.
64 // Version 16 added STOP_WAITING frame.
65 // Version 17 added per-stream flow control.
66 // Version 18 added PING frame.
67 // Version 19 added connection-level flow control
68 // Version 20 allowed to set stream- and connection-level flow control windows
69 // to different values.
70 // Version 21 made header and crypto streams flow-controlled.
71 // Version 22 added support for SCUP (server config update) messages.
72 // Version 23 added timestamps into the ACK frame.
73 // Version 24 added SPDY/4 header compression.
74 // Version 25 added support for SPDY/4 header keys and removed error_details
75 // from RST_STREAM frame.
76 // Version 26 added XLCT (expected leaf certificate) tag into CHLO.
77 // Version 27 added a nonce into SHLO.
78 // Version 28 allowed receiver to refuse creating a requested stream.
79 // Version 29 added support for QUIC_STREAM_NO_ERROR.
80 // Version 30 added server-side support for certificate transparency.
81 // Version 31 incorporated the hash of CHLO into the crypto proof supplied by
82 // the server.
83 // Version 32 removed FEC-related fields from wire format.
84 // Version 33 added diversification nonces.
85 // Version 34 removed entropy bits from packets and ACK frames, removed
86 // private flag from packet header and changed the ACK format to
87 // specify ranges of packets acknowledged rather than missing
88 // ranges.
89 // Version 35 allows endpoints to independently set stream limit.
90 // Version 36 added support for forced head-of-line blocking experiments.
91 // Version 37 added perspective into null encryption.
92 // Version 38 switched to IETF padding frame format and support for NSTP (no
93 // stop waiting frame) connection option.
94
fayang8265a2a2019-10-16 11:23:51 -070095 // Version 39 writes integers and floating numbers in big endian, stops acking
96 // acks, sends a connection level WINDOW_UPDATE every 20 sent packets which do
97 // not contain retransmittable frames.
QUICHE teama6ef0a62019-03-07 20:34:33 -050098
99 // Version 40 was an attempt to convert QUIC to IETF frame format; it was
100 // never shipped due to a bug.
101 // Version 41 was a bugfix for version 40. The working group changed the wire
102 // format before it shipped, which caused it to be never shipped
103 // and all the changes from it to be reverted. No changes from v40
104 // or v41 are present in subsequent versions.
105 // Version 42 allowed receiving overlapping stream data.
106
107 QUIC_VERSION_43 = 43, // PRIORITY frames are sent by client and accepted by
108 // server.
fayang36825da2019-08-21 14:01:27 -0700109 // Version 44 used IETF header format from draft-ietf-quic-invariants-05.
QUICHE teama6ef0a62019-03-07 20:34:33 -0500110
111 // Version 45 added MESSAGE frame.
112
113 QUIC_VERSION_46 = 46, // Use IETF draft-17 header format with demultiplexing
114 // bit.
dschinazi8b1c45a2019-10-17 08:48:13 -0700115 // Version 47 added variable-length QUIC server connection IDs.
dschinaziceed8662020-07-14 09:37:05 -0700116 // Version 48 added CRYPTO frames for the handshake.
117 // Version 49 added client connection IDs, long header lengths, and the IETF
118 // header format from draft-ietf-quic-invariants-06
nharperc32d8ab2019-10-09 11:09:06 -0700119 QUIC_VERSION_50 = 50, // Header protection and initial obfuscators.
dschinazi47692202020-07-30 11:09:42 -0700120 QUIC_VERSION_51 = 51, // draft-29 features but with GoogleQUIC frames.
dschinazi40f0b3d2020-02-19 17:54:05 -0800121 QUIC_VERSION_IETF_DRAFT_25 = 70, // draft-ietf-quic-transport-25.
dschinazic3316f32020-03-05 14:34:36 -0800122 QUIC_VERSION_IETF_DRAFT_27 = 71, // draft-ietf-quic-transport-27.
dschinazi6ab45242020-06-23 00:20:37 -0700123 // Number 72 used to represent draft-ietf-quic-transport-28.
dschinazib3fed9e2020-06-11 11:59:33 -0700124 QUIC_VERSION_IETF_DRAFT_29 = 73, // draft-ietf-quic-transport-29.
dschinazic3316f32020-03-05 14:34:36 -0800125 // Version 99 was a dumping ground for IETF QUIC changes which were not yet
126 // yet ready for production between 2018-02 and 2020-02.
127
dschinazi1ac22cc2019-06-25 11:47:50 -0700128 // QUIC_VERSION_RESERVED_FOR_NEGOTIATION is sent over the wire as ?a?a?a?a
dschinazi5a354c92019-05-09 12:18:53 -0700129 // which is part of a range reserved by the IETF for version negotiation
dschinazi1ac22cc2019-06-25 11:47:50 -0700130 // testing (see the "Versions" section of draft-ietf-quic-transport).
131 // This version is intentionally meant to never be supported to trigger
132 // version negotiation when proposed by clients and to prevent client
133 // ossification when sent by servers.
dschinazi5a354c92019-05-09 12:18:53 -0700134 QUIC_VERSION_RESERVED_FOR_NEGOTIATION = 999,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500135};
136
dschinazia0b4d2e2020-03-16 16:22:08 -0700137// This array contains QUIC transport versions which we currently support.
dschinazia98acdf2020-05-21 15:34:16 -0700138// DEPRECATED. Use SupportedVersions() instead.
dschinazi47692202020-07-30 11:09:42 -0700139constexpr std::array<QuicTransportVersion, 7> SupportedTransportVersions() {
dschinazib3fed9e2020-06-11 11:59:33 -0700140 return {QUIC_VERSION_IETF_DRAFT_29,
dschinazi2c78aac2020-05-21 17:21:58 -0700141 QUIC_VERSION_IETF_DRAFT_27,
dschinazia0b4d2e2020-03-16 16:22:08 -0700142 QUIC_VERSION_IETF_DRAFT_25,
dschinazi47692202020-07-30 11:09:42 -0700143 QUIC_VERSION_51,
dschinazia0b4d2e2020-03-16 16:22:08 -0700144 QUIC_VERSION_50,
dschinazia0b4d2e2020-03-16 16:22:08 -0700145 QUIC_VERSION_46,
146 QUIC_VERSION_43};
147}
148
dschinazidc770fc2020-01-13 15:42:41 -0800149// Helper function which translates from a QuicTransportVersion to a string.
150// Returns strings corresponding to enum names (e.g. QUIC_VERSION_6).
151QUIC_EXPORT_PRIVATE std::string QuicVersionToString(
152 QuicTransportVersion transport_version);
153
QUICHE teama6ef0a62019-03-07 20:34:33 -0500154// The crypto handshake protocols that can be used with QUIC.
155enum HandshakeProtocol {
156 PROTOCOL_UNSUPPORTED,
157 PROTOCOL_QUIC_CRYPTO,
158 PROTOCOL_TLS1_3,
159};
160
dschinazidc770fc2020-01-13 15:42:41 -0800161// Helper function which translates from a HandshakeProtocol to a string.
162QUIC_EXPORT_PRIVATE std::string HandshakeProtocolToString(
163 HandshakeProtocol handshake_protocol);
164
dschinazi0da43902020-01-17 15:26:14 -0800165// Returns whether |transport_version| uses CRYPTO frames for the handshake
166// instead of stream 1.
167QUIC_EXPORT_PRIVATE constexpr bool QuicVersionUsesCryptoFrames(
168 QuicTransportVersion transport_version) {
dschinaziceed8662020-07-14 09:37:05 -0700169 // CRYPTO frames were added in version 48.
170 return transport_version > QUIC_VERSION_46;
dschinazi0da43902020-01-17 15:26:14 -0800171}
172
dschinazidc770fc2020-01-13 15:42:41 -0800173// Returns whether this combination of handshake protocol and transport
174// version is allowed. For example, {PROTOCOL_TLS1_3, QUIC_VERSION_43} is NOT
175// allowed as TLS requires crypto frames which v43 does not support. Note that
176// UnsupportedQuicVersion is a valid version.
dschinazi0da43902020-01-17 15:26:14 -0800177QUIC_EXPORT_PRIVATE constexpr bool ParsedQuicVersionIsValid(
dschinazidc770fc2020-01-13 15:42:41 -0800178 HandshakeProtocol handshake_protocol,
dschinazi0da43902020-01-17 15:26:14 -0800179 QuicTransportVersion transport_version) {
dschinazia0b4d2e2020-03-16 16:22:08 -0700180 bool transport_version_is_valid =
181 transport_version == QUIC_VERSION_UNSUPPORTED ||
182 transport_version == QUIC_VERSION_RESERVED_FOR_NEGOTIATION;
183 if (!transport_version_is_valid) {
dschinazi5efb9652020-03-17 10:16:45 -0700184 // Iterators are not constexpr in C++14 which Chrome uses.
185 constexpr auto supported_transport_versions = SupportedTransportVersions();
186 for (size_t i = 0; i < supported_transport_versions.size(); ++i) {
187 const QuicTransportVersion& trans_vers = supported_transport_versions[i];
dschinazia0b4d2e2020-03-16 16:22:08 -0700188 if (trans_vers == transport_version) {
189 transport_version_is_valid = true;
190 break;
191 }
192 }
193 }
194 if (!transport_version_is_valid) {
195 return false;
196 }
dschinazi0da43902020-01-17 15:26:14 -0800197 switch (handshake_protocol) {
198 case PROTOCOL_UNSUPPORTED:
199 return transport_version == QUIC_VERSION_UNSUPPORTED;
200 case PROTOCOL_QUIC_CRYPTO:
dschinazi41616842020-01-21 15:46:11 -0800201 return transport_version != QUIC_VERSION_UNSUPPORTED &&
dschinazi47692202020-07-30 11:09:42 -0700202 transport_version != QUIC_VERSION_51 &&
dschinazi40f0b3d2020-02-19 17:54:05 -0800203 transport_version != QUIC_VERSION_IETF_DRAFT_25 &&
dschinazi2c78aac2020-05-21 17:21:58 -0700204 transport_version != QUIC_VERSION_IETF_DRAFT_27 &&
dschinazib3fed9e2020-06-11 11:59:33 -0700205 transport_version != QUIC_VERSION_IETF_DRAFT_29;
dschinazi0da43902020-01-17 15:26:14 -0800206 case PROTOCOL_TLS1_3:
dschinazia0b4d2e2020-03-16 16:22:08 -0700207 return transport_version != QUIC_VERSION_UNSUPPORTED &&
dschinaziceed8662020-07-14 09:37:05 -0700208 QuicVersionUsesCryptoFrames(transport_version);
dschinazi0da43902020-01-17 15:26:14 -0800209 }
210 return false;
211}
dschinazidc770fc2020-01-13 15:42:41 -0800212
QUICHE teama6ef0a62019-03-07 20:34:33 -0500213// A parsed QUIC version label which determines that handshake protocol
214// and the transport version.
215struct QUIC_EXPORT_PRIVATE ParsedQuicVersion {
216 HandshakeProtocol handshake_protocol;
217 QuicTransportVersion transport_version;
218
dschinazi3f6ccf42019-10-25 16:58:37 -0700219 constexpr ParsedQuicVersion(HandshakeProtocol handshake_protocol,
220 QuicTransportVersion transport_version)
221 : handshake_protocol(handshake_protocol),
dschinazi0da43902020-01-17 15:26:14 -0800222 transport_version(transport_version) {
223 DCHECK(ParsedQuicVersionIsValid(handshake_protocol, transport_version))
224 << QuicVersionToString(transport_version) << " "
225 << HandshakeProtocolToString(handshake_protocol);
226 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500227
dschinazi3f6ccf42019-10-25 16:58:37 -0700228 constexpr ParsedQuicVersion(const ParsedQuicVersion& other)
dschinazi97da52b2020-01-13 15:44:43 -0800229 : ParsedQuicVersion(other.handshake_protocol, other.transport_version) {}
QUICHE teama6ef0a62019-03-07 20:34:33 -0500230
231 ParsedQuicVersion& operator=(const ParsedQuicVersion& other) {
dschinazi0da43902020-01-17 15:26:14 -0800232 DCHECK(ParsedQuicVersionIsValid(other.handshake_protocol,
233 other.transport_version))
234 << QuicVersionToString(other.transport_version) << " "
235 << HandshakeProtocolToString(other.handshake_protocol);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500236 if (this != &other) {
237 handshake_protocol = other.handshake_protocol;
238 transport_version = other.transport_version;
239 }
240 return *this;
241 }
242
243 bool operator==(const ParsedQuicVersion& other) const {
244 return handshake_protocol == other.handshake_protocol &&
245 transport_version == other.transport_version;
246 }
247
248 bool operator!=(const ParsedQuicVersion& other) const {
249 return handshake_protocol != other.handshake_protocol ||
250 transport_version != other.transport_version;
251 }
zhongyi546cc452019-04-12 15:27:49 -0700252
dschinazib3fed9e2020-06-11 11:59:33 -0700253 static constexpr ParsedQuicVersion Draft29() {
254 return ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_IETF_DRAFT_29);
255 }
256
dschinazi2be3a022020-05-29 13:52:19 -0700257 static constexpr ParsedQuicVersion Draft27() {
258 return ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_IETF_DRAFT_27);
259 }
260
261 static constexpr ParsedQuicVersion Draft25() {
262 return ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_IETF_DRAFT_25);
263 }
264
dschinazi47692202020-07-30 11:09:42 -0700265 static constexpr ParsedQuicVersion T051() {
266 return ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_51);
267 }
268
dschinazi2be3a022020-05-29 13:52:19 -0700269 static constexpr ParsedQuicVersion T050() {
270 return ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_50);
271 }
272
273 static constexpr ParsedQuicVersion Q050() {
274 return ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_50);
275 }
276
dschinazi2be3a022020-05-29 13:52:19 -0700277 static constexpr ParsedQuicVersion Q046() {
278 return ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_46);
279 }
280
281 static constexpr ParsedQuicVersion Q043() {
282 return ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_43);
283 }
284
285 static constexpr ParsedQuicVersion Unsupported() {
286 return ParsedQuicVersion(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED);
287 }
288
289 static constexpr ParsedQuicVersion ReservedForNegotiation() {
290 return ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO,
291 QUIC_VERSION_RESERVED_FOR_NEGOTIATION);
292 }
293
dschinazidc770fc2020-01-13 15:42:41 -0800294 // Returns whether our codebase understands this version. This should only be
295 // called on valid versions, see ParsedQuicVersionIsValid. Assuming the
296 // version is valid, IsKnown returns whether the version is not
297 // UnsupportedQuicVersion.
298 bool IsKnown() const;
299
zhongyi546cc452019-04-12 15:27:49 -0700300 bool KnowsWhichDecrypterToUse() const;
dschinazic7036122019-04-30 12:46:34 -0700301
nharperc8d9e402019-09-12 18:30:14 -0700302 // Returns whether this version uses keys derived from the Connection ID for
303 // ENCRYPTION_INITIAL keys (instead of NullEncrypter/NullDecrypter).
304 bool UsesInitialObfuscators() const;
305
dschinazic7036122019-04-30 12:46:34 -0700306 // Indicates that this QUIC version does not have an enforced minimum value
307 // for flow control values negotiated during the handshake.
308 bool AllowsLowFlowControlLimits() const;
nharpercfafed72019-05-01 13:43:55 -0700309
310 // Returns whether header protection is used in this version of QUIC.
311 bool HasHeaderProtection() const;
dschinazi244f6dc2019-05-06 15:45:16 -0700312
313 // Returns whether this version supports IETF RETRY packets.
314 bool SupportsRetry() const;
dschinazib417d602019-05-29 13:08:45 -0700315
dschinazi278efae2020-01-28 17:03:09 -0800316 // Returns whether RETRY packets carry the Retry Integrity Tag field.
317 bool HasRetryIntegrityTag() const;
318
fayang3ac15c12019-06-14 14:04:51 -0700319 // Returns true if this version sends variable length packet number in long
320 // header.
321 bool SendsVariableLengthPacketNumberInLongHeader() const;
322
dschinazi97da52b2020-01-13 15:44:43 -0800323 // Returns whether this version allows server connection ID lengths
324 // that are not 64 bits.
325 bool AllowsVariableLengthConnectionIds() const;
326
dschinazib417d602019-05-29 13:08:45 -0700327 // Returns whether this version supports client connection ID.
328 bool SupportsClientConnectionIds() const;
dschinazi48ac9192019-07-31 00:07:26 -0700329
330 // Returns whether this version supports long header 8-bit encoded
331 // connection ID lengths as described in draft-ietf-quic-invariants-06 and
332 // draft-ietf-quic-transport-22.
333 bool HasLengthPrefixedConnectionIds() const;
fayang5f135052019-08-22 17:59:40 -0700334
335 // Returns whether this version supports IETF style anti-amplification limit,
336 // i.e., server will send no more than FLAGS_quic_anti_amplification_factor
337 // times received bytes until address can be validated.
338 bool SupportsAntiAmplificationLimit() const;
fayang58f71072019-11-05 08:47:02 -0800339
340 // Returns true if this version can send coalesced packets.
341 bool CanSendCoalescedPackets() const;
dschinazi97da52b2020-01-13 15:44:43 -0800342
343 // Returns true if this version supports the old Google-style Alt-Svc
344 // advertisement format.
345 bool SupportsGoogleAltSvcFormat() const;
346
347 // Returns true if |transport_version| uses IETF invariant headers.
348 bool HasIetfInvariantHeader() const;
349
350 // Returns true if |transport_version| supports MESSAGE frames.
351 bool SupportsMessageFrames() const;
352
353 // If true, HTTP/3 instead of gQUIC will be used at the HTTP layer.
354 // Notable changes are:
355 // * Headers stream no longer exists.
356 // * PRIORITY, HEADERS are moved from headers stream to HTTP/3 control stream.
357 // * PUSH_PROMISE is moved to request stream.
358 // * Unidirectional streams will have their first byte as a stream type.
359 // * HEADERS frames are compressed using QPACK.
360 // * DATA frame has frame headers.
361 // * GOAWAY is moved to HTTP layer.
362 bool UsesHttp3() const;
363
364 // Returns whether the transport_version supports the variable length integer
365 // length field as defined by IETF QUIC draft-13 and later.
366 bool HasLongHeaderLengths() const;
367
368 // Returns whether |transport_version| uses CRYPTO frames for the handshake
369 // instead of stream 1.
370 bool UsesCryptoFrames() const;
371
372 // Returns whether |transport_version| makes use of IETF QUIC
373 // frames or not.
374 bool HasIetfQuicFrames() const;
fayang01062942020-01-22 07:23:23 -0800375
376 // Returns true if this parsed version supports handshake done.
377 bool HasHandshakeDone() const;
dschinazi7b8f0c72020-03-02 13:17:57 -0800378
379 // Returns true if this version uses variable-length integers when
380 // encoding transport parameter types and lengths.
381 bool HasVarIntTransportParams() const;
dschinazi67507492020-04-24 12:10:39 -0700382
dschinazi2c78aac2020-05-21 17:21:58 -0700383 // Returns true if this version uses transport parameters to authenticate all
384 // the connection IDs used during the handshake.
385 bool AuthenticatesHandshakeConnectionIds() const;
386
dschinazi67507492020-04-24 12:10:39 -0700387 // Returns whether this version uses PROTOCOL_TLS1_3.
388 bool UsesTls() const;
389
390 // Returns whether this version uses PROTOCOL_QUIC_CRYPTO.
391 bool UsesQuicCrypto() const;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500392};
393
394QUIC_EXPORT_PRIVATE ParsedQuicVersion UnsupportedQuicVersion();
395
dschinazi5a354c92019-05-09 12:18:53 -0700396QUIC_EXPORT_PRIVATE ParsedQuicVersion QuicVersionReservedForNegotiation();
397
dschinazi6458eb32020-06-23 12:38:41 -0700398// Outer version used when encapsulating other packets using the Legacy Version
399// Encapsulation feature.
400QUIC_EXPORT_PRIVATE ParsedQuicVersion LegacyVersionForEncapsulation();
401
QUICHE teama6ef0a62019-03-07 20:34:33 -0500402QUIC_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
403 const ParsedQuicVersion& version);
404
405using ParsedQuicVersionVector = std::vector<ParsedQuicVersion>;
406
dschinazi1ac7f012020-04-06 13:08:56 -0700407QUIC_EXPORT_PRIVATE std::ostream& operator<<(
408 std::ostream& os,
409 const ParsedQuicVersionVector& versions);
410
QUICHE teama6ef0a62019-03-07 20:34:33 -0500411// Representation of the on-the-wire QUIC version number. Will be written/read
412// to the wire in network-byte-order.
413using QuicVersionLabel = uint32_t;
414using QuicVersionLabelVector = std::vector<QuicVersionLabel>;
415
dschinazi1ac7f012020-04-06 13:08:56 -0700416QUIC_EXPORT_PRIVATE std::ostream& operator<<(
417 std::ostream& os,
418 const QuicVersionLabelVector& version_labels);
419
QUICHE teama6ef0a62019-03-07 20:34:33 -0500420// This vector contains all crypto handshake protocols that are supported.
vasilvv228602e2020-02-06 01:11:49 -0800421constexpr std::array<HandshakeProtocol, 2> SupportedHandshakeProtocols() {
dschinazi0a9c20d2020-04-07 14:04:55 -0700422 return {PROTOCOL_TLS1_3, PROTOCOL_QUIC_CRYPTO};
vasilvv228602e2020-02-06 01:11:49 -0800423}
QUICHE teama6ef0a62019-03-07 20:34:33 -0500424
dschinazi47692202020-07-30 11:09:42 -0700425constexpr std::array<ParsedQuicVersion, 8> SupportedVersions() {
dschinazic4c0e392020-03-16 11:22:09 -0700426 return {
dschinazi6ab45242020-06-23 00:20:37 -0700427 ParsedQuicVersion::Draft29(), ParsedQuicVersion::Draft27(),
dschinazi47692202020-07-30 11:09:42 -0700428 ParsedQuicVersion::Draft25(), ParsedQuicVersion::T051(),
429 ParsedQuicVersion::T050(), ParsedQuicVersion::Q050(),
430 ParsedQuicVersion::Q046(), ParsedQuicVersion::Q043(),
dschinazic4c0e392020-03-16 11:22:09 -0700431 };
vasilvv228602e2020-02-06 01:11:49 -0800432}
nharper2891b2d2020-01-14 16:46:07 -0800433
vasilvv228602e2020-02-06 01:11:49 -0800434using QuicTransportVersionVector = std::vector<QuicTransportVersion>;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500435
dschinazi1ac7f012020-04-06 13:08:56 -0700436QUIC_EXPORT_PRIVATE std::ostream& operator<<(
437 std::ostream& os,
438 const QuicTransportVersionVector& transport_versions);
439
QUICHE teama6ef0a62019-03-07 20:34:33 -0500440// Returns a vector of QUIC versions in kSupportedTransportVersions.
441QUIC_EXPORT_PRIVATE QuicTransportVersionVector AllSupportedTransportVersions();
442
443// Returns a vector of QUIC versions that is the cartesian product of
444// kSupportedTransportVersions and kSupportedHandshakeProtocols.
445QUIC_EXPORT_PRIVATE ParsedQuicVersionVector AllSupportedVersions();
446
QUICHE teama6ef0a62019-03-07 20:34:33 -0500447// Returns a vector of QUIC versions that is the cartesian product of
448// kSupportedTransportVersions and kSupportedHandshakeProtocols, with any
449// versions disabled by flags excluded.
450QUIC_EXPORT_PRIVATE ParsedQuicVersionVector CurrentSupportedVersions();
451
452// Returns a vector of QUIC versions from |versions| which exclude any versions
453// which are disabled by flags.
QUICHE teama6ef0a62019-03-07 20:34:33 -0500454QUIC_EXPORT_PRIVATE ParsedQuicVersionVector
455FilterSupportedVersions(ParsedQuicVersionVector versions);
456
bnc36b7a032020-03-04 10:27:23 -0800457// Returns a subset of AllSupportedVersions() with
458// handshake_protocol == PROTOCOL_QUIC_CRYPTO, in the same order.
459// Deprecated; only to be used in components that do not yet support
460// PROTOCOL_TLS1_3.
dschinazi75448772020-03-05 05:09:55 -0800461QUIC_EXPORT_PRIVATE ParsedQuicVersionVector
462AllSupportedVersionsWithQuicCrypto();
bnc36b7a032020-03-04 10:27:23 -0800463
464// Returns a subset of CurrentSupportedVersions() with
465// handshake_protocol == PROTOCOL_QUIC_CRYPTO, in the same order.
dschinazi75448772020-03-05 05:09:55 -0800466QUIC_EXPORT_PRIVATE ParsedQuicVersionVector
467CurrentSupportedVersionsWithQuicCrypto();
bnc36b7a032020-03-04 10:27:23 -0800468
dschinazi8c628f22020-04-09 16:40:11 -0700469// Returns a subset of AllSupportedVersions() with
470// handshake_protocol == PROTOCOL_TLS1_3, in the same order.
471QUIC_EXPORT_PRIVATE ParsedQuicVersionVector AllSupportedVersionsWithTls();
472
fayang3b3e3012020-03-26 10:31:13 -0700473// Returns a subset of CurrentSupportedVersions() with handshake_protocol ==
474// PROTOCOL_TLS1_3.
475QUIC_EXPORT_PRIVATE ParsedQuicVersionVector CurrentSupportedVersionsWithTls();
476
QUICHE teama6ef0a62019-03-07 20:34:33 -0500477// Returns QUIC version of |index| in result of |versions|. Returns
478// QUIC_VERSION_UNSUPPORTED if |index| is out of bounds.
479QUIC_EXPORT_PRIVATE QuicTransportVersionVector
480VersionOfIndex(const QuicTransportVersionVector& versions, int index);
481
482// Returns QUIC version of |index| in result of |versions|. Returns
483// UnsupportedQuicVersion() if |index| is out of bounds.
484QUIC_EXPORT_PRIVATE ParsedQuicVersionVector
485ParsedVersionOfIndex(const ParsedQuicVersionVector& versions, int index);
486
487// Returns a vector of QuicTransportVersions corresponding to just the transport
488// versions in |versions|. If the input vector contains multiple parsed versions
489// with different handshake protocols (but the same transport version), that
490// transport version will appear in the resulting vector multiple times.
491QUIC_EXPORT_PRIVATE QuicTransportVersionVector
492ParsedVersionsToTransportVersions(const ParsedQuicVersionVector& versions);
493
494// QuicVersionLabel is written to and read from the wire, but we prefer to use
495// the more readable ParsedQuicVersion at other levels.
496// Helper function which translates from a QuicVersionLabel to a
497// ParsedQuicVersion.
498QUIC_EXPORT_PRIVATE ParsedQuicVersion
499ParseQuicVersionLabel(QuicVersionLabel version_label);
500
dschinazicee73cd2020-03-05 18:20:50 -0800501// Parses a QUIC version string such as "Q043" or "T050". Also supports parsing
502// ALPN such as "h3-25" or "h3-Q050". For PROTOCOL_QUIC_CRYPTO versions, also
503// supports parsing numbers such as "46".
dschinazi8ae60012019-04-04 18:07:27 -0700504QUIC_EXPORT_PRIVATE ParsedQuicVersion
dschinazicee73cd2020-03-05 18:20:50 -0800505ParseQuicVersionString(quiche::QuicheStringPiece version_string);
506
507// Parses a comma-separated list of QUIC version strings. Supports parsing by
508// label, ALPN and numbers for PROTOCOL_QUIC_CRYPTO. Skips unknown versions.
509// For example: "h3-25,Q050,46".
510QUIC_EXPORT_PRIVATE ParsedQuicVersionVector
511ParseQuicVersionVectorString(quiche::QuicheStringPiece versions_string);
dschinazi8ae60012019-04-04 18:07:27 -0700512
QUICHE teama6ef0a62019-03-07 20:34:33 -0500513// Constructs a QuicVersionLabel from the provided ParsedQuicVersion.
514QUIC_EXPORT_PRIVATE QuicVersionLabel
515CreateQuicVersionLabel(ParsedQuicVersion parsed_version);
516
517// Constructs a QuicVersionLabelVector from the provided
518// ParsedQuicVersionVector.
519QUIC_EXPORT_PRIVATE QuicVersionLabelVector
520CreateQuicVersionLabelVector(const ParsedQuicVersionVector& versions);
521
522// QuicVersionLabel is written to and read from the wire, but we prefer to use
523// the more readable QuicTransportVersion at other levels.
524// Helper function which translates from a QuicTransportVersion to a
525// QuicVersionLabel. Returns 0 if |version| is unsupported.
526QUIC_EXPORT_PRIVATE QuicVersionLabel
527QuicVersionToQuicVersionLabel(QuicTransportVersion transport_version);
528
529// Helper function which translates from a QuicVersionLabel to a string.
vasilvvc48c8712019-03-11 13:38:16 -0700530QUIC_EXPORT_PRIVATE std::string QuicVersionLabelToString(
531 QuicVersionLabel version_label);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500532
533// Returns |separator|-separated list of string representations of
534// QuicVersionLabel values in the supplied |version_labels| vector. The values
535// after the (0-based) |skip_after_nth_version|'th are skipped.
vasilvvc48c8712019-03-11 13:38:16 -0700536QUIC_EXPORT_PRIVATE std::string QuicVersionLabelVectorToString(
537 const QuicVersionLabelVector& version_labels,
538 const std::string& separator,
539 size_t skip_after_nth_version);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500540
541// Returns comma separated list of string representations of QuicVersionLabel
542// values in the supplied |version_labels| vector.
vasilvvc48c8712019-03-11 13:38:16 -0700543QUIC_EXPORT_PRIVATE inline std::string QuicVersionLabelVectorToString(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500544 const QuicVersionLabelVector& version_labels) {
545 return QuicVersionLabelVectorToString(version_labels, ",",
546 std::numeric_limits<size_t>::max());
547}
548
549// Returns appropriate QuicTransportVersion from a QuicVersionLabel.
550// Returns QUIC_VERSION_UNSUPPORTED if |version_label| cannot be understood.
551QUIC_EXPORT_PRIVATE QuicTransportVersion
552QuicVersionLabelToQuicVersion(QuicVersionLabel version_label);
553
554// Returns the HandshakeProtocol used with the given |version_label|, returning
555// PROTOCOL_UNSUPPORTED if it is unknown.
556QUIC_EXPORT_PRIVATE HandshakeProtocol
557QuicVersionLabelToHandshakeProtocol(QuicVersionLabel version_label);
558
QUICHE teama6ef0a62019-03-07 20:34:33 -0500559// Helper function which translates from a ParsedQuicVersion to a string.
560// Returns strings corresponding to the on-the-wire tag.
vasilvvc48c8712019-03-11 13:38:16 -0700561QUIC_EXPORT_PRIVATE std::string ParsedQuicVersionToString(
562 ParsedQuicVersion version);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500563
564// Returns comma separated list of string representations of
565// QuicTransportVersion enum values in the supplied |versions| vector.
vasilvvc48c8712019-03-11 13:38:16 -0700566QUIC_EXPORT_PRIVATE std::string QuicTransportVersionVectorToString(
567 const QuicTransportVersionVector& versions);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500568
569// Returns comma separated list of string representations of ParsedQuicVersion
570// values in the supplied |versions| vector.
vasilvvc48c8712019-03-11 13:38:16 -0700571QUIC_EXPORT_PRIVATE std::string ParsedQuicVersionVectorToString(
572 const ParsedQuicVersionVector& versions);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500573
574// Returns |separator|-separated list of string representations of
575// ParsedQuicVersion values in the supplied |versions| vector. The values after
576// the (0-based) |skip_after_nth_version|'th are skipped.
vasilvvc48c8712019-03-11 13:38:16 -0700577QUIC_EXPORT_PRIVATE std::string ParsedQuicVersionVectorToString(
578 const ParsedQuicVersionVector& versions,
579 const std::string& separator,
580 size_t skip_after_nth_version);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500581
582// Returns comma separated list of string representations of ParsedQuicVersion
583// values in the supplied |versions| vector.
vasilvvc48c8712019-03-11 13:38:16 -0700584QUIC_EXPORT_PRIVATE inline std::string ParsedQuicVersionVectorToString(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500585 const ParsedQuicVersionVector& versions) {
586 return ParsedQuicVersionVectorToString(versions, ",",
587 std::numeric_limits<size_t>::max());
588}
589
fayangd4291e42019-05-30 10:31:21 -0700590// Returns true if |transport_version| uses IETF invariant headers.
dschinazi0da43902020-01-17 15:26:14 -0800591QUIC_EXPORT_PRIVATE constexpr bool VersionHasIetfInvariantHeader(
fayangd4291e42019-05-30 10:31:21 -0700592 QuicTransportVersion transport_version) {
593 return transport_version > QUIC_VERSION_43;
594}
595
596// Returns true if |transport_version| supports MESSAGE frames.
dschinazi0da43902020-01-17 15:26:14 -0800597QUIC_EXPORT_PRIVATE constexpr bool VersionSupportsMessageFrames(
fayangd4291e42019-05-30 10:31:21 -0700598 QuicTransportVersion transport_version) {
dschinaziceed8662020-07-14 09:37:05 -0700599 // MESSAGE frames were added in version 45.
600 return transport_version > QUIC_VERSION_43;
fayangd4291e42019-05-30 10:31:21 -0700601}
602
renjietanga29a96a2019-10-10 12:47:50 -0700603// If true, HTTP/3 instead of gQUIC will be used at the HTTP layer.
604// Notable changes are:
605// * Headers stream no longer exists.
606// * PRIORITY, HEADERS are moved from headers stream to HTTP/3 control stream.
607// * PUSH_PROMISE is moved to request stream.
608// * Unidirectional streams will have their first byte as a stream type.
609// * HEADERS frames are compressed using QPACK.
610// * DATA frame has frame headers.
611// * GOAWAY is moved to HTTP layer.
dschinazi0da43902020-01-17 15:26:14 -0800612QUIC_EXPORT_PRIVATE constexpr bool VersionUsesHttp3(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500613 QuicTransportVersion transport_version) {
dschinazi47692202020-07-30 11:09:42 -0700614 return transport_version > QUIC_VERSION_51;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500615}
616
QUICHE teama6ef0a62019-03-07 20:34:33 -0500617// Returns whether the transport_version supports the variable length integer
618// length field as defined by IETF QUIC draft-13 and later.
dschinazi0da43902020-01-17 15:26:14 -0800619QUIC_EXPORT_PRIVATE constexpr bool QuicVersionHasLongHeaderLengths(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500620 QuicTransportVersion transport_version) {
dschinaziceed8662020-07-14 09:37:05 -0700621 // Long header lengths were added in version 49.
622 return transport_version > QUIC_VERSION_46;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500623}
624
fkastenholz305e1732019-06-18 05:01:22 -0700625// Returns whether |transport_version| makes use of IETF QUIC
626// frames or not.
dschinazi0da43902020-01-17 15:26:14 -0800627QUIC_EXPORT_PRIVATE constexpr bool VersionHasIetfQuicFrames(
fkastenholz305e1732019-06-18 05:01:22 -0700628 QuicTransportVersion transport_version) {
dschinaziceed8662020-07-14 09:37:05 -0700629 return VersionUsesHttp3(transport_version);
fkastenholz305e1732019-06-18 05:01:22 -0700630}
631
dschinazi48ac9192019-07-31 00:07:26 -0700632// Returns whether this version supports long header 8-bit encoded
633// connection ID lengths as described in draft-ietf-quic-invariants-06 and
634// draft-ietf-quic-transport-22.
635QUIC_EXPORT_PRIVATE bool VersionHasLengthPrefixedConnectionIds(
636 QuicTransportVersion transport_version);
637
rcheb78dbb2019-10-26 08:37:15 -0700638// Returns true if this version supports the old Google-style Alt-Svc
639// advertisement format.
640QUIC_EXPORT_PRIVATE bool VersionSupportsGoogleAltSvcFormat(
641 QuicTransportVersion transport_version);
642
dschinazi97da52b2020-01-13 15:44:43 -0800643// Returns whether this version allows server connection ID lengths that are
644// not 64 bits.
645QUIC_EXPORT_PRIVATE bool VersionAllowsVariableLengthConnectionIds(
646 QuicTransportVersion transport_version);
647
dschinazi48ac9192019-07-31 00:07:26 -0700648// Returns whether this version label supports long header 4-bit encoded
649// connection ID lengths as described in draft-ietf-quic-invariants-05 and
650// draft-ietf-quic-transport-21.
651QUIC_EXPORT_PRIVATE bool QuicVersionLabelUses4BitConnectionIdLength(
652 QuicVersionLabel version_label);
653
dschinazi35e749e2019-04-09 09:36:04 -0700654// Returns the ALPN string to use in TLS for this version of QUIC.
655QUIC_EXPORT_PRIVATE std::string AlpnForVersion(
656 ParsedQuicVersion parsed_version);
657
rcha702be22019-08-30 15:20:12 -0700658// Initializes support for the provided IETF draft version by setting the
659// correct flags.
660QUIC_EXPORT_PRIVATE void QuicVersionInitializeSupportForIetfDraft();
dschinazi8ae60012019-04-04 18:07:27 -0700661
dschinazi5a50d932020-06-17 12:43:36 -0700662// Configures the flags required to enable support for this version of QUIC.
663QUIC_EXPORT_PRIVATE void QuicEnableVersion(const ParsedQuicVersion& version);
664
665// Configures the flags required to disable support for this version of QUIC.
666QUIC_EXPORT_PRIVATE void QuicDisableVersion(const ParsedQuicVersion& version);
667
668// Returns whether support for this version of QUIC is currently enabled.
669QUIC_EXPORT_PRIVATE bool QuicVersionIsEnabled(const ParsedQuicVersion& version);
dschinazi8ae60012019-04-04 18:07:27 -0700670
QUICHE teama6ef0a62019-03-07 20:34:33 -0500671} // namespace quic
672
673#endif // QUICHE_QUIC_CORE_QUIC_VERSIONS_H_