Add a client connection ID to version negotiation packet creation

This CL adds a new client_connection_id parameter to the functions that build version negotiation packets, and pass it through to AppendIetfConnectionIds instead of EmptyQuicConnectionId. All callers of this function call it with EmptyQuicConnectionId. To verify this we have a DCHECK that makes sure client_connection_id is empty when the disabled flag quic_do_not_override_connection_id is false. This CL also adds QuicVersion::SupportsClientConnectionIds which subsequent CLs will build on.

gfe-relnote: no functional change, add function parameter that is always empty, not flag-protected
PiperOrigin-RevId: 250551156
Change-Id: I378c67df16fc262145c5c88a76ca5440f72a29d8
diff --git a/quic/core/http/end_to_end_test.cc b/quic/core/http/end_to_end_test.cc
index 38beca0..0a0326c 100644
--- a/quic/core/http/end_to_end_test.cc
+++ b/quic/core/http/end_to_end_test.cc
@@ -2376,7 +2376,7 @@
       TestConnectionIdToUInt64(client_connection->connection_id()) + 1);
   std::unique_ptr<QuicEncryptedPacket> packet(
       QuicFramer::BuildVersionNegotiationPacket(
-          incorrect_connection_id,
+          incorrect_connection_id, EmptyQuicConnectionId(),
           client_connection->transport_version() > QUIC_VERSION_43,
           server_supported_versions_));
   testing::NiceMock<MockQuicConnectionDebugVisitor> visitor;
diff --git a/quic/core/quic_connection_test.cc b/quic/core/quic_connection_test.cc
index ebfaeaa..554f71a 100644
--- a/quic/core/quic_connection_test.cc
+++ b/quic/core/quic_connection_test.cc
@@ -6905,8 +6905,9 @@
 
   // Send a version negotiation packet.
   std::unique_ptr<QuicEncryptedPacket> encrypted(
-      peer_framer_.BuildVersionNegotiationPacket(
-          connection_id_, connection_.transport_version() > QUIC_VERSION_43,
+      QuicFramer::BuildVersionNegotiationPacket(
+          connection_id_, EmptyQuicConnectionId(),
+          connection_.transport_version() > QUIC_VERSION_43,
           AllSupportedVersions()));
   std::unique_ptr<QuicReceivedPacket> received(
       ConstructReceivedPacket(*encrypted, QuicTime::Zero()));
@@ -6960,8 +6961,9 @@
               OnConnectionClosed(QUIC_INVALID_VERSION_NEGOTIATION_PACKET, _,
                                  ConnectionCloseSource::FROM_SELF));
   std::unique_ptr<QuicEncryptedPacket> encrypted(
-      framer_.BuildVersionNegotiationPacket(
-          connection_id_, connection_.transport_version() > QUIC_VERSION_43,
+      QuicFramer::BuildVersionNegotiationPacket(
+          connection_id_, EmptyQuicConnectionId(),
+          connection_.transport_version() > QUIC_VERSION_43,
           AllSupportedVersions()));
   std::unique_ptr<QuicReceivedPacket> received(
       ConstructReceivedPacket(*encrypted, QuicTime::Zero()));
diff --git a/quic/core/quic_dispatcher.cc b/quic/core/quic_dispatcher.cc
index 63a64c9..5bf072d 100644
--- a/quic/core/quic_dispatcher.cc
+++ b/quic/core/quic_dispatcher.cc
@@ -473,9 +473,10 @@
         // Since the version is not supported, send a version negotiation
         // packet and stop processing the current packet.
         time_wait_list_manager()->SendVersionNegotiationPacket(
-            server_connection_id, header.form != GOOGLE_QUIC_PACKET,
-            GetSupportedVersions(), current_self_address_,
-            current_peer_address_, GetPerPacketContext());
+            server_connection_id, EmptyQuicConnectionId(),
+            header.form != GOOGLE_QUIC_PACKET, GetSupportedVersions(),
+            current_self_address_, current_peer_address_,
+            GetPerPacketContext());
       }
       return false;
     }
