Add ReplaceConnectionId to QuicPeerIssuedConnectionId manager to support connection ID replacement via long packet header.

PiperOrigin-RevId: 354348409
Change-Id: I67ce0cdd7345e6dd704fd3f036f3dd7dd41b1088
diff --git a/quic/core/quic_connection_id_manager.cc b/quic/core/quic_connection_id_manager.cc
index c12ecbd..a4166ef 100644
--- a/quic/core/quic_connection_id_manager.cc
+++ b/quic/core/quic_connection_id_manager.cc
@@ -48,6 +48,15 @@
                       });
 }
 
+std::vector<QuicConnectionIdData>::iterator FindConnectionIdData(
+    std::vector<QuicConnectionIdData>* cid_data_vector,
+    const QuicConnectionId& cid) {
+  return std::find_if(cid_data_vector->begin(), cid_data_vector->end(),
+                      [&cid](const QuicConnectionIdData& cid_data) {
+                        return cid == cid_data.connection_id;
+                      });
+}
+
 }  // namespace
 
 QuicPeerIssuedConnectionIdManager::QuicPeerIssuedConnectionIdManager(
@@ -206,6 +215,22 @@
   return result;
 }
 
+void QuicPeerIssuedConnectionIdManager::ReplaceConnectionId(
+    const QuicConnectionId& old_connection_id,
+    const QuicConnectionId& new_connection_id) {
+  auto it1 =
+      FindConnectionIdData(&active_connection_id_data_, old_connection_id);
+  if (it1 != active_connection_id_data_.end()) {
+    it1->connection_id = new_connection_id;
+    return;
+  }
+  auto it2 = FindConnectionIdData(&to_be_retired_connection_id_data_,
+                                  old_connection_id);
+  if (it2 != to_be_retired_connection_id_data_.end()) {
+    it2->connection_id = new_connection_id;
+  }
+}
+
 namespace {
 
 class RetireSelfIssuedConnectionIdAlarmDelegate : public QuicAlarm::Delegate {
diff --git a/quic/core/quic_connection_id_manager.h b/quic/core/quic_connection_id_manager.h
index bb31da9..493a78e 100644
--- a/quic/core/quic_connection_id_manager.h
+++ b/quic/core/quic_connection_id_manager.h
@@ -77,6 +77,11 @@
   // it is safe to retires these Ids.
   std::vector<uint64_t> ConsumeToBeRetiredConnectionIdSequenceNumbers();
 
+  // If old_connection_id is still tracked by QuicPeerIssuedConnectionIdManager,
+  // replace it with new_connection_id. Otherwise, this is a no-op.
+  void ReplaceConnectionId(const QuicConnectionId& old_connection_id,
+                           const QuicConnectionId& new_connection_id);
+
  private:
   friend class QuicConnectionIdManagerPeer;
 
diff --git a/quic/core/quic_connection_id_manager_test.cc b/quic/core/quic_connection_id_manager_test.cc
index fe87f05..b9ca45f 100644
--- a/quic/core/quic_connection_id_manager_test.cc
+++ b/quic/core/quic_connection_id_manager_test.cc
@@ -517,6 +517,17 @@
       IsError(IETF_QUIC_PROTOCOL_VIOLATION));
 }
 
+TEST_F(QuicPeerIssuedConnectionIdManagerTest, ReplaceConnectionId) {
+  ASSERT_TRUE(
+      peer_issued_cid_manager_.IsConnectionIdActive(initial_connection_id_));
+  peer_issued_cid_manager_.ReplaceConnectionId(initial_connection_id_,
+                                               TestConnectionId(1));
+  EXPECT_FALSE(
+      peer_issued_cid_manager_.IsConnectionIdActive(initial_connection_id_));
+  EXPECT_TRUE(
+      peer_issued_cid_manager_.IsConnectionIdActive(TestConnectionId(1)));
+}
+
 class TestSelfIssuedConnectionIdManagerVisitor
     : public QuicConnectionIdManagerVisitorInterface {
  public: