Internal change

PiperOrigin-RevId: 468331059
diff --git a/build/source_list.bzl b/build/source_list.bzl
index 90dd052..9092865 100644
--- a/build/source_list.bzl
+++ b/build/source_list.bzl
@@ -778,6 +778,7 @@
     "quic/test_tools/first_flight.h",
     "quic/test_tools/limited_mtu_test_writer.h",
     "quic/test_tools/mock_clock.h",
+    "quic/test_tools/mock_connection_id_generator.h",
     "quic/test_tools/mock_quic_client_promised_info.h",
     "quic/test_tools/mock_quic_dispatcher.h",
     "quic/test_tools/mock_quic_session_visitor.h",
diff --git a/build/source_list.gni b/build/source_list.gni
index 842512d..e06888f 100644
--- a/build/source_list.gni
+++ b/build/source_list.gni
@@ -778,6 +778,7 @@
     "src/quiche/quic/test_tools/first_flight.h",
     "src/quiche/quic/test_tools/limited_mtu_test_writer.h",
     "src/quiche/quic/test_tools/mock_clock.h",
+    "src/quiche/quic/test_tools/mock_connection_id_generator.h",
     "src/quiche/quic/test_tools/mock_quic_client_promised_info.h",
     "src/quiche/quic/test_tools/mock_quic_dispatcher.h",
     "src/quiche/quic/test_tools/mock_quic_session_visitor.h",
diff --git a/build/source_list.json b/build/source_list.json
index 6d14856..0811079 100644
--- a/build/source_list.json
+++ b/build/source_list.json
@@ -777,6 +777,7 @@
     "quiche/quic/test_tools/first_flight.h",
     "quiche/quic/test_tools/limited_mtu_test_writer.h",
     "quiche/quic/test_tools/mock_clock.h",
+    "quiche/quic/test_tools/mock_connection_id_generator.h",
     "quiche/quic/test_tools/mock_quic_client_promised_info.h",
     "quiche/quic/test_tools/mock_quic_dispatcher.h",
     "quiche/quic/test_tools/mock_quic_session_visitor.h",
diff --git a/quiche/quic/core/quic_dispatcher.cc b/quiche/quic/core/quic_dispatcher.cc
index 6a0c8ec..69c5b51 100644
--- a/quiche/quic/core/quic_dispatcher.cc
+++ b/quiche/quic/core/quic_dispatcher.cc
@@ -334,7 +334,8 @@
     std::unique_ptr<QuicConnectionHelperInterface> helper,
     std::unique_ptr<QuicCryptoServerStreamBase::Helper> session_helper,
     std::unique_ptr<QuicAlarmFactory> alarm_factory,
-    uint8_t expected_server_connection_id_length)
+    uint8_t expected_server_connection_id_length,
+    ConnectionIdGeneratorInterface& connection_id_generator)
     : config_(config),
       crypto_config_(crypto_config),
       compressed_certs_cache_(
@@ -354,7 +355,8 @@
           expected_server_connection_id_length),
       clear_stateless_reset_addresses_alarm_(alarm_factory_->CreateAlarm(
           new ClearStatelessResetAddressesAlarm(this))),
