Allow TLS-based versions in quic_client and quic_server
Also adds functions for overriding the version label for T099, parsing version labels from strings, and easily enabling flags required by particular QUIC versions.
gfe-relnote: protected by disabled flag quic_supports_tls_handshake, or test-only code
PiperOrigin-RevId: 242047771
Change-Id: I00d8948fca5e91021c386944371dc3b92f1f3988
diff --git a/quic/core/quic_versions.cc b/quic/core/quic_versions.cc
index 036fbd0..62f9ce9 100644
--- a/quic/core/quic_versions.cc
+++ b/quic/core/quic_versions.cc
@@ -8,11 +8,13 @@
#include "net/third_party/quiche/src/quic/core/quic_tag.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_endian.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
namespace quic {
namespace {
@@ -23,6 +25,10 @@
return MakeQuicTag(d, c, b, a);
}
+// Version label for ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_99).
+// Defaults to "T099". Can be overridden for IETF interop events.
+QuicVersionLabel kQuicT099VersionLabel = 0;
+
} // namespace
ParsedQuicVersion::ParsedQuicVersion(HandshakeProtocol handshake_protocol,
@@ -66,6 +72,10 @@
case QUIC_VERSION_47:
return MakeVersionLabel(proto, '0', '4', '7');
case QUIC_VERSION_99:
+ if (parsed_version.handshake_protocol == PROTOCOL_TLS1_3 &&
+ kQuicT099VersionLabel != 0) {
+ return kQuicT099VersionLabel;
+ }
return MakeVersionLabel(proto, '0', '9', '9');
default:
// This shold be an ERROR because we should never attempt to convert an
@@ -105,6 +115,41 @@
return UnsupportedQuicVersion();
}
+ParsedQuicVersion ParseQuicVersionString(std::string version_string) {
+ if (version_string.length() == 0) {
+ return UnsupportedQuicVersion();
+ }
+ int quic_version_number = 0;
+ if (QuicTextUtils::StringToInt(version_string, &quic_version_number) &&
+ quic_version_number > 0) {
+ return ParsedQuicVersion(
+ PROTOCOL_QUIC_CRYPTO,
+ static_cast<QuicTransportVersion>(quic_version_number));
+ }
+
+ std::vector<HandshakeProtocol> protocols = {PROTOCOL_QUIC_CRYPTO};
+ if (FLAGS_quic_supports_tls_handshake) {
+ protocols.push_back(PROTOCOL_TLS1_3);
+ }
+ for (QuicTransportVersion version : kSupportedTransportVersions) {
+ for (HandshakeProtocol handshake : protocols) {
+ const ParsedQuicVersion parsed_version =
+ ParsedQuicVersion(handshake, version);
+ if (version_string == ParsedQuicVersionToString(parsed_version)) {
+ return parsed_version;
+ }
+ }
+ }
+ // Still recognize T099 even if kQuicT099VersionLabel has been changed.
+ if (FLAGS_quic_supports_tls_handshake && version_string == "T099") {
+ return ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_99);
+ }
+ // Reading from the client so this should not be considered an ERROR.
+ QUIC_DLOG(INFO) << "Unsupported QUIC version string: \"" << version_string
+ << "\".";
+ return UnsupportedQuicVersion();
+}
+
QuicTransportVersionVector AllSupportedTransportVersions() {
QuicTransportVersionVector supported_versions;
for (QuicTransportVersion version : kSupportedTransportVersions) {
@@ -333,5 +378,49 @@
return ParsedQuicVersion(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED);
}
+void QuicVersionInitializeSupportForIetfDraft(int32_t draft_version) {
+ if (draft_version == 0) {
+ return;
+ }
+ if (draft_version < 0 || draft_version >= 256) {
+ LOG(FATAL) << "Invalid IETF draft version " << draft_version;
+ return;
+ }
+
+ kQuicT099VersionLabel = 0xff000000 + draft_version;
+
+ // Enable necessary flags.
+ SetQuicFlag(&FLAGS_quic_supports_tls_handshake, true);
+ SetQuicReloadableFlag(quic_deprecate_ack_bundling_mode, true);
+ SetQuicReloadableFlag(quic_rpm_decides_when_to_send_acks, true);
+ SetQuicReloadableFlag(quic_use_uber_loss_algorithm, true);
+ SetQuicReloadableFlag(quic_use_uber_received_packet_manager, true);
+ SetQuicReloadableFlag(quic_validate_packet_number_post_decryption, true);
+ SetQuicRestartFlag(quic_enable_accept_random_ipn, true);
+}
+
+void QuicEnableVersion(ParsedQuicVersion parsed_version) {
+ if (parsed_version.handshake_protocol == PROTOCOL_TLS1_3) {
+ SetQuicFlag(&FLAGS_quic_supports_tls_handshake, true);
+ }
+ static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 6u,
+ "Supported versions out of sync");
+ if (parsed_version.transport_version >= QUIC_VERSION_99) {
+ SetQuicReloadableFlag(quic_enable_version_99, true);
+ }
+ if (parsed_version.transport_version >= QUIC_VERSION_47) {
+ SetQuicReloadableFlag(quic_enable_version_47, true);
+ }
+ if (parsed_version.transport_version >= QUIC_VERSION_46) {
+ SetQuicReloadableFlag(quic_enable_version_46, true);
+ }
+ if (parsed_version.transport_version >= QUIC_VERSION_44) {
+ SetQuicReloadableFlag(quic_enable_version_44, true);
+ }
+ if (parsed_version.transport_version >= QUIC_VERSION_43) {
+ SetQuicReloadableFlag(quic_enable_version_43, true);
+ }
+}
+
#undef RETURN_STRING_LITERAL // undef for jumbo builds
} // namespace quic
diff --git a/quic/core/quic_versions.h b/quic/core/quic_versions.h
index b23ae08..2c78760 100644
--- a/quic/core/quic_versions.h
+++ b/quic/core/quic_versions.h
@@ -227,6 +227,11 @@
QUIC_EXPORT_PRIVATE ParsedQuicVersion
ParseQuicVersionLabel(QuicVersionLabel version_label);
+// Parses a QUIC version string such as "Q043" or "T099".
+// Also supports parsing numbers such as "44".
+QUIC_EXPORT_PRIVATE ParsedQuicVersion
+ParseQuicVersionString(std::string version_string);
+
// Constructs a QuicVersionLabel from the provided ParsedQuicVersion.
QUIC_EXPORT_PRIVATE QuicVersionLabel
CreateQuicVersionLabel(ParsedQuicVersion parsed_version);
@@ -348,6 +353,14 @@
return transport_version == QUIC_VERSION_99;
}
+// Initializes support for the provided IETF draft version by setting flags
+// and the version label.
+QUIC_EXPORT_PRIVATE void QuicVersionInitializeSupportForIetfDraft(
+ int32_t draft_version);
+
+// Enables the flags required to support this version of QUIC.
+QUIC_EXPORT_PRIVATE void QuicEnableVersion(ParsedQuicVersion parsed_version);
+
} // namespace quic
#endif // QUICHE_QUIC_CORE_QUIC_VERSIONS_H_
diff --git a/quic/core/quic_versions_test.cc b/quic/core/quic_versions_test.cc
index db7f53a..6139ca8 100644
--- a/quic/core/quic_versions_test.cc
+++ b/quic/core/quic_versions_test.cc
@@ -171,6 +171,45 @@
ParseQuicVersionLabel(MakeVersionLabel('T', '0', '4', '7')));
}
+TEST_F(QuicVersionsTest, ParseQuicVersionString) {
+ EXPECT_EQ(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_39),
+ ParseQuicVersionString("Q039"));
+ EXPECT_EQ(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_43),
+ ParseQuicVersionString("Q043"));
+ EXPECT_EQ(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_44),
+ ParseQuicVersionString("Q044"));
+ EXPECT_EQ(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_46),
+ ParseQuicVersionString("Q046"));
+ EXPECT_EQ(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_47),
+ ParseQuicVersionString("Q047"));
+
+ EXPECT_EQ(UnsupportedQuicVersion(), ParseQuicVersionString(""));
+ EXPECT_EQ(UnsupportedQuicVersion(), ParseQuicVersionString("Q 47"));
+ EXPECT_EQ(UnsupportedQuicVersion(), ParseQuicVersionString("Q047 "));
+
+ // Test a TLS version:
+ FLAGS_quic_supports_tls_handshake = true;
+ EXPECT_EQ(ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_39),
+ ParseQuicVersionString("T039"));
+ EXPECT_EQ(ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_43),
+ ParseQuicVersionString("T043"));
+ EXPECT_EQ(ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_44),
+ ParseQuicVersionString("T044"));
+ EXPECT_EQ(ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_46),
+ ParseQuicVersionString("T046"));
+ EXPECT_EQ(ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_47),
+ ParseQuicVersionString("T047"));
+
+ FLAGS_quic_supports_tls_handshake = false;
+ EXPECT_EQ(UnsupportedQuicVersion(), ParseQuicVersionString("T035"));
+ EXPECT_EQ(UnsupportedQuicVersion(), ParseQuicVersionString("T039"));
+ EXPECT_EQ(UnsupportedQuicVersion(), ParseQuicVersionString("T043"));
+ EXPECT_EQ(UnsupportedQuicVersion(), ParseQuicVersionString("T044"));
+ EXPECT_EQ(UnsupportedQuicVersion(), ParseQuicVersionString("T045"));
+ EXPECT_EQ(UnsupportedQuicVersion(), ParseQuicVersionString("T046"));
+ EXPECT_EQ(UnsupportedQuicVersion(), ParseQuicVersionString("T047"));
+}
+
TEST_F(QuicVersionsTest, CreateQuicVersionLabel) {
EXPECT_EQ(MakeVersionLabel('Q', '0', '3', '9'),
CreateQuicVersionLabel(
@@ -516,6 +555,58 @@
EXPECT_EQ(QUIC_VERSION_47, 47);
EXPECT_EQ(QUIC_VERSION_99, 99);
}
+
+TEST_F(QuicVersionsTest, InitializeSupportForIetfDraft) {
+ FLAGS_quic_supports_tls_handshake = true;
+ ParsedQuicVersion parsed_version_t099 =
+ ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_99);
+ FLAGS_quic_supports_tls_handshake = false;
+ EXPECT_EQ(MakeVersionLabel('T', '0', '9', '9'),
+ CreateQuicVersionLabel(parsed_version_t099));
+
+ QuicVersionInitializeSupportForIetfDraft(0);
+ EXPECT_EQ(MakeVersionLabel('T', '0', '9', '9'),
+ CreateQuicVersionLabel(parsed_version_t099));
+ EXPECT_FALSE(FLAGS_quic_supports_tls_handshake);
+
+ QuicVersionInitializeSupportForIetfDraft(18);
+ EXPECT_TRUE(FLAGS_quic_supports_tls_handshake);
+ EXPECT_EQ(MakeVersionLabel(0xff, 0, 0, 18),
+ CreateQuicVersionLabel(parsed_version_t099));
+}
+
+TEST_F(QuicVersionsTest, QuicEnableVersion) {
+ FLAGS_quic_supports_tls_handshake = true;
+ ParsedQuicVersion parsed_version_q047 =
+ ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_47);
+ ParsedQuicVersion parsed_version_t047 =
+ ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_47);
+ ParsedQuicVersion parsed_version_t099 =
+ ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_99);
+ FLAGS_quic_supports_tls_handshake = false;
+ SetQuicReloadableFlag(quic_disable_version_39, false);
+ SetQuicReloadableFlag(quic_enable_version_43, true);
+ SetQuicReloadableFlag(quic_enable_version_44, true);
+ SetQuicReloadableFlag(quic_enable_version_46, true);
+ SetQuicReloadableFlag(quic_enable_version_47, false);
+ SetQuicReloadableFlag(quic_enable_version_99, false);
+
+ QuicEnableVersion(parsed_version_q047);
+ EXPECT_FALSE(FLAGS_quic_supports_tls_handshake);
+ EXPECT_TRUE(GetQuicReloadableFlag(quic_enable_version_47));
+ EXPECT_FALSE(GetQuicReloadableFlag(quic_enable_version_99));
+
+ QuicEnableVersion(parsed_version_t047);
+ EXPECT_TRUE(FLAGS_quic_supports_tls_handshake);
+ EXPECT_TRUE(GetQuicReloadableFlag(quic_enable_version_47));
+ EXPECT_FALSE(GetQuicReloadableFlag(quic_enable_version_99));
+
+ QuicEnableVersion(parsed_version_t099);
+ EXPECT_TRUE(FLAGS_quic_supports_tls_handshake);
+ EXPECT_TRUE(GetQuicReloadableFlag(quic_enable_version_47));
+ EXPECT_TRUE(GetQuicReloadableFlag(quic_enable_version_99));
+}
+
} // namespace
} // namespace test
} // namespace quic
diff --git a/quic/tools/quic_client_bin.cc b/quic/tools/quic_client_bin.cc
index ff81125..ee8262f 100644
--- a/quic/tools/quic_client_bin.cc
+++ b/quic/tools/quic_client_bin.cc
@@ -47,6 +47,7 @@
#include "net/third_party/quiche/src/quic/core/quic_packets.h"
#include "net/third_party/quiche/src/quic/core/quic_server_id.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
+#include "net/third_party/quiche/src/quic/core/quic_versions.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_default_proof_providers.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
@@ -151,11 +152,20 @@
"Set to true for a quieter output experience.");
DEFINE_QUIC_COMMAND_LINE_FLAG(
- int32_t,
+ std::string,
quic_version,
- -1,
+ "",
"QUIC version to speak, e.g. 21. If not set, then all available "
- "versions are offered in the handshake.");
+ "versions are offered in the handshake. Also supports wire versions "
+ "such as Q043 or T099.");
+
+DEFINE_QUIC_COMMAND_LINE_FLAG(
+ int32_t,
+ quic_ietf_draft,
+ 0,
+ "QUIC IETF draft number to use over the wire, e.g. 18. "
+ "By default this sets quic_version to T099. "
+ "This also enables required internal QUIC flags.");
DEFINE_QUIC_COMMAND_LINE_FLAG(
bool,
@@ -228,12 +238,31 @@
quic::QuicEpollServer epoll_server;
quic::QuicServerId server_id(url.host(), port, false);
quic::ParsedQuicVersionVector versions = quic::CurrentSupportedVersions();
- if (GetQuicFlag(FLAGS_quic_version) != -1) {
- versions.clear();
- versions.push_back(quic::ParsedQuicVersion(
- quic::PROTOCOL_QUIC_CRYPTO, static_cast<quic::QuicTransportVersion>(
- GetQuicFlag(FLAGS_quic_version))));
+
+ std::string quic_version_string = GetQuicFlag(FLAGS_quic_version);
+ const int32_t quic_ietf_draft = GetQuicFlag(FLAGS_quic_ietf_draft);
+ if (quic_ietf_draft > 0) {
+ quic::QuicVersionInitializeSupportForIetfDraft(quic_ietf_draft);
+ if (quic_version_string.length() == 0) {
+ quic_version_string = "T099";
+ }
}
+ if (quic_version_string.length() > 0) {
+ if (quic_version_string[0] == 'T') {
+ // ParseQuicVersionString checks quic_supports_tls_handshake.
+ SetQuicFlag(&FLAGS_quic_supports_tls_handshake, true);
+ }
+ quic::ParsedQuicVersion parsed_quic_version =
+ quic::ParseQuicVersionString(quic_version_string);
+ if (parsed_quic_version.transport_version ==
+ quic::QUIC_VERSION_UNSUPPORTED) {
+ return 1;
+ }
+ versions.clear();
+ versions.push_back(parsed_quic_version);
+ quic::QuicEnableVersion(parsed_quic_version);
+ }
+
const int32_t num_requests(GetQuicFlag(FLAGS_num_requests));
std::unique_ptr<quic::ProofVerifier> proof_verifier;
if (GetQuicFlag(FLAGS_disable_certificate_verification)) {
diff --git a/quic/tools/quic_server_bin.cc b/quic/tools/quic_server_bin.cc
index 1029fbd..128c873 100644
--- a/quic/tools/quic_server_bin.cc
+++ b/quic/tools/quic_server_bin.cc
@@ -7,6 +7,7 @@
#include <vector>
+#include "net/third_party/quiche/src/quic/core/quic_versions.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_default_proof_providers.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
@@ -26,6 +27,13 @@
"construction to seed the cache. Cache directory can be "
"generated using `wget -p --save-headers <url>`");
+DEFINE_QUIC_COMMAND_LINE_FLAG(
+ int32_t,
+ quic_ietf_draft,
+ 0,
+ "QUIC IETF draft number to use over the wire, e.g. 18. "
+ "This also enables required internal QUIC flags.");
+
int main(int argc, char* argv[]) {
const char* usage = "Usage: quic_server [options]";
std::vector<std::string> non_option_args =
@@ -35,6 +43,13 @@
exit(0);
}
+ const int32_t quic_ietf_draft = GetQuicFlag(FLAGS_quic_ietf_draft);
+ if (quic_ietf_draft > 0) {
+ quic::QuicVersionInitializeSupportForIetfDraft(quic_ietf_draft);
+ quic::QuicEnableVersion(
+ quic::ParsedQuicVersion(quic::PROTOCOL_TLS1_3, quic::QUIC_VERSION_99));
+ }
+
quic::QuicMemoryCacheBackend memory_cache_backend;
if (!GetQuicFlag(FLAGS_quic_response_cache_dir).empty()) {
memory_cache_backend.InitializeBackend(