|  | // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | // Definitions and utility functions related to handling of QUIC versions. | 
|  | // | 
|  | // QUIC versions are encoded over the wire as an opaque 32bit field. The wire | 
|  | // encoding is represented in memory as a QuicVersionLabel type (which is an | 
|  | // alias to uint32_t). Conceptual versions are represented in memory as | 
|  | // ParsedQuicVersion. | 
|  | // | 
|  | // We currently support two kinds of QUIC versions, GoogleQUIC and IETF QUIC. | 
|  | // | 
|  | // All GoogleQUIC versions use a wire encoding that matches the following regex | 
|  | // when converted to ASCII: "[QT]0\d\d" (e.g. Q050). Q or T distinguishes the | 
|  | // type of handshake used (Q for the QUIC_CRYPTO handshake, T for the QUIC+TLS | 
|  | // handshake), and the two digits at the end contain the numeric value of | 
|  | // the transport version used. | 
|  | // | 
|  | // All IETF QUIC versions use the wire encoding described in: | 
|  | // https://tools.ietf.org/html/draft-ietf-quic-transport | 
|  |  | 
|  | #ifndef QUICHE_QUIC_CORE_QUIC_VERSIONS_H_ | 
|  | #define QUICHE_QUIC_CORE_QUIC_VERSIONS_H_ | 
|  |  | 
|  | #include <string> | 
|  | #include <vector> | 
|  |  | 
|  | #include "absl/base/macros.h" | 
|  | #include "absl/strings/string_view.h" | 
|  | #include "quic/core/quic_tag.h" | 
|  | #include "quic/core/quic_types.h" | 
|  | #include "quic/platform/api/quic_export.h" | 
|  |  | 
|  | namespace quic { | 
|  |  | 
|  | // The list of existing QUIC transport versions. Note that QUIC versions are | 
|  | // sent over the wire as an encoding of ParsedQuicVersion, which requires a | 
|  | // QUIC transport version and handshake protocol. For transport versions of the | 
|  | // form QUIC_VERSION_XX where XX is decimal, the enum numeric value is | 
|  | // guaranteed to match the name. Older deprecated transport versions are | 
|  | // documented in comments below. | 
|  | enum QuicTransportVersion { | 
|  | // Special case to indicate unknown/unsupported QUIC version. | 
|  | QUIC_VERSION_UNSUPPORTED = 0, | 
|  |  | 
|  | // Version 1 was the first version of QUIC that supported versioning. | 
|  | // Version 2 decoupled versioning of non-cryptographic parameters from the | 
|  | //           SCFG. | 
|  | // Version 3 moved public flags into the beginning of the packet. | 
|  | // Version 4 added support for variable-length connection IDs. | 
|  | // Version 5 made specifying FEC groups optional. | 
|  | // Version 6 introduced variable-length packet numbers. | 
|  | // Version 7 introduced a lower-overhead encoding for stream frames. | 
|  | // Version 8 made salt length equal to digest length for the RSA-PSS | 
|  | //           signatures. | 
|  | // Version 9 added stream priority. | 
|  | // Version 10 redid the frame type numbering. | 
|  | // Version 11 reduced the length of null encryption authentication tag | 
|  | //            from 16 to 12 bytes. | 
|  | // Version 12 made the sequence numbers in the ACK frames variable-sized. | 
|  | // Version 13 added the dedicated header stream. | 
|  | // Version 14 added byte_offset to RST_STREAM frame. | 
|  | // Version 15 added a list of packets recovered using FEC to the ACK frame. | 
|  | // Version 16 added STOP_WAITING frame. | 
|  | // Version 17 added per-stream flow control. | 
|  | // Version 18 added PING frame. | 
|  | // Version 19 added connection-level flow control | 
|  | // Version 20 allowed to set stream- and connection-level flow control windows | 
|  | //            to different values. | 
|  | // Version 21 made header and crypto streams flow-controlled. | 
|  | // Version 22 added support for SCUP (server config update) messages. | 
|  | // Version 23 added timestamps into the ACK frame. | 
|  | // Version 24 added SPDY/4 header compression. | 
|  | // Version 25 added support for SPDY/4 header keys and removed error_details | 
|  | //            from RST_STREAM frame. | 
|  | // Version 26 added XLCT (expected leaf certificate) tag into CHLO. | 
|  | // Version 27 added a nonce into SHLO. | 
|  | // Version 28 allowed receiver to refuse creating a requested stream. | 
|  | // Version 29 added support for QUIC_STREAM_NO_ERROR. | 
|  | // Version 30 added server-side support for certificate transparency. | 
|  | // Version 31 incorporated the hash of CHLO into the crypto proof supplied by | 
|  | //            the server. | 
|  | // Version 32 removed FEC-related fields from wire format. | 
|  | // Version 33 added diversification nonces. | 
|  | // Version 34 removed entropy bits from packets and ACK frames, removed | 
|  | //            private flag from packet header and changed the ACK format to | 
|  | //            specify ranges of packets acknowledged rather than missing | 
|  | //            ranges. | 
|  | // Version 35 allows endpoints to independently set stream limit. | 
|  | // Version 36 added support for forced head-of-line blocking experiments. | 
|  | // Version 37 added perspective into null encryption. | 
|  | // Version 38 switched to IETF padding frame format and support for NSTP (no | 
|  | //            stop waiting frame) connection option. | 
|  |  | 
|  | // Version 39 writes integers and floating numbers in big endian, stops acking | 
|  | // acks, sends a connection level WINDOW_UPDATE every 20 sent packets which do | 
|  | // not contain retransmittable frames. | 
|  |  | 
|  | // Version 40 was an attempt to convert QUIC to IETF frame format; it was | 
|  | //            never shipped due to a bug. | 
|  | // Version 41 was a bugfix for version 40.  The working group changed the wire | 
|  | //            format before it shipped, which caused it to be never shipped | 
|  | //            and all the changes from it to be reverted.  No changes from v40 | 
|  | //            or v41 are present in subsequent versions. | 
|  | // Version 42 allowed receiving overlapping stream data. | 
|  |  | 
|  | QUIC_VERSION_43 = 43,  // PRIORITY frames are sent by client and accepted by | 
|  | // server. | 
|  | // Version 44 used IETF header format from draft-ietf-quic-invariants-05. | 
|  |  | 
|  | // Version 45 added MESSAGE frame. | 
|  |  | 
|  | QUIC_VERSION_46 = 46,  // Use IETF draft-17 header format with demultiplexing | 
|  | // bit. | 
|  | // Version 47 added variable-length QUIC server connection IDs. | 
|  | // Version 48 added CRYPTO frames for the handshake. | 
|  | // Version 49 added client connection IDs, long header lengths, and the IETF | 
|  | // header format from draft-ietf-quic-invariants-06 | 
|  | QUIC_VERSION_50 = 50,  // Header protection and initial obfuscators. | 
|  | // Number 51 was T051 which used draft-29 features but with GoogleQUIC frames. | 
|  | // Number 70 used to represent draft-ietf-quic-transport-25. | 
|  | // Number 71 used to represent draft-ietf-quic-transport-27. | 
|  | // Number 72 used to represent draft-ietf-quic-transport-28. | 
|  | QUIC_VERSION_IETF_DRAFT_29 = 73,  // draft-ietf-quic-transport-29. | 
|  | QUIC_VERSION_IETF_RFC_V1 = 80,    // RFC 9000. | 
|  | // Version 99 was a dumping ground for IETF QUIC changes which were not yet | 
|  | // ready for production between 2018-02 and 2020-02. | 
|  |  | 
|  | // QUIC_VERSION_RESERVED_FOR_NEGOTIATION is sent over the wire as ?a?a?a?a | 
|  | // which is part of a range reserved by the IETF for version negotiation | 
|  | // testing (see the "Versions" section of draft-ietf-quic-transport). | 
|  | // This version is intentionally meant to never be supported to trigger | 
|  | // version negotiation when proposed by clients and to prevent client | 
|  | // ossification when sent by servers. | 
|  | QUIC_VERSION_RESERVED_FOR_NEGOTIATION = 999, | 
|  | }; | 
|  |  | 
|  | // Helper function which translates from a QuicTransportVersion to a string. | 
|  | // Returns strings corresponding to enum names (e.g. QUIC_VERSION_6). | 
|  | QUIC_EXPORT_PRIVATE std::string QuicVersionToString( | 
|  | QuicTransportVersion transport_version); | 
|  |  | 
|  | // The crypto handshake protocols that can be used with QUIC. | 
|  | // We are planning on eventually deprecating PROTOCOL_QUIC_CRYPTO in favor of | 
|  | // PROTOCOL_TLS1_3. | 
|  | enum HandshakeProtocol { | 
|  | PROTOCOL_UNSUPPORTED, | 
|  | PROTOCOL_QUIC_CRYPTO, | 
|  | PROTOCOL_TLS1_3, | 
|  | }; | 
|  |  | 
|  | // Helper function which translates from a HandshakeProtocol to a string. | 
|  | QUIC_EXPORT_PRIVATE std::string HandshakeProtocolToString( | 
|  | HandshakeProtocol handshake_protocol); | 
|  |  | 
|  | // Returns whether |transport_version| uses CRYPTO frames for the handshake | 
|  | // instead of stream 1. | 
|  | QUIC_EXPORT_PRIVATE constexpr bool QuicVersionUsesCryptoFrames( | 
|  | QuicTransportVersion transport_version) { | 
|  | // CRYPTO frames were added in version 48. | 
|  | return transport_version > QUIC_VERSION_46; | 
|  | } | 
|  |  | 
|  | // Returns whether this combination of handshake protocol and transport | 
|  | // version is allowed. For example, {PROTOCOL_TLS1_3, QUIC_VERSION_43} is NOT | 
|  | // allowed as TLS requires crypto frames which v43 does not support. Note that | 
|  | // UnsupportedQuicVersion is a valid version. | 
|  | QUIC_EXPORT_PRIVATE constexpr bool ParsedQuicVersionIsValid( | 
|  | HandshakeProtocol handshake_protocol, | 
|  | QuicTransportVersion transport_version) { | 
|  | bool transport_version_is_valid = false; | 
|  | constexpr QuicTransportVersion valid_transport_versions[] = { | 
|  | QUIC_VERSION_IETF_RFC_V1, | 
|  | QUIC_VERSION_IETF_DRAFT_29, | 
|  | QUIC_VERSION_50, | 
|  | QUIC_VERSION_46, | 
|  | QUIC_VERSION_43, | 
|  | QUIC_VERSION_RESERVED_FOR_NEGOTIATION, | 
|  | QUIC_VERSION_UNSUPPORTED, | 
|  | }; | 
|  | for (size_t i = 0; i < ABSL_ARRAYSIZE(valid_transport_versions); ++i) { | 
|  | if (transport_version == valid_transport_versions[i]) { | 
|  | transport_version_is_valid = true; | 
|  | break; | 
|  | } | 
|  | } | 
|  | if (!transport_version_is_valid) { | 
|  | return false; | 
|  | } | 
|  | switch (handshake_protocol) { | 
|  | case PROTOCOL_UNSUPPORTED: | 
|  | return transport_version == QUIC_VERSION_UNSUPPORTED; | 
|  | case PROTOCOL_QUIC_CRYPTO: | 
|  | return transport_version != QUIC_VERSION_UNSUPPORTED && | 
|  | transport_version != QUIC_VERSION_RESERVED_FOR_NEGOTIATION && | 
|  | transport_version != QUIC_VERSION_IETF_DRAFT_29 && | 
|  | transport_version != QUIC_VERSION_IETF_RFC_V1; | 
|  | case PROTOCOL_TLS1_3: | 
|  | return transport_version != QUIC_VERSION_UNSUPPORTED && | 
|  | transport_version != QUIC_VERSION_50 && | 
|  | QuicVersionUsesCryptoFrames(transport_version); | 
|  | } | 
|  | return false; | 
|  | } | 
|  |  | 
|  | // A parsed QUIC version label which determines that handshake protocol | 
|  | // and the transport version. | 
|  | struct QUIC_EXPORT_PRIVATE ParsedQuicVersion { | 
|  | HandshakeProtocol handshake_protocol; | 
|  | QuicTransportVersion transport_version; | 
|  |  | 
|  | constexpr ParsedQuicVersion(HandshakeProtocol handshake_protocol, | 
|  | QuicTransportVersion transport_version) | 
|  | : handshake_protocol(handshake_protocol), | 
|  | transport_version(transport_version) { | 
|  | QUICHE_DCHECK( | 
|  | ParsedQuicVersionIsValid(handshake_protocol, transport_version)) | 
|  | << QuicVersionToString(transport_version) << " " | 
|  | << HandshakeProtocolToString(handshake_protocol); | 
|  | } | 
|  |  | 
|  | constexpr ParsedQuicVersion(const ParsedQuicVersion& other) | 
|  | : ParsedQuicVersion(other.handshake_protocol, other.transport_version) {} | 
|  |  | 
|  | ParsedQuicVersion& operator=(const ParsedQuicVersion& other) { | 
|  | QUICHE_DCHECK(ParsedQuicVersionIsValid(other.handshake_protocol, | 
|  | other.transport_version)) | 
|  | << QuicVersionToString(other.transport_version) << " " | 
|  | << HandshakeProtocolToString(other.handshake_protocol); | 
|  | if (this != &other) { | 
|  | handshake_protocol = other.handshake_protocol; | 
|  | transport_version = other.transport_version; | 
|  | } | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | bool operator==(const ParsedQuicVersion& other) const { | 
|  | return handshake_protocol == other.handshake_protocol && | 
|  | transport_version == other.transport_version; | 
|  | } | 
|  |  | 
|  | bool operator!=(const ParsedQuicVersion& other) const { | 
|  | return handshake_protocol != other.handshake_protocol || | 
|  | transport_version != other.transport_version; | 
|  | } | 
|  |  | 
|  | static constexpr ParsedQuicVersion RFCv1() { | 
|  | return ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_IETF_RFC_V1); | 
|  | } | 
|  |  | 
|  | static constexpr ParsedQuicVersion Draft29() { | 
|  | return ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_IETF_DRAFT_29); | 
|  | } | 
|  |  | 
|  | static constexpr ParsedQuicVersion Q050() { | 
|  | return ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_50); | 
|  | } | 
|  |  | 
|  | static constexpr ParsedQuicVersion Q046() { | 
|  | return ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_46); | 
|  | } | 
|  |  | 
|  | static constexpr ParsedQuicVersion Q043() { | 
|  | return ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_43); | 
|  | } | 
|  |  | 
|  | static constexpr ParsedQuicVersion Unsupported() { | 
|  | return ParsedQuicVersion(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED); | 
|  | } | 
|  |  | 
|  | static constexpr ParsedQuicVersion ReservedForNegotiation() { | 
|  | return ParsedQuicVersion(PROTOCOL_TLS1_3, | 
|  | QUIC_VERSION_RESERVED_FOR_NEGOTIATION); | 
|  | } | 
|  |  | 
|  | // Returns whether our codebase understands this version. This should only be | 
|  | // called on valid versions, see ParsedQuicVersionIsValid. Assuming the | 
|  | // version is valid, IsKnown returns whether the version is not | 
|  | // UnsupportedQuicVersion. | 
|  | bool IsKnown() const; | 
|  |  | 
|  | bool KnowsWhichDecrypterToUse() const; | 
|  |  | 
|  | // Returns whether this version uses keys derived from the Connection ID for | 
|  | // ENCRYPTION_INITIAL keys (instead of NullEncrypter/NullDecrypter). | 
|  | bool UsesInitialObfuscators() const; | 
|  |  | 
|  | // Indicates that this QUIC version does not have an enforced minimum value | 
|  | // for flow control values negotiated during the handshake. | 
|  | bool AllowsLowFlowControlLimits() const; | 
|  |  | 
|  | // Returns whether header protection is used in this version of QUIC. | 
|  | bool HasHeaderProtection() const; | 
|  |  | 
|  | // Returns whether this version supports IETF RETRY packets. | 
|  | bool SupportsRetry() const; | 
|  |  | 
|  | // Returns true if this version sends variable length packet number in long | 
|  | // header. | 
|  | bool SendsVariableLengthPacketNumberInLongHeader() const; | 
|  |  | 
|  | // Returns whether this version allows server connection ID lengths | 
|  | // that are not 64 bits. | 
|  | bool AllowsVariableLengthConnectionIds() const; | 
|  |  | 
|  | // Returns whether this version supports client connection ID. | 
|  | bool SupportsClientConnectionIds() const; | 
|  |  | 
|  | // Returns whether this version supports long header 8-bit encoded | 
|  | // connection ID lengths as described in draft-ietf-quic-invariants-06 and | 
|  | // draft-ietf-quic-transport-22. | 
|  | bool HasLengthPrefixedConnectionIds() const; | 
|  |  | 
|  | // Returns whether this version supports IETF style anti-amplification limit, | 
|  | // i.e., server will send no more than FLAGS_quic_anti_amplification_factor | 
|  | // times received bytes until address can be validated. | 
|  | bool SupportsAntiAmplificationLimit() const; | 
|  |  | 
|  | // Returns true if this version can send coalesced packets. | 
|  | bool CanSendCoalescedPackets() const; | 
|  |  | 
|  | // Returns true if this version supports the old Google-style Alt-Svc | 
|  | // advertisement format. | 
|  | bool SupportsGoogleAltSvcFormat() const; | 
|  |  | 
|  | // Returns true if |transport_version| uses IETF invariant headers. | 
|  | bool HasIetfInvariantHeader() const; | 
|  |  | 
|  | // Returns true if |transport_version| supports MESSAGE frames. | 
|  | bool SupportsMessageFrames() const; | 
|  |  | 
|  | // If true, HTTP/3 instead of gQUIC will be used at the HTTP layer. | 
|  | // Notable changes are: | 
|  | // * Headers stream no longer exists. | 
|  | // * PRIORITY, HEADERS are moved from headers stream to HTTP/3 control stream. | 
|  | // * PUSH_PROMISE is moved to request stream. | 
|  | // * Unidirectional streams will have their first byte as a stream type. | 
|  | // * HEADERS frames are compressed using QPACK. | 
|  | // * DATA frame has frame headers. | 
|  | // * GOAWAY is moved to HTTP layer. | 
|  | bool UsesHttp3() const; | 
|  |  | 
|  | // Returns whether the transport_version supports the variable length integer | 
|  | // length field as defined by IETF QUIC draft-13 and later. | 
|  | bool HasLongHeaderLengths() const; | 
|  |  | 
|  | // Returns whether |transport_version| uses CRYPTO frames for the handshake | 
|  | // instead of stream 1. | 
|  | bool UsesCryptoFrames() const; | 
|  |  | 
|  | // Returns whether |transport_version| makes use of IETF QUIC | 
|  | // frames or not. | 
|  | bool HasIetfQuicFrames() const; | 
|  |  | 
|  | // Returns whether this version uses the legacy TLS extension codepoint. | 
|  | bool UsesLegacyTlsExtension() const; | 
|  |  | 
|  | // Returns whether this version uses PROTOCOL_TLS1_3. | 
|  | bool UsesTls() const; | 
|  |  | 
|  | // Returns whether this version uses PROTOCOL_QUIC_CRYPTO. | 
|  | bool UsesQuicCrypto() const; | 
|  | }; | 
|  |  | 
|  | QUIC_EXPORT_PRIVATE ParsedQuicVersion UnsupportedQuicVersion(); | 
|  |  | 
|  | QUIC_EXPORT_PRIVATE ParsedQuicVersion QuicVersionReservedForNegotiation(); | 
|  |  | 
|  | // Outer version used when encapsulating other packets using the Legacy Version | 
|  | // Encapsulation feature. | 
|  | QUIC_EXPORT_PRIVATE ParsedQuicVersion LegacyVersionForEncapsulation(); | 
|  |  | 
|  | QUIC_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os, | 
|  | const ParsedQuicVersion& version); | 
|  |  | 
|  | using ParsedQuicVersionVector = std::vector<ParsedQuicVersion>; | 
|  |  | 
|  | QUIC_EXPORT_PRIVATE std::ostream& operator<<( | 
|  | std::ostream& os, | 
|  | const ParsedQuicVersionVector& versions); | 
|  |  | 
|  | // Representation of the on-the-wire QUIC version number. Will be written/read | 
|  | // to the wire in network-byte-order. | 
|  | using QuicVersionLabel = uint32_t; | 
|  | using QuicVersionLabelVector = std::vector<QuicVersionLabel>; | 
|  |  | 
|  | QUIC_EXPORT_PRIVATE std::ostream& operator<<( | 
|  | std::ostream& os, | 
|  | const QuicVersionLabelVector& version_labels); | 
|  |  | 
|  | // This vector contains all crypto handshake protocols that are supported. | 
|  | constexpr std::array<HandshakeProtocol, 2> SupportedHandshakeProtocols() { | 
|  | return {PROTOCOL_TLS1_3, PROTOCOL_QUIC_CRYPTO}; | 
|  | } | 
|  |  | 
|  | constexpr std::array<ParsedQuicVersion, 5> SupportedVersions() { | 
|  | return { | 
|  | ParsedQuicVersion::RFCv1(), ParsedQuicVersion::Draft29(), | 
|  | ParsedQuicVersion::Q050(),  ParsedQuicVersion::Q046(), | 
|  | ParsedQuicVersion::Q043(), | 
|  | }; | 
|  | } | 
|  |  | 
|  | using QuicTransportVersionVector = std::vector<QuicTransportVersion>; | 
|  |  | 
|  | QUIC_EXPORT_PRIVATE std::ostream& operator<<( | 
|  | std::ostream& os, | 
|  | const QuicTransportVersionVector& transport_versions); | 
|  |  | 
|  | // Returns a vector of supported QUIC versions. | 
|  | QUIC_EXPORT_PRIVATE ParsedQuicVersionVector AllSupportedVersions(); | 
|  |  | 
|  | // Returns a vector of supported QUIC versions, with any versions disabled by | 
|  | // flags excluded. | 
|  | QUIC_EXPORT_PRIVATE ParsedQuicVersionVector CurrentSupportedVersions(); | 
|  |  | 
|  | // Returns a vector of QUIC versions from |versions| which exclude any versions | 
|  | // which are disabled by flags. | 
|  | QUIC_EXPORT_PRIVATE ParsedQuicVersionVector | 
|  | FilterSupportedVersions(ParsedQuicVersionVector versions); | 
|  |  | 
|  | // Returns a subset of AllSupportedVersions() with | 
|  | // handshake_protocol == PROTOCOL_QUIC_CRYPTO, in the same order. | 
|  | // Deprecated; only to be used in components that do not yet support | 
|  | // PROTOCOL_TLS1_3. | 
|  | QUIC_EXPORT_PRIVATE ParsedQuicVersionVector | 
|  | AllSupportedVersionsWithQuicCrypto(); | 
|  |  | 
|  | // Returns a subset of CurrentSupportedVersions() with | 
|  | // handshake_protocol == PROTOCOL_QUIC_CRYPTO, in the same order. | 
|  | QUIC_EXPORT_PRIVATE ParsedQuicVersionVector | 
|  | CurrentSupportedVersionsWithQuicCrypto(); | 
|  |  | 
|  | // Returns a subset of AllSupportedVersions() with | 
|  | // handshake_protocol == PROTOCOL_TLS1_3, in the same order. | 
|  | QUIC_EXPORT_PRIVATE ParsedQuicVersionVector AllSupportedVersionsWithTls(); | 
|  |  | 
|  | // Returns a subset of CurrentSupportedVersions() with handshake_protocol == | 
|  | // PROTOCOL_TLS1_3. | 
|  | QUIC_EXPORT_PRIVATE ParsedQuicVersionVector CurrentSupportedVersionsWithTls(); | 
|  |  | 
|  | // Returns a subset of CurrentSupportedVersions() using HTTP/3 at the HTTP | 
|  | // layer. | 
|  | QUIC_EXPORT_PRIVATE ParsedQuicVersionVector CurrentSupportedHttp3Versions(); | 
|  |  | 
|  | // Returns QUIC version of |index| in result of |versions|. Returns | 
|  | // UnsupportedQuicVersion() if |index| is out of bounds. | 
|  | QUIC_EXPORT_PRIVATE ParsedQuicVersionVector | 
|  | ParsedVersionOfIndex(const ParsedQuicVersionVector& versions, int index); | 
|  |  | 
|  | // QuicVersionLabel is written to and read from the wire, but we prefer to use | 
|  | // the more readable ParsedQuicVersion at other levels. | 
|  | // Helper function which translates from a QuicVersionLabel to a | 
|  | // ParsedQuicVersion. | 
|  | QUIC_EXPORT_PRIVATE ParsedQuicVersion | 
|  | ParseQuicVersionLabel(QuicVersionLabel version_label); | 
|  |  | 
|  | // Helper function that translates from a QuicVersionLabelVector to a | 
|  | // ParsedQuicVersionVector. | 
|  | QUIC_EXPORT_PRIVATE ParsedQuicVersionVector | 
|  | ParseQuicVersionLabelVector(const QuicVersionLabelVector& version_labels); | 
|  |  | 
|  | // Parses a QUIC version string such as "Q043" or "T051". Also supports parsing | 
|  | // ALPN such as "h3-29" or "h3-Q050". For PROTOCOL_QUIC_CRYPTO versions, also | 
|  | // supports parsing numbers such as "46". | 
|  | QUIC_EXPORT_PRIVATE ParsedQuicVersion | 
|  | ParseQuicVersionString(absl::string_view version_string); | 
|  |  | 
|  | // Parses a comma-separated list of QUIC version strings. Supports parsing by | 
|  | // label, ALPN and numbers for PROTOCOL_QUIC_CRYPTO. Skips unknown versions. | 
|  | // For example: "h3-29,Q050,46". | 
|  | QUIC_EXPORT_PRIVATE ParsedQuicVersionVector | 
|  | ParseQuicVersionVectorString(absl::string_view versions_string); | 
|  |  | 
|  | // Constructs a QuicVersionLabel from the provided ParsedQuicVersion. | 
|  | // QuicVersionLabel is written to and read from the wire, but we prefer to use | 
|  | // the more readable ParsedQuicVersion at other levels. | 
|  | // Helper function which translates from a ParsedQuicVersion to a | 
|  | // QuicVersionLabel. Returns 0 if |parsed_version| is unsupported. | 
|  | QUIC_EXPORT_PRIVATE QuicVersionLabel | 
|  | CreateQuicVersionLabel(ParsedQuicVersion parsed_version); | 
|  |  | 
|  | // Constructs a QuicVersionLabelVector from the provided | 
|  | // ParsedQuicVersionVector. | 
|  | QUIC_EXPORT_PRIVATE QuicVersionLabelVector | 
|  | CreateQuicVersionLabelVector(const ParsedQuicVersionVector& versions); | 
|  |  | 
|  | // Helper function which translates from a QuicVersionLabel to a string. | 
|  | QUIC_EXPORT_PRIVATE std::string QuicVersionLabelToString( | 
|  | QuicVersionLabel version_label); | 
|  |  | 
|  | // Returns |separator|-separated list of string representations of | 
|  | // QuicVersionLabel values in the supplied |version_labels| vector. The values | 
|  | // after the (0-based) |skip_after_nth_version|'th are skipped. | 
|  | QUIC_EXPORT_PRIVATE std::string QuicVersionLabelVectorToString( | 
|  | const QuicVersionLabelVector& version_labels, | 
|  | const std::string& separator, | 
|  | size_t skip_after_nth_version); | 
|  |  | 
|  | // Returns comma separated list of string representations of QuicVersionLabel | 
|  | // values in the supplied |version_labels| vector. | 
|  | QUIC_EXPORT_PRIVATE inline std::string QuicVersionLabelVectorToString( | 
|  | const QuicVersionLabelVector& version_labels) { | 
|  | return QuicVersionLabelVectorToString(version_labels, ",", | 
|  | std::numeric_limits<size_t>::max()); | 
|  | } | 
|  |  | 
|  | // Helper function which translates from a ParsedQuicVersion to a string. | 
|  | // Returns strings corresponding to the on-the-wire tag. | 
|  | QUIC_EXPORT_PRIVATE std::string ParsedQuicVersionToString( | 
|  | ParsedQuicVersion version); | 
|  |  | 
|  | // Returns a vector of supported QUIC transport versions. DEPRECATED, use | 
|  | // AllSupportedVersions instead. | 
|  | QUIC_EXPORT_PRIVATE QuicTransportVersionVector AllSupportedTransportVersions(); | 
|  |  | 
|  | // Returns comma separated list of string representations of | 
|  | // QuicTransportVersion enum values in the supplied |versions| vector. | 
|  | QUIC_EXPORT_PRIVATE std::string QuicTransportVersionVectorToString( | 
|  | const QuicTransportVersionVector& versions); | 
|  |  | 
|  | // Returns comma separated list of string representations of ParsedQuicVersion | 
|  | // values in the supplied |versions| vector. | 
|  | QUIC_EXPORT_PRIVATE std::string ParsedQuicVersionVectorToString( | 
|  | const ParsedQuicVersionVector& versions); | 
|  |  | 
|  | // Returns |separator|-separated list of string representations of | 
|  | // ParsedQuicVersion values in the supplied |versions| vector. The values after | 
|  | // the (0-based) |skip_after_nth_version|'th are skipped. | 
|  | QUIC_EXPORT_PRIVATE std::string ParsedQuicVersionVectorToString( | 
|  | const ParsedQuicVersionVector& versions, | 
|  | const std::string& separator, | 
|  | size_t skip_after_nth_version); | 
|  |  | 
|  | // Returns comma separated list of string representations of ParsedQuicVersion | 
|  | // values in the supplied |versions| vector. | 
|  | QUIC_EXPORT_PRIVATE inline std::string ParsedQuicVersionVectorToString( | 
|  | const ParsedQuicVersionVector& versions) { | 
|  | return ParsedQuicVersionVectorToString(versions, ",", | 
|  | std::numeric_limits<size_t>::max()); | 
|  | } | 
|  |  | 
|  | // Returns true if |transport_version| uses IETF invariant headers. | 
|  | QUIC_EXPORT_PRIVATE constexpr bool VersionHasIetfInvariantHeader( | 
|  | QuicTransportVersion transport_version) { | 
|  | return transport_version > QUIC_VERSION_43; | 
|  | } | 
|  |  | 
|  | // Returns true if |transport_version| supports MESSAGE frames. | 
|  | QUIC_EXPORT_PRIVATE constexpr bool VersionSupportsMessageFrames( | 
|  | QuicTransportVersion transport_version) { | 
|  | // MESSAGE frames were added in version 45. | 
|  | return transport_version > QUIC_VERSION_43; | 
|  | } | 
|  |  | 
|  | // If true, HTTP/3 instead of gQUIC will be used at the HTTP layer. | 
|  | // Notable changes are: | 
|  | // * Headers stream no longer exists. | 
|  | // * PRIORITY, HEADERS are moved from headers stream to HTTP/3 control stream. | 
|  | // * PUSH_PROMISE is moved to request stream. | 
|  | // * Unidirectional streams will have their first byte as a stream type. | 
|  | // * HEADERS frames are compressed using QPACK. | 
|  | // * DATA frame has frame headers. | 
|  | // * GOAWAY is moved to HTTP layer. | 
|  | QUIC_EXPORT_PRIVATE constexpr bool VersionUsesHttp3( | 
|  | QuicTransportVersion transport_version) { | 
|  | return transport_version >= QUIC_VERSION_IETF_DRAFT_29; | 
|  | } | 
|  |  | 
|  | // Returns whether the transport_version supports the variable length integer | 
|  | // length field as defined by IETF QUIC draft-13 and later. | 
|  | QUIC_EXPORT_PRIVATE constexpr bool QuicVersionHasLongHeaderLengths( | 
|  | QuicTransportVersion transport_version) { | 
|  | // Long header lengths were added in version 49. | 
|  | return transport_version > QUIC_VERSION_46; | 
|  | } | 
|  |  | 
|  | // Returns whether |transport_version| makes use of IETF QUIC | 
|  | // frames or not. | 
|  | QUIC_EXPORT_PRIVATE constexpr bool VersionHasIetfQuicFrames( | 
|  | QuicTransportVersion transport_version) { | 
|  | return VersionUsesHttp3(transport_version); | 
|  | } | 
|  |  | 
|  | // Returns whether this version supports long header 8-bit encoded | 
|  | // connection ID lengths as described in draft-ietf-quic-invariants-06 and | 
|  | // draft-ietf-quic-transport-22. | 
|  | QUIC_EXPORT_PRIVATE bool VersionHasLengthPrefixedConnectionIds( | 
|  | QuicTransportVersion transport_version); | 
|  |  | 
|  | // Returns true if this version supports the old Google-style Alt-Svc | 
|  | // advertisement format. | 
|  | QUIC_EXPORT_PRIVATE bool VersionSupportsGoogleAltSvcFormat( | 
|  | QuicTransportVersion transport_version); | 
|  |  | 
|  | // Returns whether this version allows server connection ID lengths that are | 
|  | // not 64 bits. | 
|  | QUIC_EXPORT_PRIVATE bool VersionAllowsVariableLengthConnectionIds( | 
|  | QuicTransportVersion transport_version); | 
|  |  | 
|  | // Returns whether this version label supports long header 4-bit encoded | 
|  | // connection ID lengths as described in draft-ietf-quic-invariants-05 and | 
|  | // draft-ietf-quic-transport-21. | 
|  | QUIC_EXPORT_PRIVATE bool QuicVersionLabelUses4BitConnectionIdLength( | 
|  | QuicVersionLabel version_label); | 
|  |  | 
|  | // Returns the ALPN string to use in TLS for this version of QUIC. | 
|  | QUIC_EXPORT_PRIVATE std::string AlpnForVersion( | 
|  | ParsedQuicVersion parsed_version); | 
|  |  | 
|  | // Initializes support for the provided IETF draft version by setting the | 
|  | // correct flags. | 
|  | QUIC_EXPORT_PRIVATE void QuicVersionInitializeSupportForIetfDraft(); | 
|  |  | 
|  | // Configures the flags required to enable support for this version of QUIC. | 
|  | QUIC_EXPORT_PRIVATE void QuicEnableVersion(const ParsedQuicVersion& version); | 
|  |  | 
|  | // Configures the flags required to disable support for this version of QUIC. | 
|  | QUIC_EXPORT_PRIVATE void QuicDisableVersion(const ParsedQuicVersion& version); | 
|  |  | 
|  | // Returns whether support for this version of QUIC is currently enabled. | 
|  | QUIC_EXPORT_PRIVATE bool QuicVersionIsEnabled(const ParsedQuicVersion& version); | 
|  |  | 
|  | }  // namespace quic | 
|  |  | 
|  | #endif  // QUICHE_QUIC_CORE_QUIC_VERSIONS_H_ |