-      should_update_expected_server_connection_id_length_(false) {
+      should_update_expected_server_connection_id_length_(false),
+      connection_id_generator_(connection_id_generator) {
   QUIC_BUG_IF(quic_bug_12724_1, GetSupportedVersions().empty())
       << "Trying to create dispatcher without any supported versions";
   QUIC_DLOG(INFO) << "Created QuicDispatcher with versions: "
@@ -446,12 +448,17 @@
   ProcessHeader(&packet_info);
 }
 
-QuicConnectionId QuicDispatcher::MaybeReplaceServerConnectionId(
+absl::optional<QuicConnectionId> QuicDispatcher::MaybeReplaceServerConnectionId(
     const QuicConnectionId& server_connection_id,
-    const ParsedQuicVersion& version) const {
+    const ParsedQuicVersion& version) {
+  if (GetQuicRestartFlag(quic_abstract_connection_id_generator)) {
+    QUIC_RESTART_FLAG_COUNT(quic_abstract_connection_id_generator);
+    return connection_id_generator_.MaybeReplaceConnectionId(
+        server_connection_id, version);
+  }
   const uint8_t server_connection_id_length = server_connection_id.length();
   if (server_connection_id_length == expected_server_connection_id_length_) {
-    return server_connection_id;
+    return absl::optional<QuicConnectionId>();
   }
   QUICHE_DCHECK(version.AllowsVariableLengthConnectionIds());
   QuicConnectionId new_connection_id;
@@ -627,14 +634,15 @@
     // |reference_counted_session_map_| is storing original connection IDs
     // separately. It can be counterproductive to do this check if that
     // consumes a nonce or generates a random connection ID.
-    QuicConnectionId replaced_connection_id = MaybeReplaceServerConnectionId(
-        server_connection_id, packet_info.version);
-    if (replaced_connection_id != server_connection_id) {
+    absl::optional<QuicConnectionId> replaced_connection_id =
+        MaybeReplaceServerConnectionId(server_connection_id,
+                                       packet_info.version);
+    if (replaced_connection_id.has_value()) {
       // Search for the replacement.
-      auto it2 = reference_counted_session_map_.find(replaced_connection_id);
+      auto it2 = reference_counted_session_map_.find(*replaced_connection_id);
       if (it2 != reference_counted_session_map_.end()) {
         QUICHE_DCHECK(
-            !buffered_packets_.HasBufferedPackets(replaced_connection_id));
+            !buffered_packets_.HasBufferedPackets(*replaced_connection_id));
         it2->second->ProcessUdpPacket(packet_info.self_address,
                                       packet_info.peer_address,
                                       packet_info.packet);
@@ -1404,11 +1412,13 @@
     const ParsedClientHello& parsed_chlo, const ParsedQuicVersion version,
     const QuicSocketAddress self_address,
     const QuicSocketAddress peer_address) {
-  QuicConnectionId server_connection_id =
+  absl::optional<QuicConnectionId> server_connection_id =
       MaybeReplaceServerConnectionId(original_connection_id, version);
-  const bool replaced_connection_id =
-      original_connection_id != server_connection_id;
-  if (reference_counted_session_map_.count(server_connection_id) > 0 &&
+  const bool replaced_connection_id = server_connection_id.has_value();
+  if (!replaced_connection_id) {
+    server_connection_id = original_connection_id;
+  }
+  if (reference_counted_session_map_.count(*server_connection_id) > 0 &&
       GetQuicRestartFlag(quic_map_original_connection_ids2)) {
     // The new connection ID is owned by another session. Avoid creating one
     // altogether, as this connection attempt cannot possibly succeed.
@@ -1427,11 +1437,11 @@
   // Creates a new session and process all buffered packets for this connection.
   std::string alpn = SelectAlpn(parsed_chlo.alpns);
   std::unique_ptr<QuicSession> session =
-      CreateQuicSession(server_connection_id, self_address, peer_address, alpn,
+      CreateQuicSession(*server_connection_id, self_address, peer_address, alpn,
                         version, parsed_chlo);
   if (ABSL_PREDICT_FALSE(session == nullptr)) {
     QUIC_BUG(quic_bug_10287_8)
-        << "CreateQuicSession returned nullptr for " << server_connection_id
+        << "CreateQuicSession returned nullptr for " << *server_connection_id
         << " from " << peer_address << " to " << self_address << " ALPN \""
         << alpn << "\" version " << version;
     return nullptr;
@@ -1441,16 +1451,16 @@
     session->connection()->SetOriginalDestinationConnectionId(
         original_connection_id);
   }
-  QUIC_DLOG(INFO) << "Created new session for " << server_connection_id;
+  QUIC_DLOG(INFO) << "Created new session for " << *server_connection_id;
 
   auto insertion_result = reference_counted_session_map_.insert(std::make_pair(
-      server_connection_id, std::shared_ptr<QuicSession>(std::move(session))));
+      *server_connection_id, std::shared_ptr<QuicSession>(std::move(session))));
   std::shared_ptr<QuicSession> session_ptr = insertion_result.first->second;
   if (!insertion_result.second) {
     QUIC_BUG(quic_bug_10287_9)
         << "Tried to add a session to session_map with existing "
            "connection id: "
-        << server_connection_id;
+        << *server_connection_id;
   } else {
     ++num_sessions_in_session_map_;
     if (GetQuicRestartFlag(quic_map_original_connection_ids2) &&
diff --git a/quiche/quic/core/quic_dispatcher.h b/quiche/quic/core/quic_dispatcher.h
index 813655b..b461690 100644
--- a/quiche/quic/core/quic_dispatcher.h
+++ b/quiche/quic/core/quic_dispatcher.h
@@ -15,6 +15,7 @@
 
 #include "absl/container/flat_hash_map.h"
 #include "absl/strings/string_view.h"
+#include "quiche/quic/core/connection_id_generator.h"
 #include "quiche/quic/core/crypto/quic_compressed_certs_cache.h"
 #include "quiche/quic/core/crypto/quic_random.h"
 #include "quiche/quic/core/quic_blocked_writer_interface.h"
@@ -54,7 +55,8 @@
       std::unique_ptr<QuicConnectionHelperInterface> helper,
       std::unique_ptr<QuicCryptoServerStreamBase::Helper> session_helper,
       std::unique_ptr<QuicAlarmFactory> alarm_factory,
-      uint8_t expected_server_connection_id_length);
+      uint8_t expected_server_connection_id_length,
+      ConnectionIdGeneratorInterface& connection_id_generator);
   QuicDispatcher(const QuicDispatcher&) = delete;
   QuicDispatcher& operator=(const QuicDispatcher&) = delete;
 
@@ -340,13 +342,10 @@
   // element of the vector is returned.
   std::string SelectAlpn(const std::vector<std::string>& alpns);
 
-  // If the connection ID length is different from what the dispatcher expects,
-  // replace the connection ID with one of the right length.
-  // Note that this MUST produce a deterministic result (calling this method
-  // with two connection IDs that are equal must produce the same result).
-  QuicConnectionId MaybeReplaceServerConnectionId(
+  // Check if the client-generated server connection ID needs to be replaced.
+  absl::optional<QuicConnectionId> MaybeReplaceServerConnectionId(
       const QuicConnectionId& server_connection_id,
-      const ParsedQuicVersion& version) const;
+      const ParsedQuicVersion& version);
 
   // Sends public/stateless reset packets with no version and unknown
   // connection ID according to the packet's size.
@@ -478,6 +477,8 @@
 
   const bool send_connection_close_for_tls_alerts_ =
       GetQuicRestartFlag(quic_dispatcher_send_connection_close_for_tls_alerts);
+
+  ConnectionIdGeneratorInterface& connection_id_generator_;
 };
 
 }  // namespace quic
diff --git a/quiche/quic/core/quic_dispatcher_test.cc b/quiche/quic/core/quic_dispatcher_test.cc
index 5c71e62..5d05bd6 100644
--- a/quiche/quic/core/quic_dispatcher_test.cc
+++ b/quiche/quic/core/quic_dispatcher_test.cc
@@ -16,6 +16,7 @@
 #include "quiche/quic/core/crypto/crypto_protocol.h"
 #include "quiche/quic/core/crypto/quic_crypto_server_config.h"
 #include "quiche/quic/core/crypto/quic_random.h"
+#include "quiche/quic/core/deterministic_connection_id_generator.h"
 #include "quiche/quic/core/frames/quic_new_connection_id_frame.h"
 #include "quiche/quic/core/quic_config.h"
 #include "quiche/quic/core/quic_connection.h"
@@ -33,6 +34,7 @@
 #include "quiche/quic/test_tools/crypto_test_utils.h"
 #include "quiche/quic/test_tools/fake_proof_source.h"
 #include "quiche/quic/test_tools/first_flight.h"
+#include "quiche/quic/test_tools/mock_connection_id_generator.h"
 #include "quiche/quic/test_tools/mock_quic_time_wait_list_manager.h"
 #include "quiche/quic/test_tools/quic_buffered_packet_store_peer.h"
 #include "quiche/quic/test_tools/quic_connection_peer.h"
@@ -108,13 +110,14 @@
  public:
   TestDispatcher(const QuicConfig* config,
                  const QuicCryptoServerConfig* crypto_config,
-                 QuicVersionManager* version_manager, QuicRandom* random)
+                 QuicVersionManager* version_manager, QuicRandom* random,
+                 ConnectionIdGeneratorInterface& generator)
       : QuicDispatcher(config, crypto_config, version_manager,
                        std::make_unique<MockQuicConnectionHelper>(),
                        std::unique_ptr<QuicCryptoServerStreamBase::Helper>(
                            new QuicSimpleCryptoServerStreamHelper()),
                        std::make_unique<TestAlarmFactory>(),
-                       kQuicDefaultConnectionIdLength),
+                       kQuicDefaultConnectionIdLength, generator),
         random_(random) {}
 
   MOCK_METHOD(std::unique_ptr<QuicSession>, CreateQuicSession,
@@ -223,9 +226,10 @@
                        QuicRandom::GetInstance(), std::move(proof_source),
                        KeyExchangeSource::Default()),
         server_address_(QuicIpAddress::Any4(), 5),
+        connection_id_generator_(kQuicDefaultConnectionIdLength),
         dispatcher_(new NiceMock<TestDispatcher>(
             &config_, &crypto_config_, &version_manager_,
-            mock_helper_.GetRandomGenerator())),
+            mock_helper_.GetRandomGenerator(), connection_id_generator_)),
         time_wait_list_manager_(nullptr),
         session1_(nullptr),
         session2_(nullptr),
