Send version negotiation in response to short connection IDs
This code change is in response to the following spec change:
https://github.com/quicwg/base-drafts/pull/4187/files
We're now expected to not enforce the 64bit minimum on unknown versions.
Protected by FLAGS_quic_reloadable_flag_quic_send_version_negotiation_for_short_connection_ids.
PiperOrigin-RevId: 338099578
Change-Id: I9d28a38464fc8050c166d976bb12e7cafd62633c
diff --git a/quic/core/quic_dispatcher.cc b/quic/core/quic_dispatcher.cc
index ac40b0a..11c6753 100644
--- a/quic/core/quic_dispatcher.cc
+++ b/quic/core/quic_dispatcher.cc
@@ -465,7 +465,16 @@
// connection ID, the dispatcher picks a new one of its expected length.
// Therefore we should never receive a connection ID that is smaller
// than 64 bits and smaller than what we expect.
- if (server_connection_id.length() < kQuicMinimumInitialConnectionIdLength &&
+ bool should_check_short_connection_ids = true;
+ if (GetQuicReloadableFlag(
+ quic_send_version_negotiation_for_short_connection_ids)) {
+ QUIC_RELOADABLE_FLAG_COUNT(
+ quic_send_version_negotiation_for_short_connection_ids);
+ should_check_short_connection_ids =
+ packet_info.version_flag && packet_info.version.IsKnown();
+ }
+ if (should_check_short_connection_ids &&
+ server_connection_id.length() < kQuicMinimumInitialConnectionIdLength &&
server_connection_id.length() < expected_server_connection_id_length_ &&
!allow_short_initial_server_connection_ids_) {
DCHECK(packet_info.version_flag);
diff --git a/quic/core/quic_dispatcher_test.cc b/quic/core/quic_dispatcher_test.cc
index a88eadb..9f692a8 100644
--- a/quic/core/quic_dispatcher_test.cc
+++ b/quic/core/quic_dispatcher_test.cc
@@ -471,6 +471,10 @@
void TestTlsMultiPacketClientHello(bool add_reordering);
+ void TestVersionNegotiationForUnknownVersionInvalidShortInitialConnectionId(
+ const QuicConnectionId& server_connection_id,
+ const QuicConnectionId& client_connection_id);
+
ParsedQuicVersion version_;
MockQuicConnectionHelper mock_helper_;
MockAlarmFactory mock_alarm_factory_;
@@ -1054,7 +1058,7 @@
}
TEST_P(QuicDispatcherTestAllVersions,
- ProcessPacketWithInvalidShortInitialConnectionId) {
+ DropPacketWithKnownVersionAndInvalidShortInitialConnectionId) {
if (!version_.AllowsVariableLengthConnectionIds()) {
return;
}
@@ -1063,14 +1067,59 @@
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
// dispatcher_ should drop this packet.
- EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, client_address, _, _))
- .Times(0);
+ EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _, _)).Times(0);
EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, _, _, _)).Times(0);
EXPECT_CALL(*time_wait_list_manager_, AddConnectionIdToTimeWait(_, _, _))
.Times(0);
ProcessFirstFlight(client_address, EmptyQuicConnectionId());
}
+void QuicDispatcherTestBase::
+ TestVersionNegotiationForUnknownVersionInvalidShortInitialConnectionId(
+ const QuicConnectionId& server_connection_id,
+ const QuicConnectionId& client_connection_id) {
+ SetQuicReloadableFlag(quic_send_version_negotiation_for_short_connection_ids,
+ true);
+ CreateTimeWaitListManager();
+
+ QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
+
+ EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _, _)).Times(0);
+ EXPECT_CALL(*time_wait_list_manager_,
+ SendVersionNegotiationPacket(
+ server_connection_id, client_connection_id,
+ /*ietf_quic=*/true,
+ /*use_length_prefix=*/true, _, _, client_address, _))
+ .Times(1);
+ ProcessFirstFlight(ParsedQuicVersion::ReservedForNegotiation(),
+ client_address, server_connection_id,
+ client_connection_id);
+}
+
+TEST_P(QuicDispatcherTestOneVersion,
+ VersionNegotiationForUnknownVersionInvalidShortInitialConnectionId) {
+ TestVersionNegotiationForUnknownVersionInvalidShortInitialConnectionId(
+ EmptyQuicConnectionId(), EmptyQuicConnectionId());
+}
+
+TEST_P(QuicDispatcherTestOneVersion,
+ VersionNegotiationForUnknownVersionInvalidShortInitialConnectionId2) {
+ char server_connection_id_bytes[3] = {1, 2, 3};
+ QuicConnectionId server_connection_id(server_connection_id_bytes,
+ sizeof(server_connection_id_bytes));
+ TestVersionNegotiationForUnknownVersionInvalidShortInitialConnectionId(
+ server_connection_id, EmptyQuicConnectionId());
+}
+
+TEST_P(QuicDispatcherTestOneVersion,
+ VersionNegotiationForUnknownVersionInvalidShortInitialConnectionId3) {
+ char client_connection_id_bytes[8] = {1, 2, 3, 4, 5, 6, 7, 8};
+ QuicConnectionId client_connection_id(client_connection_id_bytes,
+ sizeof(client_connection_id_bytes));
+ TestVersionNegotiationForUnknownVersionInvalidShortInitialConnectionId(
+ EmptyQuicConnectionId(), client_connection_id);
+}
+
TEST_P(QuicDispatcherTestOneVersion, VersionsChangeInFlight) {
VerifyVersionNotSupported(QuicVersionReservedForNegotiation());
for (ParsedQuicVersion version : CurrentSupportedVersions()) {
diff --git a/quic/core/quic_framer.cc b/quic/core/quic_framer.cc
index 19b0cd5..03b27f2 100644
--- a/quic/core/quic_framer.cc
+++ b/quic/core/quic_framer.cc
@@ -6671,8 +6671,7 @@
return false;
}
if (destination_connection_id_length > kQuicMaxConnectionId4BitLength ||
- destination_connection_id_length <
- kQuicMinimumInitialConnectionIdLength) {
+ destination_connection_id_length < kQuicDefaultConnectionIdLength) {
QUIC_BUG << "Invalid connection_id_length";
return false;
}
diff --git a/quic/core/quic_versions.cc b/quic/core/quic_versions.cc
index d2b5774..98bef7f 100644
--- a/quic/core/quic_versions.cc
+++ b/quic/core/quic_versions.cc
@@ -664,6 +664,8 @@
// Enable necessary flags.
SetQuicRestartFlag(quic_enable_zero_rtt_for_tls_v2, true);
SetQuicReloadableFlag(quic_key_update_supported, true);
+ SetQuicReloadableFlag(quic_send_version_negotiation_for_short_connection_ids,
+ true);
}
void QuicEnableVersion(const ParsedQuicVersion& version) {
diff --git a/quic/test_tools/quic_test_utils.cc b/quic/test_tools/quic_test_utils.cc
index b286764..0357ee2 100644
--- a/quic/test_tools/quic_test_utils.cc
+++ b/quic/test_tools/quic_test_utils.cc
@@ -1572,11 +1572,6 @@
QUIC_BUG << "Invalid destination_connection_id_length_out";
return false;
}
- if (*destination_connection_id_length_out <
- kQuicMinimumInitialConnectionIdLength) {
- QUIC_BUG << "Invalid *destination_connection_id_length_out";
- return false;
- }
QuicEncryptedPacket encrypted_packet(packet_bytes, packet_length);
PacketHeaderFormat format;
@@ -1601,12 +1596,6 @@
QUIC_BUG << "Packet is not a long header";
return false;
}
- if (destination_connection_id.length() <
- kQuicMinimumInitialConnectionIdLength) {
- QUIC_BUG << "Invalid destination_connection_id length "
- << static_cast<int>(destination_connection_id.length());
- return false;
- }
if (*destination_connection_id_length_out <
destination_connection_id.length()) {
QUIC_BUG << "destination_connection_id_length_out too small";