Relocate QUICHE files into quiche/ directory within the quiche repo, and change the relative include paths accordingly.
PiperOrigin-RevId: 440164720
Change-Id: I64d8a975d08888a3a86f6c51908e63d5cd45fa35
diff --git a/quiche/quic/core/quic_versions.cc b/quiche/quic/core/quic_versions.cc
new file mode 100644
index 0000000..df43ce7
--- /dev/null
+++ b/quiche/quic/core/quic_versions.cc
@@ -0,0 +1,667 @@
+// 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.
+
+#include "quiche/quic/core/quic_versions.h"
+
+#include <string>
+
+#include "absl/base/macros.h"
+#include "absl/strings/numbers.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_split.h"
+#include "quiche/quic/core/crypto/quic_random.h"
+#include "quiche/quic/core/quic_tag.h"
+#include "quiche/quic/core/quic_types.h"
+#include "quiche/quic/platform/api/quic_bug_tracker.h"
+#include "quiche/quic/platform/api/quic_flag_utils.h"
+#include "quiche/quic/platform/api/quic_flags.h"
+#include "quiche/quic/platform/api/quic_logging.h"
+#include "quiche/common/quiche_endian.h"
+#include "quiche/common/quiche_text_utils.h"
+
+namespace quic {
+namespace {
+
+QuicVersionLabel CreateRandomVersionLabelForNegotiation() {
+ QuicVersionLabel result;
+ if (!GetQuicFlag(FLAGS_quic_disable_version_negotiation_grease_randomness)) {
+ QuicRandom::GetInstance()->RandBytes(&result, sizeof(result));
+ } else {
+ result = MakeVersionLabel(0xd1, 0x57, 0x38, 0x3f);
+ }
+ result &= 0xf0f0f0f0;
+ result |= 0x0a0a0a0a;
+ return result;
+}
+
+void SetVersionFlag(const ParsedQuicVersion& version, bool should_enable) {
+ static_assert(SupportedVersions().size() == 6u,
+ "Supported versions out of sync");
+ const bool enable = should_enable;
+ const bool disable = !should_enable;
+ if (version == ParsedQuicVersion::V2Draft01()) {
+ SetQuicReloadableFlag(quic_enable_version_2_draft_01, enable);
+ } else if (version == ParsedQuicVersion::RFCv1()) {
+ SetQuicReloadableFlag(quic_disable_version_rfcv1, disable);
+ } else if (version == ParsedQuicVersion::Draft29()) {
+ SetQuicReloadableFlag(quic_disable_version_draft_29, disable);
+ } else if (version == ParsedQuicVersion::Q050()) {
+ SetQuicReloadableFlag(quic_disable_version_q050, disable);
+ } else if (version == ParsedQuicVersion::Q046()) {
+ SetQuicReloadableFlag(quic_disable_version_q046, disable);
+ } else if (version == ParsedQuicVersion::Q043()) {
+ SetQuicReloadableFlag(quic_disable_version_q043, disable);
+ } else {
+ QUIC_BUG(quic_bug_10589_1)
+ << "Cannot " << (enable ? "en" : "dis") << "able version " << version;
+ }
+}
+
+} // namespace
+
+bool ParsedQuicVersion::IsKnown() const {
+ QUICHE_DCHECK(ParsedQuicVersionIsValid(handshake_protocol, transport_version))
+ << QuicVersionToString(transport_version) << " "
+ << HandshakeProtocolToString(handshake_protocol);
+ return transport_version != QUIC_VERSION_UNSUPPORTED;
+}
+
+bool ParsedQuicVersion::KnowsWhichDecrypterToUse() const {
+ QUICHE_DCHECK(IsKnown());
+ return transport_version > QUIC_VERSION_46;
+}
+
+bool ParsedQuicVersion::UsesInitialObfuscators() const {
+ QUICHE_DCHECK(IsKnown());
+ // Initial obfuscators were added in version 50.
+ return transport_version > QUIC_VERSION_46;
+}
+
+bool ParsedQuicVersion::AllowsLowFlowControlLimits() const {
+ QUICHE_DCHECK(IsKnown());
+ // Low flow-control limits are used for all IETF versions.
+ return UsesHttp3();
+}
+
+bool ParsedQuicVersion::HasHeaderProtection() const {
+ QUICHE_DCHECK(IsKnown());
+ // Header protection was added in version 50.
+ return transport_version > QUIC_VERSION_46;
+}
+
+bool ParsedQuicVersion::SupportsRetry() const {
+ QUICHE_DCHECK(IsKnown());
+ // Retry was added in version 47.
+ return transport_version > QUIC_VERSION_46;
+}
+
+bool ParsedQuicVersion::SendsVariableLengthPacketNumberInLongHeader() const {
+ QUICHE_DCHECK(IsKnown());
+ return transport_version > QUIC_VERSION_46;
+}
+
+bool ParsedQuicVersion::AllowsVariableLengthConnectionIds() const {
+ QUICHE_DCHECK(IsKnown());
+ return VersionAllowsVariableLengthConnectionIds(transport_version);
+}
+
+bool ParsedQuicVersion::SupportsClientConnectionIds() const {
+ QUICHE_DCHECK(IsKnown());
+ // Client connection IDs were added in version 49.
+ return transport_version > QUIC_VERSION_46;
+}
+
+bool ParsedQuicVersion::HasLengthPrefixedConnectionIds() const {
+ QUICHE_DCHECK(IsKnown());
+ return VersionHasLengthPrefixedConnectionIds(transport_version);
+}
+
+bool ParsedQuicVersion::SupportsAntiAmplificationLimit() const {
+ QUICHE_DCHECK(IsKnown());
+ // The anti-amplification limit is used for all IETF versions.
+ return UsesHttp3();
+}
+
+bool ParsedQuicVersion::CanSendCoalescedPackets() const {
+ QUICHE_DCHECK(IsKnown());
+ return HasLongHeaderLengths() && UsesTls();
+}
+
+bool ParsedQuicVersion::SupportsGoogleAltSvcFormat() const {
+ QUICHE_DCHECK(IsKnown());
+ return VersionSupportsGoogleAltSvcFormat(transport_version);
+}
+
+bool ParsedQuicVersion::HasIetfInvariantHeader() const {
+ QUICHE_DCHECK(IsKnown());
+ return VersionHasIetfInvariantHeader(transport_version);
+}
+
+bool ParsedQuicVersion::SupportsMessageFrames() const {
+ QUICHE_DCHECK(IsKnown());
+ return VersionSupportsMessageFrames(transport_version);
+}
+
+bool ParsedQuicVersion::UsesHttp3() const {
+ QUICHE_DCHECK(IsKnown());
+ return VersionUsesHttp3(transport_version);
+}
+
+bool ParsedQuicVersion::HasLongHeaderLengths() const {
+ QUICHE_DCHECK(IsKnown());
+ return QuicVersionHasLongHeaderLengths(transport_version);
+}
+
+bool ParsedQuicVersion::UsesCryptoFrames() const {
+ QUICHE_DCHECK(IsKnown());
+ return QuicVersionUsesCryptoFrames(transport_version);
+}
+
+bool ParsedQuicVersion::HasIetfQuicFrames() const {
+ QUICHE_DCHECK(IsKnown());
+ return VersionHasIetfQuicFrames(transport_version);
+}
+
+bool ParsedQuicVersion::UsesLegacyTlsExtension() const {
+ QUICHE_DCHECK(IsKnown());
+ return UsesTls() && transport_version <= QUIC_VERSION_IETF_DRAFT_29;
+}
+
+bool ParsedQuicVersion::UsesTls() const {
+ QUICHE_DCHECK(IsKnown());
+ return handshake_protocol == PROTOCOL_TLS1_3;
+}
+
+bool ParsedQuicVersion::UsesQuicCrypto() const {
+ QUICHE_DCHECK(IsKnown());
+ return handshake_protocol == PROTOCOL_QUIC_CRYPTO;
+}
+
+bool ParsedQuicVersion::UsesV2PacketTypes() const {
+ QUICHE_DCHECK(IsKnown());
+ return transport_version == QUIC_VERSION_IETF_2_DRAFT_01;
+}
+
+bool ParsedQuicVersion::AlpnDeferToRFCv1() const {
+ QUICHE_DCHECK(IsKnown());
+ return transport_version == QUIC_VERSION_IETF_2_DRAFT_01;
+}
+
+bool VersionHasLengthPrefixedConnectionIds(
+ QuicTransportVersion transport_version) {
+ QUICHE_DCHECK(transport_version != QUIC_VERSION_UNSUPPORTED);
+ // Length-prefixed connection IDs were added in version 49.
+ return transport_version > QUIC_VERSION_46;
+}
+
+std::ostream& operator<<(std::ostream& os, const ParsedQuicVersion& version) {
+ os << ParsedQuicVersionToString(version);
+ return os;
+}
+
+std::ostream& operator<<(std::ostream& os,
+ const ParsedQuicVersionVector& versions) {
+ os << ParsedQuicVersionVectorToString(versions);
+ return os;
+}
+
+QuicVersionLabel MakeVersionLabel(uint8_t a, uint8_t b, uint8_t c, uint8_t d) {
+ return MakeQuicTag(d, c, b, a);
+}
+
+std::ostream& operator<<(std::ostream& os,
+ const QuicVersionLabelVector& version_labels) {
+ os << QuicVersionLabelVectorToString(version_labels);
+ return os;
+}
+
+std::ostream& operator<<(std::ostream& os,
+ const QuicTransportVersionVector& transport_versions) {
+ os << QuicTransportVersionVectorToString(transport_versions);
+ return os;
+}
+
+QuicVersionLabel CreateQuicVersionLabel(ParsedQuicVersion parsed_version) {
+ static_assert(SupportedVersions().size() == 6u,
+ "Supported versions out of sync");
+ if (parsed_version == ParsedQuicVersion::V2Draft01()) {
+ return MakeVersionLabel(0x70, 0x9a, 0x50, 0xc4);
+ } else if (parsed_version == ParsedQuicVersion::RFCv1()) {
+ return MakeVersionLabel(0x00, 0x00, 0x00, 0x01);
+ } else if (parsed_version == ParsedQuicVersion::Draft29()) {
+ return MakeVersionLabel(0xff, 0x00, 0x00, 29);
+ } else if (parsed_version == ParsedQuicVersion::Q050()) {
+ return MakeVersionLabel('Q', '0', '5', '0');
+ } else if (parsed_version == ParsedQuicVersion::Q046()) {
+ return MakeVersionLabel('Q', '0', '4', '6');
+ } else if (parsed_version == ParsedQuicVersion::Q043()) {
+ return MakeVersionLabel('Q', '0', '4', '3');
+ } else if (parsed_version == ParsedQuicVersion::ReservedForNegotiation()) {
+ return CreateRandomVersionLabelForNegotiation();
+ }
+ QUIC_BUG(quic_bug_10589_2)
+ << "Unsupported version "
+ << QuicVersionToString(parsed_version.transport_version) << " "
+ << HandshakeProtocolToString(parsed_version.handshake_protocol);
+ return 0;
+}
+
+QuicVersionLabelVector CreateQuicVersionLabelVector(
+ const ParsedQuicVersionVector& versions) {
+ QuicVersionLabelVector out;
+ out.reserve(versions.size());
+ for (const auto& version : versions) {
+ out.push_back(CreateQuicVersionLabel(version));
+ }
+ return out;
+}
+
+ParsedQuicVersionVector AllSupportedVersionsWithQuicCrypto() {
+ ParsedQuicVersionVector versions;
+ for (const ParsedQuicVersion& version : AllSupportedVersions()) {
+ if (version.handshake_protocol == PROTOCOL_QUIC_CRYPTO) {
+ versions.push_back(version);
+ }
+ }
+ QUIC_BUG_IF(quic_bug_10589_3, versions.empty())
+ << "No version with QUIC crypto found.";
+ return versions;
+}
+
+ParsedQuicVersionVector CurrentSupportedVersionsWithQuicCrypto() {
+ ParsedQuicVersionVector versions;
+ for (const ParsedQuicVersion& version : CurrentSupportedVersions()) {
+ if (version.handshake_protocol == PROTOCOL_QUIC_CRYPTO) {
+ versions.push_back(version);
+ }
+ }
+ QUIC_BUG_IF(quic_bug_10589_4, versions.empty())
+ << "No version with QUIC crypto found.";
+ return versions;
+}
+
+ParsedQuicVersionVector AllSupportedVersionsWithTls() {
+ ParsedQuicVersionVector versions;
+ for (const ParsedQuicVersion& version : AllSupportedVersions()) {
+ if (version.UsesTls()) {
+ versions.push_back(version);
+ }
+ }
+ QUIC_BUG_IF(quic_bug_10589_5, versions.empty())
+ << "No version with TLS handshake found.";
+ return versions;
+}
+
+ParsedQuicVersionVector CurrentSupportedVersionsWithTls() {
+ ParsedQuicVersionVector versions;
+ for (const ParsedQuicVersion& version : CurrentSupportedVersions()) {
+ if (version.UsesTls()) {
+ versions.push_back(version);
+ }
+ }
+ QUIC_BUG_IF(quic_bug_10589_6, versions.empty())
+ << "No version with TLS handshake found.";
+ return versions;
+}
+
+ParsedQuicVersionVector CurrentSupportedHttp3Versions() {
+ ParsedQuicVersionVector versions;
+ for (const ParsedQuicVersion& version : CurrentSupportedVersions()) {
+ if (version.UsesHttp3()) {
+ versions.push_back(version);
+ }
+ }
+ QUIC_BUG_IF(no_version_uses_http3, versions.empty())
+ << "No version speaking Http3 found.";
+ return versions;
+}
+
+ParsedQuicVersion ParseQuicVersionLabel(QuicVersionLabel version_label) {
+ for (const ParsedQuicVersion& version : AllSupportedVersions()) {
+ if (version_label == CreateQuicVersionLabel(version)) {
+ return version;
+ }
+ }
+ // Reading from the client so this should not be considered an ERROR.
+ QUIC_DLOG(INFO) << "Unsupported QuicVersionLabel version: "
+ << QuicVersionLabelToString(version_label);
+ return UnsupportedQuicVersion();
+}
+
+ParsedQuicVersionVector ParseQuicVersionLabelVector(
+ const QuicVersionLabelVector& version_labels) {
+ ParsedQuicVersionVector parsed_versions;
+ for (const QuicVersionLabel& version_label : version_labels) {
+ ParsedQuicVersion parsed_version = ParseQuicVersionLabel(version_label);
+ if (parsed_version.IsKnown()) {
+ parsed_versions.push_back(parsed_version);
+ }
+ }
+ return parsed_versions;
+}
+
+ParsedQuicVersion ParseQuicVersionString(absl::string_view version_string) {
+ if (version_string.empty()) {
+ return UnsupportedQuicVersion();
+ }
+ const ParsedQuicVersionVector supported_versions = AllSupportedVersions();
+ for (const ParsedQuicVersion& version : supported_versions) {
+ if (version_string == ParsedQuicVersionToString(version) ||
+ (version_string == AlpnForVersion(version) &&
+ !version.AlpnDeferToRFCv1()) ||
+ (version.handshake_protocol == PROTOCOL_QUIC_CRYPTO &&
+ version_string == QuicVersionToString(version.transport_version))) {
+ return version;
+ }
+ }
+ for (const ParsedQuicVersion& version : supported_versions) {
+ if (version.UsesHttp3() &&
+ version_string ==
+ QuicVersionLabelToString(CreateQuicVersionLabel(version))) {
+ return version;
+ }
+ }
+ int quic_version_number = 0;
+ if (absl::SimpleAtoi(version_string, &quic_version_number) &&
+ quic_version_number > 0) {
+ QuicTransportVersion transport_version =
+ static_cast<QuicTransportVersion>(quic_version_number);
+ if (!ParsedQuicVersionIsValid(PROTOCOL_QUIC_CRYPTO, transport_version)) {
+ return UnsupportedQuicVersion();
+ }
+ ParsedQuicVersion version(PROTOCOL_QUIC_CRYPTO, transport_version);
+ if (std::find(supported_versions.begin(), supported_versions.end(),
+ version) != supported_versions.end()) {
+ return version;
+ }
+ return UnsupportedQuicVersion();
+ }
+ // Reading from the client so this should not be considered an ERROR.
+ QUIC_DLOG(INFO) << "Unsupported QUIC version string: \"" << version_string
+ << "\".";
+ return UnsupportedQuicVersion();
+}
+
+ParsedQuicVersionVector ParseQuicVersionVectorString(
+ absl::string_view versions_string) {
+ ParsedQuicVersionVector versions;
+ std::vector<absl::string_view> version_strings =
+ absl::StrSplit(versions_string, ',');
+ for (absl::string_view version_string : version_strings) {
+ quiche::QuicheTextUtils::RemoveLeadingAndTrailingWhitespace(
+ &version_string);
+ ParsedQuicVersion version = ParseQuicVersionString(version_string);
+ if (!version.IsKnown() || std::find(versions.begin(), versions.end(),
+ version) != versions.end()) {
+ continue;
+ }
+ versions.push_back(version);
+ }
+ return versions;
+}
+
+QuicTransportVersionVector AllSupportedTransportVersions() {
+ QuicTransportVersionVector transport_versions;
+ for (const ParsedQuicVersion& version : AllSupportedVersions()) {
+ if (std::find(transport_versions.begin(), transport_versions.end(),
+ version.transport_version) == transport_versions.end()) {
+ transport_versions.push_back(version.transport_version);
+ }
+ }
+ return transport_versions;
+}
+
+ParsedQuicVersionVector AllSupportedVersions() {
+ constexpr auto supported_versions = SupportedVersions();
+ return ParsedQuicVersionVector(supported_versions.begin(),
+ supported_versions.end());
+}
+
+ParsedQuicVersionVector CurrentSupportedVersions() {
+ return FilterSupportedVersions(AllSupportedVersions());
+}
+
+ParsedQuicVersionVector FilterSupportedVersions(
+ ParsedQuicVersionVector versions) {
+ static_assert(SupportedVersions().size() == 6u,
+ "Supported versions out of sync");
+ ParsedQuicVersionVector filtered_versions;
+ filtered_versions.reserve(versions.size());
+ for (const ParsedQuicVersion& version : versions) {
+ if (version == ParsedQuicVersion::V2Draft01()) {
+ if (GetQuicReloadableFlag(quic_enable_version_2_draft_01)) {
+ filtered_versions.push_back(version);
+ }
+ } else if (version == ParsedQuicVersion::RFCv1()) {
+ if (!GetQuicReloadableFlag(quic_disable_version_rfcv1)) {
+ filtered_versions.push_back(version);
+ }
+ } else if (version == ParsedQuicVersion::Draft29()) {
+ if (!GetQuicReloadableFlag(quic_disable_version_draft_29)) {
+ filtered_versions.push_back(version);
+ }
+ } else if (version == ParsedQuicVersion::Q050()) {
+ if (!GetQuicReloadableFlag(quic_disable_version_q050)) {
+ filtered_versions.push_back(version);
+ }
+ } else if (version == ParsedQuicVersion::Q046()) {
+ if (!GetQuicReloadableFlag(quic_disable_version_q046)) {
+ filtered_versions.push_back(version);
+ }
+ } else if (version == ParsedQuicVersion::Q043()) {
+ if (!GetQuicReloadableFlag(quic_disable_version_q043)) {
+ filtered_versions.push_back(version);
+ }
+ } else {
+ QUIC_BUG(quic_bug_10589_7)
+ << "QUIC version " << version << " has no flag protection";
+ filtered_versions.push_back(version);
+ }
+ }
+ return filtered_versions;
+}
+
+ParsedQuicVersionVector ParsedVersionOfIndex(
+ const ParsedQuicVersionVector& versions, int index) {
+ ParsedQuicVersionVector version;
+ int version_count = versions.size();
+ if (index >= 0 && index < version_count) {
+ version.push_back(versions[index]);
+ } else {
+ version.push_back(UnsupportedQuicVersion());
+ }
+ return version;
+}
+
+std::string QuicVersionLabelToString(QuicVersionLabel version_label) {
+ return QuicTagToString(quiche::QuicheEndian::HostToNet32(version_label));
+}
+
+ParsedQuicVersion ParseQuicVersionLabelString(
+ absl::string_view version_label_string) {
+ const ParsedQuicVersionVector supported_versions = AllSupportedVersions();
+ for (const ParsedQuicVersion& version : supported_versions) {
+ if (version_label_string ==
+ QuicVersionLabelToString(CreateQuicVersionLabel(version))) {
+ return version;
+ }
+ }
+ return UnsupportedQuicVersion();
+}
+
+std::string QuicVersionLabelVectorToString(
+ const QuicVersionLabelVector& version_labels, const std::string& separator,
+ size_t skip_after_nth_version) {
+ std::string result;
+ for (size_t i = 0; i < version_labels.size(); ++i) {
+ if (i != 0) {
+ result.append(separator);
+ }
+
+ if (i > skip_after_nth_version) {
+ result.append("...");
+ break;
+ }
+ result.append(QuicVersionLabelToString(version_labels[i]));
+ }
+ return result;
+}
+
+#define RETURN_STRING_LITERAL(x) \
+ case x: \
+ return #x
+
+std::string QuicVersionToString(QuicTransportVersion transport_version) {
+ switch (transport_version) {
+ RETURN_STRING_LITERAL(QUIC_VERSION_43);
+ RETURN_STRING_LITERAL(QUIC_VERSION_46);
+ RETURN_STRING_LITERAL(QUIC_VERSION_50);
+ RETURN_STRING_LITERAL(QUIC_VERSION_IETF_DRAFT_29);
+ RETURN_STRING_LITERAL(QUIC_VERSION_IETF_RFC_V1);
+ RETURN_STRING_LITERAL(QUIC_VERSION_IETF_2_DRAFT_01);
+ RETURN_STRING_LITERAL(QUIC_VERSION_UNSUPPORTED);
+ RETURN_STRING_LITERAL(QUIC_VERSION_RESERVED_FOR_NEGOTIATION);
+ }
+ return absl::StrCat("QUIC_VERSION_UNKNOWN(",
+ static_cast<int>(transport_version), ")");
+}
+
+std::string HandshakeProtocolToString(HandshakeProtocol handshake_protocol) {
+ switch (handshake_protocol) {
+ RETURN_STRING_LITERAL(PROTOCOL_UNSUPPORTED);
+ RETURN_STRING_LITERAL(PROTOCOL_QUIC_CRYPTO);
+ RETURN_STRING_LITERAL(PROTOCOL_TLS1_3);
+ }
+ return absl::StrCat("PROTOCOL_UNKNOWN(", static_cast<int>(handshake_protocol),
+ ")");
+}
+
+std::string ParsedQuicVersionToString(ParsedQuicVersion version) {
+ static_assert(SupportedVersions().size() == 6u,
+ "Supported versions out of sync");
+ if (version == UnsupportedQuicVersion()) {
+ return "0";
+ } else if (version == ParsedQuicVersion::V2Draft01()) {
+ QUICHE_DCHECK(version.UsesHttp3());
+ return "v2draft01";
+ } else if (version == ParsedQuicVersion::RFCv1()) {
+ QUICHE_DCHECK(version.UsesHttp3());
+ return "RFCv1";
+ } else if (version == ParsedQuicVersion::Draft29()) {
+ QUICHE_DCHECK(version.UsesHttp3());
+ return "draft29";
+ }
+
+ return QuicVersionLabelToString(CreateQuicVersionLabel(version));
+}
+
+std::string QuicTransportVersionVectorToString(
+ const QuicTransportVersionVector& versions) {
+ std::string result = "";
+ for (size_t i = 0; i < versions.size(); ++i) {
+ if (i != 0) {
+ result.append(",");
+ }
+ result.append(QuicVersionToString(versions[i]));
+ }
+ return result;
+}
+
+std::string ParsedQuicVersionVectorToString(
+ const ParsedQuicVersionVector& versions, const std::string& separator,
+ size_t skip_after_nth_version) {
+ std::string result;
+ for (size_t i = 0; i < versions.size(); ++i) {
+ if (i != 0) {
+ result.append(separator);
+ }
+ if (i > skip_after_nth_version) {
+ result.append("...");
+ break;
+ }
+ result.append(ParsedQuicVersionToString(versions[i]));
+ }
+ return result;
+}
+
+bool VersionSupportsGoogleAltSvcFormat(QuicTransportVersion transport_version) {
+ return transport_version <= QUIC_VERSION_46;
+}
+
+bool VersionAllowsVariableLengthConnectionIds(
+ QuicTransportVersion transport_version) {
+ QUICHE_DCHECK_NE(transport_version, QUIC_VERSION_UNSUPPORTED);
+ return transport_version > QUIC_VERSION_46;
+}
+
+bool QuicVersionLabelUses4BitConnectionIdLength(
+ QuicVersionLabel version_label) {
+ // As we deprecate old versions, we still need the ability to send valid
+ // version negotiation packets for those versions. This function keeps track
+ // of the versions that ever supported the 4bit connection ID length encoding
+ // that we know about. Google QUIC 43 and earlier used a different encoding,
+ // and Google QUIC 49 and later use the new length prefixed encoding.
+ // Similarly, only IETF drafts 11 to 21 used this encoding.
+
+ // Check Q044, Q045, Q046, Q047 and Q048.
+ for (uint8_t c = '4'; c <= '8'; ++c) {
+ if (version_label == MakeVersionLabel('Q', '0', '4', c)) {
+ return true;
+ }
+ }
+ // Check T048.
+ if (version_label == MakeVersionLabel('T', '0', '4', '8')) {
+ return true;
+ }
+ // Check IETF draft versions in [11,21].
+ for (uint8_t draft_number = 11; draft_number <= 21; ++draft_number) {
+ if (version_label == MakeVersionLabel(0xff, 0x00, 0x00, draft_number)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+ParsedQuicVersion UnsupportedQuicVersion() {
+ return ParsedQuicVersion::Unsupported();
+}
+
+ParsedQuicVersion QuicVersionReservedForNegotiation() {
+ return ParsedQuicVersion::ReservedForNegotiation();
+}
+
+ParsedQuicVersion LegacyVersionForEncapsulation() {
+ return ParsedQuicVersion::Q043();
+}
+
+std::string AlpnForVersion(ParsedQuicVersion parsed_version) {
+ if (parsed_version == ParsedQuicVersion::V2Draft01()) {
+ return "h3";
+ } else if (parsed_version == ParsedQuicVersion::RFCv1()) {
+ return "h3";
+ } else if (parsed_version == ParsedQuicVersion::Draft29()) {
+ return "h3-29";
+ }
+ return "h3-" + ParsedQuicVersionToString(parsed_version);
+}
+
+void QuicVersionInitializeSupportForIetfDraft() {
+ // Enable necessary flags.
+}
+
+void QuicEnableVersion(const ParsedQuicVersion& version) {
+ SetVersionFlag(version, /*should_enable=*/true);
+}
+
+void QuicDisableVersion(const ParsedQuicVersion& version) {
+ SetVersionFlag(version, /*should_enable=*/false);
+}
+
+bool QuicVersionIsEnabled(const ParsedQuicVersion& version) {
+ ParsedQuicVersionVector current = CurrentSupportedVersions();
+ return std::find(current.begin(), current.end(), version) != current.end();
+}
+
+#undef RETURN_STRING_LITERAL // undef for jumbo builds
+} // namespace quic