@@ -516,6 +520,7 @@
   QuicVersionManager version_manager_;
   QuicCryptoServerConfig crypto_config_;
   QuicSocketAddress server_address_;
+  DeterministicConnectionIdGenerator connection_id_generator_;
   std::unique_ptr<NiceMock<TestDispatcher>> dispatcher_;
   MockTimeWaitListManager* time_wait_list_manager_;
   TestQuicSpdyServerSession* session1_;
@@ -1058,6 +1063,78 @@
                 "data");
 }
 
+TEST_P(QuicDispatcherTestAllVersions, UsesConnectionIdGenerator) {
+  SetQuicRestartFlag(quic_abstract_connection_id_generator, true);
+  // Avoid multiple calls to MaybeReplaceConnectionId()
+  SetQuicRestartFlag(quic_map_original_connection_ids2, true);
+  // Create a new dispatcher with the Mock generator.
+  QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
+  MockConnectionIdGenerator generator;
+  dispatcher_.reset();
+  dispatcher_ = std::make_unique<NiceMock<TestDispatcher>>(
+      &config_, &crypto_config_, &version_manager_,
+      mock_helper_.GetRandomGenerator(), generator);
+  SetUp();
+  // Generator does not change connection ID.
+  EXPECT_CALL(generator, MaybeReplaceConnectionId(TestConnectionId(1), _))
+      .WillOnce(Return(absl::optional<QuicConnectionId>()));
+  EXPECT_CALL(*dispatcher_,
+              CreateQuicSession(TestConnectionId(1), _, client_address,
+                                Eq(ExpectedAlpn()), _, _))
+      .WillOnce(Return(CreateSession(
+          dispatcher_.get(), config_, TestConnectionId(1), client_address,
+          &mock_helper_, &mock_alarm_factory_, &crypto_config_,
+          QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
+  ProcessFirstFlight(client_address, TestConnectionId(1));
+  // Generator changes connection ID.
+  QuicConnectionId new_connection_id(
+      {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08});
+  EXPECT_CALL(generator, MaybeReplaceConnectionId(TestConnectionId(2), _))
+      .WillOnce(Return(new_connection_id));
+  EXPECT_CALL(*dispatcher_,
+              CreateQuicSession(new_connection_id, _, client_address,
+                                Eq(ExpectedAlpn()), _, _))
+      .WillOnce(Return(CreateSession(
+          dispatcher_.get(), config_, new_connection_id, client_address,
+          &mock_helper_, &mock_alarm_factory_, &crypto_config_,
+          QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
+  ProcessFirstFlight(client_address, TestConnectionId(2));
+}
+
+TEST_P(QuicDispatcherTestAllVersions, DoesNotUseConnectionIdGenerator) {
+  SetQuicRestartFlag(quic_abstract_connection_id_generator, false);
+  // Avoid multiple calls to MaybeReplaceConnectionId()
+  SetQuicRestartFlag(quic_map_original_connection_ids2, true);
+  // Create a new dispatcher with the Mock generator.
+  QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
+  MockConnectionIdGenerator generator;
+  dispatcher_.reset();
+  dispatcher_ = std::make_unique<NiceMock<TestDispatcher>>(
+      &config_, &crypto_config_, &version_manager_,
+      mock_helper_.GetRandomGenerator(), generator);
+  SetUp();
+  EXPECT_CALL(generator, MaybeReplaceConnectionId(TestConnectionId(1), _))
+      .Times(0);
+  EXPECT_CALL(*dispatcher_,
+              CreateQuicSession(TestConnectionId(1), _, client_address,
+                                Eq(ExpectedAlpn()), _, _))
+      .WillOnce(Return(CreateSession(
+          dispatcher_.get(), config_, TestConnectionId(1), client_address,
+          &mock_helper_, &mock_alarm_factory_, &crypto_config_,
+          QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
+  ProcessFirstFlight(client_address, TestConnectionId(1));
+  EXPECT_CALL(generator, MaybeReplaceConnectionId(TestConnectionId(2), _))
+      .Times(0);
+  EXPECT_CALL(*dispatcher_,
+              CreateQuicSession(TestConnectionId(2), _, client_address,
+                                Eq(ExpectedAlpn()), _, _))
+      .WillOnce(Return(CreateSession(
+          dispatcher_.get(), config_, TestConnectionId(2), client_address,
+          &mock_helper_, &mock_alarm_factory_, &crypto_config_,
+          QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
+  ProcessFirstFlight(client_address, TestConnectionId(2));
+}
+
 // Makes sure nine-byte connection IDs are replaced by 8-byte ones.
 TEST_P(QuicDispatcherTestAllVersions, LongConnectionIdLengthReplaced) {
   if (!version_.AllowsVariableLengthConnectionIds()) {
@@ -2158,7 +2235,7 @@
       : QuicDispatcherTestBase(crypto_test_utils::ProofSourceForTesting()) {
     dispatcher_ = std::make_unique<NiceMock<TestDispatcher>>(
         &config_, &crypto_config_, &version_manager_,
-        mock_helper_.GetRandomGenerator());
+        mock_helper_.GetRandomGenerator(), connection_id_generator_);
   }
   void AddConnection1() {
     QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
diff --git a/quiche/quic/core/quic_flags_list.h b/quiche/quic/core/quic_flags_list.h
index f043e97..46573ec 100644
--- a/quiche/quic/core/quic_flags_list.h
+++ b/quiche/quic/core/quic_flags_list.h
@@ -99,6 +99,8 @@
 QUIC_FLAG(quic_reloadable_flag_quic_validate_header_field_value_at_spdy_stream, true)
 // Store original QUIC connection IDs in the dispatcher\'s map
 QUIC_FLAG(quic_restart_flag_quic_map_original_connection_ids2, false)
+// Use a library to generate connection IDs
+QUIC_FLAG(quic_restart_flag_quic_abstract_connection_id_generator, false)
 // When the flag is true, exit STARTUP after the same number of loss events as PROBE_UP.
 QUIC_FLAG(quic_reloadable_flag_quic_bbr2_startup_probe_up_loss_events, true)
 // When true, defaults to BBR congestion control instead of Cubic.
diff --git a/quiche/quic/masque/masque_dispatcher.cc b/quiche/quic/masque/masque_dispatcher.cc
index 32776ee..6e081aa 100644
--- a/quiche/quic/masque/masque_dispatcher.cc
+++ b/quiche/quic/masque/masque_dispatcher.cc
@@ -16,11 +16,12 @@
     std::unique_ptr<QuicCryptoServerStreamBase::Helper> session_helper,
     std::unique_ptr<QuicAlarmFactory> alarm_factory,
     MasqueServerBackend* masque_server_backend,
-    uint8_t expected_server_connection_id_length)
+    uint8_t expected_server_connection_id_length,
+    ConnectionIdGeneratorInterface& generator)
     : QuicSimpleDispatcher(config, crypto_config, version_manager,
                            std::move(helper), std::move(session_helper),
                            std::move(alarm_factory), masque_server_backend,
-                           expected_server_connection_id_length),
+                           expected_server_connection_id_length, generator),
       masque_mode_(masque_mode),
       event_loop_(event_loop),
       masque_server_backend_(masque_server_backend) {}
diff --git a/quiche/quic/masque/masque_dispatcher.h b/quiche/quic/masque/masque_dispatcher.h
index 804d2e9..8d5a07b 100644
--- a/quiche/quic/masque/masque_dispatcher.h
+++ b/quiche/quic/masque/masque_dispatcher.h
@@ -27,7 +27,8 @@
       std::unique_ptr<QuicCryptoServerStreamBase::Helper> session_helper,
       std::unique_ptr<QuicAlarmFactory> alarm_factory,
       MasqueServerBackend* masque_server_backend,
-      uint8_t expected_server_connection_id_length);
+      uint8_t expected_server_connection_id_length,
+      ConnectionIdGeneratorInterface& generator);
 
   // Disallow copy and assign.
   MasqueDispatcher(const MasqueDispatcher&) = delete;
diff --git a/quiche/quic/masque/masque_epoll_server.cc b/quiche/quic/masque/masque_epoll_server.cc
index a67c507..80d9d2e 100644
--- a/quiche/quic/masque/masque_epoll_server.cc
+++ b/quiche/quic/masque/masque_epoll_server.cc
@@ -25,7 +25,7 @@
       event_loop(), std::make_unique<QuicDefaultConnectionHelper>(),
       std::make_unique<QuicSimpleCryptoServerStreamHelper>(),
       event_loop()->CreateAlarmFactory(), masque_server_backend_,
-      expected_server_connection_id_length());
+      expected_server_connection_id_length(), connection_id_generator());
 }
 
 }  // namespace quic
diff --git a/quiche/quic/qbone/qbone_client_test.cc b/quiche/quic/qbone/qbone_client_test.cc
index 7d54852..cb9541b 100644
--- a/quiche/quic/qbone/qbone_client_test.cc
+++ b/quiche/quic/qbone/qbone_client_test.cc
@@ -104,11 +104,11 @@
       std::unique_ptr<QuicConnectionHelperInterface> helper,
       std::unique_ptr<QuicCryptoServerStreamBase::Helper> session_helper,
       std::unique_ptr<QuicAlarmFactory> alarm_factory,
-      QbonePacketWriter* writer)
+      QbonePacketWriter* writer, ConnectionIdGeneratorInterface& generator)
       : QuicDispatcher(config, crypto_config, version_manager,
                        std::move(helper), std::move(session_helper),
-                       std::move(alarm_factory),
-                       kQuicDefaultConnectionIdLength),
+                       std::move(alarm_factory), kQuicDefaultConnectionIdLength,
+                       generator),
         writer_(writer) {}
 
   std::unique_ptr<QuicSession> CreateQuicSession(
@@ -143,7 +143,8 @@
         &config(), &crypto_config(), version_manager(),
         std::make_unique<QuicDefaultConnectionHelper>(),
         std::make_unique<QboneCryptoServerStreamHelper>(),
-        event_loop()->CreateAlarmFactory(), &writer_);
+        event_loop()->CreateAlarmFactory(), &writer_,
+        connection_id_generator());
   }
 
   std::vector<std::string> data() { return writer_.data(); }
