chromium/net/third_party/quiche/src/quiche/quic/core/quic_versions.h

// 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_