@@ -840,7 +841,8 @@
   // with an empty version list, which can be understood by the client.
   std::vector<std::unique_ptr<QuicEncryptedPacket>> termination_packets;
   termination_packets.push_back(QuicFramer::BuildVersionNegotiationPacket(
-      server_connection_id, /*ietf_quic=*/format != GOOGLE_QUIC_PACKET,
+      server_connection_id, EmptyQuicConnectionId(),
+      /*ietf_quic=*/format != GOOGLE_QUIC_PACKET,
       ParsedQuicVersionVector{UnsupportedQuicVersion()}));
   if (format == GOOGLE_QUIC_PACKET) {
     QUIC_RELOADABLE_FLAG_COUNT_N(quic_terminate_gquic_connection_as_ietf, 2, 2);
diff --git a/quic/core/quic_dispatcher_test.cc b/quic/core/quic_dispatcher_test.cc
index 6fdd130..105bd00 100644
--- a/quic/core/quic_dispatcher_test.cc
+++ b/quic/core/quic_dispatcher_test.cc
@@ -492,7 +492,7 @@
 
   EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
   EXPECT_CALL(*time_wait_list_manager_,
-              SendVersionNegotiationPacket(_, _, _, _, _, _))
+              SendVersionNegotiationPacket(_, _, _, _, _, _, _))
       .Times(1);
   QuicTransportVersion version =
       static_cast<QuicTransportVersion>(QuicTransportVersionMin() - 1);
@@ -511,7 +511,7 @@
 
   EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
   EXPECT_CALL(*time_wait_list_manager_,
-              SendVersionNegotiationPacket(_, _, _, _, _, _))
+              SendVersionNegotiationPacket(_, _, _, _, _, _, _))
       .Times(0);
   QuicTransportVersion version =
       static_cast<QuicTransportVersion>(QuicTransportVersionMin() - 1);
@@ -537,7 +537,7 @@
 
   EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
   EXPECT_CALL(*time_wait_list_manager_,
-              SendVersionNegotiationPacket(_, _, _, _, _, _))
+              SendVersionNegotiationPacket(_, _, _, _, _, _, _))
       .Times(1);
   QuicTransportVersion version =
       static_cast<QuicTransportVersion>(QuicTransportVersionMin() - 1);