diff --git a/quiche/quic/test_tools/mock_connection_id_generator.h b/quiche/quic/test_tools/mock_connection_id_generator.h
new file mode 100644
index 0000000..66176f9
--- /dev/null
+++ b/quiche/quic/test_tools/mock_connection_id_generator.h
@@ -0,0 +1,28 @@
+// 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.
+
+#ifndef QUICHE_QUIC_TEST_TOOLS_MOCK_CONNECTION_ID_GENERATOR_H_
+#define QUICHE_QUIC_TEST_TOOLS_MOCK_CONNECTION_ID_GENERATOR_H_
+
+#include "quiche/quic/core/connection_id_generator.h"
+#include "quiche/quic/platform/api/quic_test.h"
+
+namespace quic {
+namespace test {
+
+class MockConnectionIdGenerator : public quic::ConnectionIdGeneratorInterface {
+ public:
+  MOCK_METHOD(absl::optional<quic::QuicConnectionId>, GenerateNextConnectionId,
+              (const quic::QuicConnectionId& original), (override));
+
+  MOCK_METHOD(absl::optional<quic::QuicConnectionId>, MaybeReplaceConnectionId,
+              (const quic::QuicConnectionId& original,
+               const quic::ParsedQuicVersion& version),
+              (override));
+};
+
+}  // namespace test
+}  // namespace quic
+
+#endif  // QUICHE_QUIC_TEST_TOOLS_MOCK_CONNECTION_ID_GENERATOR_H_
diff --git a/quiche/quic/test_tools/mock_quic_dispatcher.cc b/quiche/quic/test_tools/mock_quic_dispatcher.cc
index fd91281..527047e 100644
--- a/quiche/quic/test_tools/mock_quic_dispatcher.cc
+++ b/quiche/quic/test_tools/mock_quic_dispatcher.cc
@@ -15,11 +15,12 @@
     std::unique_ptr<QuicConnectionHelperInterface> helper,
     std::unique_ptr<QuicCryptoServerStreamBase::Helper> session_helper,
     std::unique_ptr<QuicAlarmFactory> alarm_factory,
