Allow variable length connection IDs for unsupported versions

This solves an IETF interop issue where other implementation were failing to trigger version negotiation with a destination connection ID length > 8.

gfe-relnote: allow using QUIC version negotiation with custom connection ID lengths, protected by gfe2_restart_flag_quic_allow_variable_length_connection_id_for_negotiation
PiperOrigin-RevId: 247647676
Change-Id: I5709072f50264f6f207c8e8689d0ed5dd5f6a712
diff --git a/quic/core/http/end_to_end_test.cc b/quic/core/http/end_to_end_test.cc
index 777291d..04567f1 100644
--- a/quic/core/http/end_to_end_test.cc
+++ b/quic/core/http/end_to_end_test.cc
@@ -770,6 +770,33 @@
                                                 .length());
 }
 
+TEST_P(EndToEndTest, ForcedVersionNegotiationAndBadConnectionIdLength) {
+  if (!GetQuicRestartFlag(
+          quic_allow_variable_length_connection_id_for_negotiation)) {
+    ASSERT_TRUE(Initialize());
+    return;
+  }
+  if (!QuicUtils::VariableLengthConnectionIdAllowedForVersion(
+          GetParam().negotiated_version.transport_version)) {
+    ASSERT_TRUE(Initialize());
+    return;
+  }
+  client_supported_versions_.insert(client_supported_versions_.begin(),
+                                    QuicVersionReservedForNegotiation());
+  QuicConnectionId connection_id =
+      TestConnectionIdNineBytesLong(UINT64_C(0xBADbadBADbad));
+  override_connection_id_ = &connection_id;
+  ASSERT_TRUE(Initialize());
+  ASSERT_TRUE(ServerSendsVersionNegotiation());
+  EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
+  EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
+  EXPECT_EQ(kQuicDefaultConnectionIdLength, client_->client()
+                                                ->client_session()
+                                                ->connection()
+                                                ->connection_id()
+                                                .length());
+}
+
 TEST_P(EndToEndTest, MixGoodAndBadConnectionIdLengths) {
   if (!QuicUtils::VariableLengthConnectionIdAllowedForVersion(
           GetParam().negotiated_version.transport_version)) {
diff --git a/quic/core/quic_utils.cc b/quic/core/quic_utils.cc
index e1caf89..85ce4f2 100644
--- a/quic/core/quic_utils.cc
+++ b/quic/core/quic_utils.cc
@@ -15,6 +15,7 @@
 #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_prefetch.h"
 #include "net/third_party/quiche/src/quic/platform/api/quic_uint128.h"
@@ -505,7 +506,16 @@
 // static
 bool QuicUtils::VariableLengthConnectionIdAllowedForVersion(
     QuicTransportVersion version) {
-  return version >= QUIC_VERSION_47;
+  if (!GetQuicRestartFlag(
+          quic_allow_variable_length_connection_id_for_negotiation)) {
+    return version >= QUIC_VERSION_47;
+  }
+  QUIC_RESTART_FLAG_COUNT(
+      quic_allow_variable_length_connection_id_for_negotiation);
+  // We allow variable length connection IDs for unsupported versions to
+  // ensure that IETF version negotiation works when other implementations
+  // trigger version negotiation with custom connection ID lengths.
+  return version >= QUIC_VERSION_47 || version == QUIC_VERSION_UNSUPPORTED;
 }
 
 // static
diff --git a/quic/core/quic_versions.cc b/quic/core/quic_versions.cc
index 002062f..c4564a7 100644
--- a/quic/core/quic_versions.cc
+++ b/quic/core/quic_versions.cc
@@ -446,6 +446,8 @@
   SetQuicRestartFlag(quic_no_server_conn_ver_negotiation2, true);
   SetQuicRestartFlag(quic_server_drop_version_negotiation, true);
   SetQuicRestartFlag(quic_enable_accept_random_ipn, true);
+  SetQuicRestartFlag(quic_allow_variable_length_connection_id_for_negotiation,
+                     true);
 }
 
 void QuicEnableVersion(ParsedQuicVersion parsed_version) {