diff --git a/quic/core/quic_framer.cc b/quic/core/quic_framer.cc
index b66b98d..7e34b3b 100644
--- a/quic/core/quic_framer.cc
+++ b/quic/core/quic_framer.cc
@@ -1389,11 +1389,17 @@
 // static
 std::unique_ptr<QuicEncryptedPacket> QuicFramer::BuildVersionNegotiationPacket(
     QuicConnectionId server_connection_id,
+    QuicConnectionId client_connection_id,
     bool ietf_quic,
     const ParsedQuicVersionVector& versions) {
   if (ietf_quic) {
-    return BuildIetfVersionNegotiationPacket(server_connection_id, versions);
+    return BuildIetfVersionNegotiationPacket(server_connection_id,
+                                             client_connection_id, versions);
   }
+
+  // The GQUIC encoding does not support encoding client connection IDs.
+  DCHECK(client_connection_id.IsEmpty());
+
   DCHECK(!versions.empty());
   size_t len = kPublicFlagsSize + server_connection_id.length() +
                versions.size() * kQuicVersionSize;
@@ -1428,13 +1434,16 @@
 // static
 std::unique_ptr<QuicEncryptedPacket>
 QuicFramer::BuildIetfVersionNegotiationPacket(
-    QuicConnectionId source_connection_id,
+    QuicConnectionId server_connection_id,
+    QuicConnectionId client_connection_id,
     const ParsedQuicVersionVector& versions) {
   QUIC_DVLOG(1) << "Building IETF version negotiation packet: "
                 << ParsedQuicVersionVectorToString(versions);
+  DCHECK(client_connection_id.IsEmpty() ||
+         GetQuicRestartFlag(quic_do_not_override_connection_id));
   DCHECK(!versions.empty());
   size_t len = kPacketHeaderTypeSize + kConnectionIdLengthSize +
-               source_connection_id.length() +
+               client_connection_id.length() + server_connection_id.length() +
                (versions.size() + 1) * kQuicVersionSize;
   std::unique_ptr<char[]> buffer(new char[len]);
   QuicDataWriter writer(len, buffer.get());
@@ -1453,8 +1462,8 @@
     return nullptr;
   }
 
-  if (!AppendIetfConnectionIds(true, EmptyQuicConnectionId(),
-                               source_connection_id, &writer)) {
+  if (!AppendIetfConnectionIds(true, client_connection_id, server_connection_id,
+                               &writer)) {
     return nullptr;
   }
 
diff --git a/quic/core/quic_framer.h b/quic/core/quic_framer.h
index d939175..11d48bb 100644
--- a/quic/core/quic_framer.h
+++ b/quic/core/quic_framer.h
@@ -435,13 +435,15 @@
 
   // Returns a new version negotiation packet.
   static std::unique_ptr<QuicEncryptedPacket> BuildVersionNegotiationPacket(
-      QuicConnectionId connection_id,
+      QuicConnectionId server_connection_id,
+      QuicConnectionId client_connection_id,
       bool ietf_quic,
       const ParsedQuicVersionVector& versions);
 
   // Returns a new IETF version negotiation packet.
   static std::unique_ptr<QuicEncryptedPacket> BuildIetfVersionNegotiationPacket(
-      QuicConnectionId source_connection_id,
+      QuicConnectionId server_connection_id,
+      QuicConnectionId client_connection_id,
       const ParsedQuicVersionVector& versions);
 
   // If header.version_flag is set, the version in the
diff --git a/quic/core/quic_framer_test.cc b/quic/core/quic_framer_test.cc
index 0201c8e..13e4482 100644
--- a/quic/core/quic_framer_test.cc
+++ b/quic/core/quic_framer_test.cc
@@ -6625,13 +6625,55 @@
 
   QuicConnectionId connection_id = FramerTestConnectionId();
   std::unique_ptr<QuicEncryptedPacket> data(
-      framer_.BuildVersionNegotiationPacket(
-          connection_id, framer_.transport_version() > QUIC_VERSION_43,
+      QuicFramer::BuildVersionNegotiationPacket(
+          connection_id, EmptyQuicConnectionId(),
+          framer_.transport_version() > QUIC_VERSION_43,
           SupportedVersions(GetParam())));
   test::CompareCharArraysWithHexError("constructed packet", data->data(),
                                       data->length(), AsChars(p), p_size);
 }
 
+TEST_P(QuicFramerTest, BuildVersionNegotiationPacketWithClientConnectionId) {
+  if (framer_.transport_version() <= QUIC_VERSION_43) {
+    // The GQUIC encoding does not support encoding client connection IDs.
+    return;
+  }
+
+  // Client connection IDs cannot be used unless this flag is true.
+  SetQuicRestartFlag(quic_do_not_override_connection_id, true);
+
+  unsigned char type_byte = 0x80;
+  if (GetQuicReloadableFlag(quic_send_version_negotiation_fixed_bit)) {
+    type_byte = 0xC0;
+  }
+  // clang-format off
+  unsigned char packet[] = {
+      // type (long header)
+      type_byte,
+      // version tag
+      0x00, 0x00, 0x00, 0x00,
+      // connection ID lengths
+      0x55,
+      // client/destination connection ID
+      0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x11,
+      // server/source connection ID
+      0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+      // version tag
+      QUIC_VERSION_BYTES,
+  };
+  // clang-format on
+
+  QuicConnectionId server_connection_id = FramerTestConnectionId();
+  QuicConnectionId client_connection_id = FramerTestConnectionIdPlusOne();
+  std::unique_ptr<QuicEncryptedPacket> data(
+      QuicFramer::BuildVersionNegotiationPacket(server_connection_id,
+                                                client_connection_id, true,
+                                                SupportedVersions(GetParam())));
+  test::CompareCharArraysWithHexError("constructed packet", data->data(),
+                                      data->length(), AsChars(packet),
+                                      QUIC_ARRAYSIZE(packet));
+}
+
 TEST_P(QuicFramerTest, BuildAckFramePacketOneAckBlock) {
   QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
   QuicPacketHeader header;
diff --git a/quic/core/quic_packet_creator.cc b/quic/core/quic_packet_creator.cc
index 5a53ffd..7420c72 100644
--- a/quic/core/quic_packet_creator.cc
+++ b/quic/core/quic_packet_creator.cc
@@ -625,6 +625,7 @@
   DCHECK_EQ(Perspective::IS_SERVER, framer_->perspective());
   std::unique_ptr<QuicEncryptedPacket> encrypted =
       QuicFramer::BuildVersionNegotiationPacket(server_connection_id_,
+                                                EmptyQuicConnectionId(),
                                                 ietf_quic, supported_versions);
   DCHECK(encrypted);
   DCHECK_GE(max_packet_length_, encrypted->length());
diff --git a/quic/core/quic_time_wait_list_manager.cc b/quic/core/quic_time_wait_list_manager.cc
index 56cd70a..f1f6dcf 100644
--- a/quic/core/quic_time_wait_list_manager.cc
+++ b/quic/core/quic_time_wait_list_manager.cc
@@ -201,14 +201,16 @@
 }
 
 void QuicTimeWaitListManager::SendVersionNegotiationPacket(
-    QuicConnectionId connection_id,
+    QuicConnectionId server_connection_id,
+    QuicConnectionId client_connection_id,
     bool ietf_quic,
     const ParsedQuicVersionVector& supported_versions,
     const QuicSocketAddress& self_address,
     const QuicSocketAddress& peer_address,
     std::unique_ptr<QuicPerPacketContext> packet_context) {
   std::unique_ptr<QuicEncryptedPacket> version_packet =
-      QuicFramer::BuildVersionNegotiationPacket(connection_id, ietf_quic,
+      QuicFramer::BuildVersionNegotiationPacket(server_connection_id,
+                                                client_connection_id, ietf_quic,
                                                 supported_versions);
   QUIC_DVLOG(2) << "Dispatcher sending version negotiation packet: {"
                 << ParsedQuicVersionVectorToString(supported_versions) << "}, "
diff --git a/quic/core/quic_time_wait_list_manager.h b/quic/core/quic_time_wait_list_manager.h
index dee5d11..ba0c763 100644
--- a/quic/core/quic_time_wait_list_manager.h
+++ b/quic/core/quic_time_wait_list_manager.h
@@ -118,10 +118,12 @@
   // The number of connections on the time-wait list.
   size_t num_connections() const { return connection_id_map_.size(); }
 
-  // Sends a version negotiation packet for |connection_id| announcing support
-  // for |supported_versions| to |peer_address| from |self_address|.
+  // Sends a version negotiation packet for |server_connection_id| and
+  // |client_connection_id| announcing support for |supported_versions| to
+  // |peer_address| from |self_address|.
   virtual void SendVersionNegotiationPacket(
-      QuicConnectionId connection_id,
+      QuicConnectionId server_connection_id,
+      QuicConnectionId client_connection_id,
       bool ietf_quic,
       const ParsedQuicVersionVector& supported_versions,
       const QuicSocketAddress& self_address,
diff --git a/quic/core/quic_time_wait_list_manager_test.cc b/quic/core/quic_time_wait_list_manager_test.cc
index a391390..4624a23 100644
--- a/quic/core/quic_time_wait_list_manager_test.cc
+++ b/quic/core/quic_time_wait_list_manager_test.cc
@@ -251,15 +251,50 @@
 
 TEST_F(QuicTimeWaitListManagerTest, SendVersionNegotiationPacket) {
   std::unique_ptr<QuicEncryptedPacket> packet(
-      QuicFramer::BuildVersionNegotiationPacket(connection_id_, false,
+      QuicFramer::BuildVersionNegotiationPacket(connection_id_,
+                                                EmptyQuicConnectionId(), false,
                                                 AllSupportedVersions()));
   EXPECT_CALL(writer_, WritePacket(_, packet->length(), self_address_.host(),
                                    peer_address_, _))
       .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 1)));
 
   time_wait_list_manager_.SendVersionNegotiationPacket(
-      connection_id_, false, AllSupportedVersions(), self_address_,
-      peer_address_, QuicMakeUnique<QuicPerPacketContext>());
+      connection_id_, EmptyQuicConnectionId(), false, AllSupportedVersions(),
+      self_address_, peer_address_, QuicMakeUnique<QuicPerPacketContext>());
+  EXPECT_EQ(0u, time_wait_list_manager_.num_connections());
+}
+
+TEST_F(QuicTimeWaitListManagerTest, SendIetfVersionNegotiationPacket) {
+  std::unique_ptr<QuicEncryptedPacket> packet(
+      QuicFramer::BuildVersionNegotiationPacket(connection_id_,
+                                                EmptyQuicConnectionId(), true,
+                                                AllSupportedVersions()));
+  EXPECT_CALL(writer_, WritePacket(_, packet->length(), self_address_.host(),
+                                   peer_address_, _))
+      .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 1)));
+
+  time_wait_list_manager_.SendVersionNegotiationPacket(
+      connection_id_, EmptyQuicConnectionId(), true, AllSupportedVersions(),
+      self_address_, peer_address_, QuicMakeUnique<QuicPerPacketContext>());
+  EXPECT_EQ(0u, time_wait_list_manager_.num_connections());
+}
+
+TEST_F(QuicTimeWaitListManagerTest,
+       SendIetfVersionNegotiationPacketWithClientConnectionId) {
+  // Client connection IDs cannot be used unless this flag is true.
+  SetQuicRestartFlag(quic_do_not_override_connection_id, true);
+
+  std::unique_ptr<QuicEncryptedPacket> packet(
+      QuicFramer::BuildVersionNegotiationPacket(connection_id_,
+                                                TestConnectionId(0x33), true,
+                                                AllSupportedVersions()));
+  EXPECT_CALL(writer_, WritePacket(_, packet->length(), self_address_.host(),
+                                   peer_address_, _))
+      .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 1)));
+
+  time_wait_list_manager_.SendVersionNegotiationPacket(
+      connection_id_, TestConnectionId(0x33), true, AllSupportedVersions(),
+      self_address_, peer_address_, QuicMakeUnique<QuicPerPacketContext>());
   EXPECT_EQ(0u, time_wait_list_manager_.num_connections());
 }
 