-    QuicSimpleServerBackend* quic_simple_server_backend)
+    QuicSimpleServerBackend* quic_simple_server_backend,
+    ConnectionIdGeneratorInterface& generator)
     : QuicSimpleDispatcher(config, crypto_config, version_manager,
                            std::move(helper), std::move(session_helper),
                            std::move(alarm_factory), quic_simple_server_backend,
-                           kQuicDefaultConnectionIdLength) {}
+                           kQuicDefaultConnectionIdLength, generator) {}
 
 MockQuicDispatcher::~MockQuicDispatcher() {}
 
diff --git a/quiche/quic/test_tools/mock_quic_dispatcher.h b/quiche/quic/test_tools/mock_quic_dispatcher.h
index 4e152e7..32b4c85 100644
--- a/quiche/quic/test_tools/mock_quic_dispatcher.h
+++ b/quiche/quic/test_tools/mock_quic_dispatcher.h
@@ -23,7 +23,8 @@
       std::unique_ptr<QuicConnectionHelperInterface> helper,
       std::unique_ptr<QuicCryptoServerStreamBase::Helper> session_helper,
       std::unique_ptr<QuicAlarmFactory> alarm_factory,
-      QuicSimpleServerBackend* quic_simple_server_backend);
+      QuicSimpleServerBackend* quic_simple_server_backend,
+      ConnectionIdGeneratorInterface& generator);
   MockQuicDispatcher(const MockQuicDispatcher&) = delete;
   MockQuicDispatcher& operator=(const MockQuicDispatcher&) = delete;
 
