// 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. Q046). 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 <cstdint> #include <string> #include <vector> #include "absl/base/macros.h" #include "absl/strings/string_view.h" #include "quiche/quic/core/quic_tag.h" #include "quiche/quic/core/quic_types.h" #include "quiche/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 { … }; // Helper function which translates from a QuicTransportVersion to a string. // Returns strings corresponding to enum names (e.g. QUIC_VERSION_6). QUICHE_EXPORT 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 { … }; // Helper function which translates from a HandshakeProtocol to a string. QUICHE_EXPORT std::string HandshakeProtocolToString( HandshakeProtocol handshake_protocol); // Returns whether |transport_version| uses CRYPTO frames for the handshake // instead of stream 1. QUICHE_EXPORT constexpr bool QuicVersionUsesCryptoFrames( QuicTransportVersion transport_version) { … } // Returns whether this combination of handshake protocol and transport // version is allowed. For example, {PROTOCOL_TLS1_3, QUIC_VERSION_46} is NOT // allowed as TLS requires crypto frames which v46 does not support. Note that // UnsupportedQuicVersion is a valid version. QUICHE_EXPORT constexpr bool ParsedQuicVersionIsValid( HandshakeProtocol handshake_protocol, QuicTransportVersion transport_version) { … } // A parsed QUIC version label which determines that handshake protocol // and the transport version. struct QUICHE_EXPORT ParsedQuicVersion { … }; QUICHE_EXPORT ParsedQuicVersion UnsupportedQuicVersion(); QUICHE_EXPORT ParsedQuicVersion QuicVersionReservedForNegotiation(); QUICHE_EXPORT std::ostream& operator<<(std::ostream& os, const ParsedQuicVersion& version); ParsedQuicVersionVector; QUICHE_EXPORT 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. QuicVersionLabel; QuicVersionLabelVector; // Constructs a version label from the 4 bytes such that the on-the-wire // order will be: d, c, b, a. QUICHE_EXPORT QuicVersionLabel MakeVersionLabel(uint8_t a, uint8_t b, uint8_t c, uint8_t d); QUICHE_EXPORT 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() { … } constexpr std::array<ParsedQuicVersion, 4> SupportedVersions() { … } QuicTransportVersionVector; QUICHE_EXPORT std::ostream& operator<<( std::ostream& os, const QuicTransportVersionVector& transport_versions); // Returns a vector of supported QUIC versions. QUICHE_EXPORT ParsedQuicVersionVector AllSupportedVersions(); // Returns a vector of supported QUIC versions, with any versions disabled by // flags excluded. QUICHE_EXPORT ParsedQuicVersionVector CurrentSupportedVersions(); // Obsolete QUIC supported versions are versions that are supported in // QUICHE but which should not be used by by modern clients. QUICHE_EXPORT ParsedQuicVersionVector ObsoleteSupportedVersions(); // Returns true if `version` is in `ObsoleteSupportedVersions`. QUICHE_EXPORT bool IsObsoleteSupportedVersion(ParsedQuicVersion version); // Returns a vector of supported QUIC versions which should be used by clients. // Server need to support old clients, but new client should only be using // QUIC versions in this list. QUICHE_EXPORT ParsedQuicVersionVector CurrentSupportedVersionsForClients(); // Returns a vector of QUIC versions from |versions| which exclude any versions // which are disabled by flags. QUICHE_EXPORT 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. QUICHE_EXPORT ParsedQuicVersionVector AllSupportedVersionsWithQuicCrypto(); // Returns a subset of CurrentSupportedVersions() with // handshake_protocol == PROTOCOL_QUIC_CRYPTO, in the same order. QUICHE_EXPORT ParsedQuicVersionVector CurrentSupportedVersionsWithQuicCrypto(); // Returns a subset of AllSupportedVersions() with // handshake_protocol == PROTOCOL_TLS1_3, in the same order. QUICHE_EXPORT ParsedQuicVersionVector AllSupportedVersionsWithTls(); // Returns a subset of CurrentSupportedVersions() with handshake_protocol == // PROTOCOL_TLS1_3. QUICHE_EXPORT ParsedQuicVersionVector CurrentSupportedVersionsWithTls(); // Returns a subset of CurrentSupportedVersions() using HTTP/3 at the HTTP // layer. QUICHE_EXPORT ParsedQuicVersionVector CurrentSupportedHttp3Versions(); // Returns QUIC version of |index| in result of |versions|. Returns // UnsupportedQuicVersion() if |index| is out of bounds. QUICHE_EXPORT 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. QUICHE_EXPORT ParsedQuicVersion ParseQuicVersionLabel(QuicVersionLabel version_label); // Helper function that translates from a QuicVersionLabelVector to a // ParsedQuicVersionVector. QUICHE_EXPORT 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-Q046". For PROTOCOL_QUIC_CRYPTO versions, also // supports parsing numbers such as "46". QUICHE_EXPORT 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,Q046,46". QUICHE_EXPORT 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. QUICHE_EXPORT QuicVersionLabel CreateQuicVersionLabel(ParsedQuicVersion parsed_version); // Constructs a QuicVersionLabelVector from the provided // ParsedQuicVersionVector. QUICHE_EXPORT QuicVersionLabelVector CreateQuicVersionLabelVector(const ParsedQuicVersionVector& versions); // Helper function which translates from a QuicVersionLabel to a string. QUICHE_EXPORT std::string QuicVersionLabelToString( QuicVersionLabel version_label); // Helper function which translates from a QuicVersionLabel string to a // ParsedQuicVersion. The version label string must be of the form returned // by QuicVersionLabelToString, for example, "00000001" or "Q046", but not // "51303433" (the hex encoding of the Q064 version label). Returns // the ParsedQuicVersion which matches the label or UnsupportedQuicVersion() // otherwise. QUICHE_EXPORT ParsedQuicVersion ParseQuicVersionLabelString(absl::string_view version_label_string); // 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. QUICHE_EXPORT 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. QUICHE_EXPORT inline std::string QuicVersionLabelVectorToString( const QuicVersionLabelVector& version_labels) { … } // Helper function which translates from a ParsedQuicVersion to a string. // Returns strings corresponding to the on-the-wire tag. QUICHE_EXPORT std::string ParsedQuicVersionToString(ParsedQuicVersion version); // Returns a vector of supported QUIC transport versions. DEPRECATED, use // AllSupportedVersions instead. QUICHE_EXPORT QuicTransportVersionVector AllSupportedTransportVersions(); // Returns comma separated list of string representations of // QuicTransportVersion enum values in the supplied |versions| vector. QUICHE_EXPORT std::string QuicTransportVersionVectorToString( const QuicTransportVersionVector& versions); // Returns comma separated list of string representations of ParsedQuicVersion // values in the supplied |versions| vector. QUICHE_EXPORT 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. QUICHE_EXPORT 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. QUICHE_EXPORT inline std::string ParsedQuicVersionVectorToString( const ParsedQuicVersionVector& versions) { … } // 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. QUICHE_EXPORT constexpr bool VersionUsesHttp3( QuicTransportVersion transport_version) { … } // Returns whether the transport_version supports the variable length integer // length field as defined by IETF QUIC draft-13 and later. QUICHE_EXPORT constexpr bool QuicVersionHasLongHeaderLengths( QuicTransportVersion transport_version) { … } // Returns whether |transport_version| makes use of IETF QUIC // frames or not. QUICHE_EXPORT constexpr bool VersionHasIetfQuicFrames( QuicTransportVersion 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. QUICHE_EXPORT bool VersionHasLengthPrefixedConnectionIds( QuicTransportVersion transport_version); // Returns true if this version supports the old Google-style Alt-Svc // advertisement format. QUICHE_EXPORT bool VersionSupportsGoogleAltSvcFormat( QuicTransportVersion transport_version); // Returns whether this version allows server connection ID lengths that are // not 64 bits. QUICHE_EXPORT 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. QUICHE_EXPORT bool QuicVersionLabelUses4BitConnectionIdLength( QuicVersionLabel version_label); // Returns the ALPN string to use in TLS for this version of QUIC. QUICHE_EXPORT std::string AlpnForVersion(ParsedQuicVersion parsed_version); // Configures the flags required to enable support for this version of QUIC. QUICHE_EXPORT void QuicEnableVersion(const ParsedQuicVersion& version); // Configures the flags required to disable support for this version of QUIC. QUICHE_EXPORT void QuicDisableVersion(const ParsedQuicVersion& version); // Returns whether support for this version of QUIC is currently enabled. QUICHE_EXPORT bool QuicVersionIsEnabled(const ParsedQuicVersion& version); } // namespace quic #endif // QUICHE_QUIC_CORE_QUIC_VERSIONS_H_