diff --git a/quic/core/quic_versions.cc b/quic/core/quic_versions.cc
index 94ad7fd..6873edd 100644
--- a/quic/core/quic_versions.cc
+++ b/quic/core/quic_versions.cc
@@ -55,6 +55,12 @@
   return transport_version > QUIC_VERSION_46;
 }
 
+bool ParsedQuicVersion::SupportsClientConnectionIds() const {
+  // This will be enabled in v99 after the rest of the client connection ID
+  // code lands.
+  return false;
+}
+
 std::ostream& operator<<(std::ostream& os, const ParsedQuicVersion& version) {
   os << ParsedQuicVersionToString(version);
   return os;
diff --git a/quic/core/quic_versions.h b/quic/core/quic_versions.h
index 939ee36..0a368df 100644
--- a/quic/core/quic_versions.h
+++ b/quic/core/quic_versions.h
@@ -162,6 +162,9 @@
 
   // Returns whether this version supports IETF RETRY packets.
   bool SupportsRetry() const;
+
+  // Returns whether this version supports client connection ID.
+  bool SupportsClientConnectionIds() const;
 };
 
 QUIC_EXPORT_PRIVATE ParsedQuicVersion UnsupportedQuicVersion();
diff --git a/quic/test_tools/mock_quic_time_wait_list_manager.h b/quic/test_tools/mock_quic_time_wait_list_manager.h
index d13d5ac..8a39442 100644
--- a/quic/test_tools/mock_quic_time_wait_list_manager.h
+++ b/quic/test_tools/mock_quic_time_wait_list_manager.h
@@ -45,8 +45,9 @@
                     PacketHeaderFormat header_format,
                     std::unique_ptr<QuicPerPacketContext> packet_context));
 
-  MOCK_METHOD6(SendVersionNegotiationPacket,
-               void(QuicConnectionId connection_id,
+  MOCK_METHOD7(SendVersionNegotiationPacket,
+               void(QuicConnectionId server_connection_id,
+                    QuicConnectionId client_connection_id,
                     bool ietf_quic,
                     const ParsedQuicVersionVector& supported_versions,
                     const QuicSocketAddress& server_address,