diff --git a/quiche/quic/test_tools/quic_test_server.cc b/quiche/quic/test_tools/quic_test_server.cc
index b8499ff..8c270bb 100644
--- a/quiche/quic/test_tools/quic_test_server.cc
+++ b/quiche/quic/test_tools/quic_test_server.cc
@@ -73,11 +73,13 @@
       std::unique_ptr<QuicCryptoServerStreamBase::Helper> session_helper,
       std::unique_ptr<QuicAlarmFactory> alarm_factory,
       QuicSimpleServerBackend* quic_simple_server_backend,
-      uint8_t expected_server_connection_id_length)
-      : QuicSimpleDispatcher(
-            config, crypto_config, version_manager, std::move(helper),
-            std::move(session_helper), std::move(alarm_factory),
-            quic_simple_server_backend, expected_server_connection_id_length),
+      uint8_t expected_server_connection_id_length,
+      ConnectionIdGeneratorInterface& generator)
+      : QuicSimpleDispatcher(config, crypto_config, version_manager,
+                             std::move(helper), std::move(session_helper),
+                             std::move(alarm_factory),
+                             quic_simple_server_backend,
+                             expected_server_connection_id_length, generator),
         session_factory_(nullptr),
         stream_factory_(nullptr),
         crypto_stream_factory_(nullptr) {}
@@ -182,7 +184,7 @@
       std::unique_ptr<QuicCryptoServerStreamBase::Helper>(
           new QuicSimpleCryptoServerStreamHelper()),
       event_loop()->CreateAlarmFactory(), server_backend(),
-      expected_server_connection_id_length());
+      expected_server_connection_id_length(), connection_id_generator());
 }
 
 void QuicTestServer::SetSessionFactory(SessionFactory* factory) {
diff --git a/quiche/quic/tools/quic_server.cc b/quiche/quic/tools/quic_server.cc
index 0c3233a..b318cfd 100644
--- a/quiche/quic/tools/quic_server.cc
+++ b/quiche/quic/tools/quic_server.cc
@@ -76,7 +76,8 @@
       packet_reader_(new QuicPacketReader()),
       quic_simple_server_backend_(quic_simple_server_backend),
       expected_server_connection_id_length_(
-          expected_server_connection_id_length) {
+          expected_server_connection_id_length),
+      connection_id_generator_(expected_server_connection_id_length) {
   QUICHE_DCHECK(quic_simple_server_backend_);
   Initialize();
 }
@@ -170,7 +171,7 @@
       std::unique_ptr<QuicCryptoServerStreamBase::Helper>(
           new QuicSimpleCryptoServerStreamHelper()),
       event_loop_->CreateAlarmFactory(), quic_simple_server_backend_,
-      expected_server_connection_id_length_);
+      expected_server_connection_id_length_, connection_id_generator_);
 }
 
 std::unique_ptr<QuicEventLoop> QuicServer::CreateEventLoop() {
diff --git a/quiche/quic/tools/quic_server.h b/quiche/quic/tools/quic_server.h
index 0e48371..cf71ac6 100644
--- a/quiche/quic/tools/quic_server.h
+++ b/quiche/quic/tools/quic_server.h
@@ -15,6 +15,7 @@
 
 #include "absl/strings/string_view.h"
 #include "quiche/quic/core/crypto/quic_crypto_server_config.h"
+#include "quiche/quic/core/deterministic_connection_id_generator.h"
 #include "quiche/quic/core/io/quic_event_loop.h"
 #include "quiche/quic/core/io/socket_factory.h"
 #include "quiche/quic/core/quic_config.h"
@@ -108,6 +109,10 @@
     return expected_server_connection_id_length_;
   }
 
+  ConnectionIdGeneratorInterface& connection_id_generator() {
+    return connection_id_generator_;
+  }
+
  private:
   friend class quic::test::QuicServerPeer;
 
@@ -160,6 +165,8 @@
 
   // Connection ID length expected to be read on incoming IETF short headers.
   uint8_t expected_server_connection_id_length_;
+
+  DeterministicConnectionIdGenerator connection_id_generator_;
 };
 
 }  // namespace quic
diff --git a/quiche/quic/tools/quic_server_test.cc b/quiche/quic/tools/quic_server_test.cc
index fe68ba5..26075a1 100644
--- a/quiche/quic/tools/quic_server_test.cc
+++ b/quiche/quic/tools/quic_server_test.cc
@@ -8,6 +8,7 @@
 
 #include "absl/base/macros.h"
 #include "quiche/quic/core/crypto/quic_random.h"
+#include "quiche/quic/core/deterministic_connection_id_generator.h"
 #include "quiche/quic/core/io/quic_default_event_loop.h"
 #include "quiche/quic/core/io/quic_event_loop.h"
 #include "quiche/quic/core/quic_default_clock.h"
@@ -40,11 +41,13 @@
       std::unique_ptr<QuicConnectionHelperInterface> helper,
       std::unique_ptr<QuicCryptoServerStreamBase::Helper> session_helper,
       std::unique_ptr<QuicAlarmFactory> alarm_factory,
-      QuicSimpleServerBackend* quic_simple_server_backend)
-      : QuicSimpleDispatcher(
-            config, crypto_config, version_manager, std::move(helper),
-            std::move(session_helper), std::move(alarm_factory),
-            quic_simple_server_backend, kQuicDefaultConnectionIdLength) {}
+      QuicSimpleServerBackend* quic_simple_server_backend,
+      ConnectionIdGeneratorInterface& generator)
+      : QuicSimpleDispatcher(config, crypto_config, version_manager,
+                             std::move(helper), std::move(session_helper),
+                             std::move(alarm_factory),
+                             quic_simple_server_backend,
+                             kQuicDefaultConnectionIdLength, generator) {}
   ~MockQuicSimpleDispatcher() override = default;
 
   MOCK_METHOD(void, OnCanWrite, (), (override));
@@ -73,7 +76,8 @@
         std::make_unique<QuicDefaultConnectionHelper>(),
         std::unique_ptr<QuicCryptoServerStreamBase::Helper>(
             new QuicSimpleCryptoServerStreamHelper()),
-        event_loop()->CreateAlarmFactory(), quic_simple_server_backend_);
+        event_loop()->CreateAlarmFactory(), quic_simple_server_backend_,
+        connection_id_generator());
     return mock_dispatcher_;
   }
 
@@ -169,11 +173,12 @@
                        KeyExchangeSource::Default()),
         version_manager_(AllSupportedVersions()),
         event_loop_(GetDefaultEventLoop()->Create(QuicDefaultClock::Get())),
+        connection_id_generator_(kQuicDefaultConnectionIdLength),
         dispatcher_(&config_, &crypto_config_, &version_manager_,
                     std::make_unique<QuicDefaultConnectionHelper>(),
                     std::make_unique<QuicSimpleCryptoServerStreamHelper>(),
                     event_loop_->CreateAlarmFactory(),
-                    &quic_simple_server_backend_) {
+                    &quic_simple_server_backend_, connection_id_generator_) {
     dispatcher_.InitializeWithWriter(new QuicDefaultPacketWriter(1234));
   }
 
@@ -188,6 +193,7 @@
   QuicVersionManager version_manager_;
   std::unique_ptr<QuicEventLoop> event_loop_;
   QuicMemoryCacheBackend quic_simple_server_backend_;
+  DeterministicConnectionIdGenerator connection_id_generator_;
   MockQuicDispatcher dispatcher_;
 };
 
diff --git a/quiche/quic/tools/quic_simple_dispatcher.cc b/quiche/quic/tools/quic_simple_dispatcher.cc
index 247e6f7..5fb270c 100644
--- a/quiche/quic/tools/quic_simple_dispatcher.cc
+++ b/quiche/quic/tools/quic_simple_dispatcher.cc
@@ -16,10 +16,11 @@
     std::unique_ptr<QuicCryptoServerStreamBase::Helper> session_helper,
     std::unique_ptr<QuicAlarmFactory> alarm_factory,
     QuicSimpleServerBackend* quic_simple_server_backend,
-    uint8_t expected_server_connection_id_length)
+    uint8_t expected_server_connection_id_length,
+    ConnectionIdGeneratorInterface& generator)
     : QuicDispatcher(config, crypto_config, version_manager, std::move(helper),
                      std::move(session_helper), std::move(alarm_factory),
-                     expected_server_connection_id_length),
+                     expected_server_connection_id_length, generator),
       quic_simple_server_backend_(quic_simple_server_backend) {}
 
 QuicSimpleDispatcher::~QuicSimpleDispatcher() = default;
diff --git a/quiche/quic/tools/quic_simple_dispatcher.h b/quiche/quic/tools/quic_simple_dispatcher.h
index 609e210..16f7fd0 100644
--- a/quiche/quic/tools/quic_simple_dispatcher.h
+++ b/quiche/quic/tools/quic_simple_dispatcher.h
@@ -21,7 +21,8 @@
       std::unique_ptr<QuicCryptoServerStreamBase::Helper> session_helper,
       std::unique_ptr<QuicAlarmFactory> alarm_factory,
       QuicSimpleServerBackend* quic_simple_server_backend,
-      uint8_t expected_server_connection_id_length);
+      uint8_t expected_server_connection_id_length,
+      ConnectionIdGeneratorInterface& generator);
 
   ~QuicSimpleDispatcher() override;