Reduce the exposure of session_map_ outside the QuicDispatcher base class.

PiperOrigin-RevId: 348642314
Change-Id: Ie4f6161bf6d5dc2d76ef43ec68edbd6a61001160
diff --git a/quic/core/http/end_to_end_test.cc b/quic/core/http/end_to_end_test.cc
index 2cd4fd0..51e0c99 100644
--- a/quic/core/http/end_to_end_test.cc
+++ b/quic/core/http/end_to_end_test.cc
@@ -347,13 +347,13 @@
       ADD_FAILURE() << "Missing dispatcher";
       return nullptr;
     }
-    if (dispatcher->session_map().empty()) {
+    if (dispatcher->NumSessions() == 0) {
       ADD_FAILURE() << "Empty dispatcher session map";
       return nullptr;
     }
-    EXPECT_EQ(1u, dispatcher->session_map().size());
+    EXPECT_EQ(1u, dispatcher->NumSessions());
     return static_cast<QuicSpdySession*>(
-        dispatcher->session_map().begin()->second.get());
+        QuicDispatcherPeer::GetFirstSessionIfAny(dispatcher));
   }
 
   bool Initialize() {
@@ -3535,11 +3535,9 @@
 
   QuicDispatcher* dispatcher =
       QuicServerPeer::GetDispatcher(server_thread_->server());
-  QuicDispatcher::SessionMap const& map =
-      QuicDispatcherPeer::session_map(dispatcher);
-  auto it = map.begin();
-  EXPECT_TRUE(it != map.end());
-  QuicSession* server_session = it->second.get();
+  QuicSession* server_session =
+      QuicDispatcherPeer::GetFirstSessionIfAny(dispatcher);
+  EXPECT_TRUE(server_session != nullptr);
 
   // The stream is not waiting for the arrival of the peer's final offset.
   EXPECT_EQ(
@@ -4132,7 +4130,7 @@
     server_thread_->Resume();
     return;
   }
-  if (!dispatcher->session_map().empty()) {
+  if (dispatcher->NumSessions() > 0) {
     ADD_FAILURE() << "Dispatcher session map not empty";
     server_thread_->Resume();
     return;
@@ -4173,7 +4171,7 @@
     server_thread_->Resume();
     return;
   }
-  if (!dispatcher->session_map().empty()) {
+  if (dispatcher->NumSessions() > 0) {
     ADD_FAILURE() << "Dispatcher session map not empty";
     server_thread_->Resume();
     return;
@@ -4780,7 +4778,7 @@
     server_thread_->Resume();
     return;
   }
-  if (!dispatcher->session_map().empty()) {
+  if (dispatcher->NumSessions() > 0) {
     ADD_FAILURE() << "Dispatcher session map not empty";
     server_thread_->Resume();
     return;
@@ -4849,7 +4847,7 @@
     server_thread_->Resume();
     return;
   }
-  if (!dispatcher->session_map().empty()) {
+  if (dispatcher->NumSessions() > 0) {
     ADD_FAILURE() << "Dispatcher session map not empty";
     server_thread_->Resume();
     return;
diff --git a/quic/core/quic_dispatcher.cc b/quic/core/quic_dispatcher.cc
index 8439f1e..0b0707a 100644
--- a/quic/core/quic_dispatcher.cc
+++ b/quic/core/quic_dispatcher.cc
@@ -4,6 +4,7 @@
 
 #include "net/third_party/quiche/src/quic/core/quic_dispatcher.h"
 
+#include <memory>
 #include <string>
 #include <utility>
 
@@ -12,6 +13,7 @@
 #include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
 #include "net/third_party/quiche/src/quic/core/crypto/quic_random.h"
 #include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
+#include "net/third_party/quiche/src/quic/core/quic_session.h"
 #include "net/third_party/quiche/src/quic/core/quic_time_wait_list_manager.h"
 #include "net/third_party/quiche/src/quic/core/quic_types.h"
 #include "net/third_party/quiche/src/quic/core/quic_utils.h"
@@ -793,6 +795,13 @@
   buffered_packets_.DiscardAllPackets();
 }
 
+void QuicDispatcher::PerformActionOnActiveSessions(
+    std::function<void(QuicSession*)> operation) const {
+  for (auto const& kv : session_map_) {
+    operation(kv.second.get());
+  }
+}
+
 std::unique_ptr<QuicPerPacketContext> QuicDispatcher::GetPerPacketContext()
     const {
   return nullptr;
diff --git a/quic/core/quic_dispatcher.h b/quic/core/quic_dispatcher.h
index d2711e0..58d7932 100644
--- a/quic/core/quic_dispatcher.h
+++ b/quic/core/quic_dispatcher.h
@@ -8,6 +8,7 @@
 #ifndef QUICHE_QUIC_CORE_QUIC_DISPATCHER_H_
 #define QUICHE_QUIC_CORE_QUIC_DISPATCHER_H_
 
+#include <cstddef>
 #include <memory>
 #include <string>
 #include <vector>
@@ -18,6 +19,7 @@
 #include "net/third_party/quiche/src/quic/core/quic_blocked_writer_interface.h"
 #include "net/third_party/quiche/src/quic/core/quic_buffered_packet_store.h"
 #include "net/third_party/quiche/src/quic/core/quic_connection.h"
+#include "net/third_party/quiche/src/quic/core/quic_connection_id.h"
 #include "net/third_party/quiche/src/quic/core/quic_crypto_server_stream_base.h"
 #include "net/third_party/quiche/src/quic/core/quic_packets.h"
 #include "net/third_party/quiche/src/quic/core/quic_process_packet_interface.h"
@@ -107,6 +109,8 @@
                                  std::unique_ptr<QuicSession>,
                                  QuicConnectionIdHash>;
 
+  size_t NumSessions() const { return session_map_.size(); }
+
   const SessionMap& session_map() const { return session_map_; }
 
   // Deletes all sessions on the closed session list and clears the list.
@@ -133,6 +137,10 @@
   // duck process or because explicitly configured.
   void StopAcceptingNewConnections();
 
+  // Apply an operation for each session.
+  void PerformActionOnActiveSessions(
+      std::function<void(QuicSession*)> operation) const;
+
   bool accept_new_connections() const { return accept_new_connections_; }
 
  protected:
diff --git a/quic/core/quic_dispatcher_test.cc b/quic/core/quic_dispatcher_test.cc
index d65159f..1fb5d7d 100644
--- a/quic/core/quic_dispatcher_test.cc
+++ b/quic/core/quic_dispatcher_test.cc
@@ -557,7 +557,7 @@
   ProcessReceivedPacket(std::move(packets[0]), client_address, version_,
                         server_connection_id);
 
-  EXPECT_EQ(dispatcher_->session_map().size(), 0u)
+  EXPECT_EQ(dispatcher_->NumSessions(), 0u)
       << "No session should be created before the rest of the CHLO arrives.";
 
   // Processing the second packet should create the new session.
@@ -574,7 +574,7 @@
 
   ProcessReceivedPacket(std::move(packets[1]), client_address, version_,
                         server_connection_id);
-  EXPECT_EQ(dispatcher_->session_map().size(), 1u);
+  EXPECT_EQ(dispatcher_->NumSessions(), 1u);
 }
 
 TEST_P(QuicDispatcherTestAllVersions, TlsMultiPacketClientHello) {
@@ -641,7 +641,7 @@
 
   ProcessReceivedPacket(packets[0]->Clone(), client_address, version_,
                         server_connection_id);
-  EXPECT_EQ(dispatcher_->session_map().size(), 1u);
+  EXPECT_EQ(dispatcher_->NumSessions(), 1u);
 
   // Processing the same packet a second time should also be routed by the
   // dispatcher to the right connection (we expect ProcessUdpPacket to be
@@ -2011,7 +2011,7 @@
                                 ReceivedPacketInfoConnectionIdEquals(conn_id)));
   // Process non-CHLO packet.
   ProcessUndecryptableEarlyPacket(conn_id);
-  EXPECT_EQ(0u, dispatcher_->session_map().size())
+  EXPECT_EQ(0u, dispatcher_->NumSessions())
       << "No session should be created before CHLO arrives.";
 
   // When CHLO arrives, a new session should be created, and all packets
@@ -2044,7 +2044,7 @@
   for (size_t i = 1; i <= kDefaultMaxUndecryptablePackets + 1; ++i) {
     ProcessUndecryptableEarlyPacket(conn_id);
   }
-  EXPECT_EQ(0u, dispatcher_->session_map().size())
+  EXPECT_EQ(0u, dispatcher_->NumSessions())
       << "No session should be created before CHLO arrives.";
 
   // Pop out the last packet as it is also be dropped by the store.
diff --git a/quic/qbone/qbone_client_test.cc b/quic/qbone/qbone_client_test.cc
index 98b1a2e..4ed7ed4 100644
--- a/quic/qbone/qbone_client_test.cc
+++ b/quic/qbone/qbone_client_test.cc
@@ -23,6 +23,7 @@
 #include "net/third_party/quiche/src/quic/qbone/qbone_server_session.h"
 #include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h"
 #include "net/third_party/quiche/src/quic/test_tools/quic_connection_peer.h"
+#include "net/third_party/quiche/src/quic/test_tools/quic_dispatcher_peer.h"
 #include "net/third_party/quiche/src/quic/test_tools/quic_server_peer.h"
 #include "net/third_party/quiche/src/quic/test_tools/server_thread.h"
 #include "net/third_party/quiche/src/quic/tools/quic_memory_cache_backend.h"
@@ -261,11 +262,9 @@
   server_thread.Schedule([&server, &long_data]() {
     EXPECT_THAT(server->data()[0], testing::Eq(TestPacketOut("hello")));
     EXPECT_THAT(server->data()[1], testing::Eq(TestPacketOut("world")));
-    auto server_session =
-        static_cast<QboneServerSession*>(QuicServerPeer::GetDispatcher(server)
-                                             ->session_map()
-                                             .begin()
-                                             ->second.get());
+    auto server_session = static_cast<QboneServerSession*>(
+        QuicDispatcherPeer::GetFirstSessionIfAny(
+            QuicServerPeer::GetDispatcher(server)));
     server_session->ProcessPacketFromNetwork(
         TestPacketIn("Somethingsomething"));
     server_session->ProcessPacketFromNetwork(TestPacketIn(long_data));
diff --git a/quic/test_tools/quic_dispatcher_peer.cc b/quic/test_tools/quic_dispatcher_peer.cc
index 467c689..072b801 100644
--- a/quic/test_tools/quic_dispatcher_peer.cc
+++ b/quic/test_tools/quic_dispatcher_peer.cc
@@ -74,12 +74,6 @@
 }
 
 // static
-const QuicDispatcher::SessionMap& QuicDispatcherPeer::session_map(
-    QuicDispatcher* dispatcher) {
-  return dispatcher->session_map();
-}
-
-// static
 void QuicDispatcherPeer::set_new_sessions_allowed_per_event_loop(
     QuicDispatcher* dispatcher,
     size_t num_session_allowed) {
@@ -119,5 +113,14 @@
   return dispatcher->SelectAlpn(alpns);
 }
 
+// static
+QuicSession* QuicDispatcherPeer::GetFirstSessionIfAny(
+    QuicDispatcher* dispatcher) {
+  if (dispatcher->session_map_.empty()) {
+    return nullptr;
+  }
+  return dispatcher->session_map_.begin()->second.get();
+}
+
 }  // namespace test
 }  // namespace quic
diff --git a/quic/test_tools/quic_dispatcher_peer.h b/quic/test_tools/quic_dispatcher_peer.h
index ec22f94..b9a25ad 100644
--- a/quic/test_tools/quic_dispatcher_peer.h
+++ b/quic/test_tools/quic_dispatcher_peer.h
@@ -46,9 +46,6 @@
   static QuicBufferedPacketStore* GetBufferedPackets(
       QuicDispatcher* dispatcher);
 
-  static const QuicDispatcher::SessionMap& session_map(
-      QuicDispatcher* dispatcher);
-
   static void set_new_sessions_allowed_per_event_loop(
       QuicDispatcher* dispatcher,
       size_t num_session_allowed);
@@ -69,6 +66,10 @@
 
   static std::string SelectAlpn(QuicDispatcher* dispatcher,
                                 const std::vector<std::string>& alpns);
+
+  // Get the first session in the session map. Returns nullptr if the map is
+  // empty.
+  static QuicSession* GetFirstSessionIfAny(QuicDispatcher* dispatcher);
 };
 
 }  // namespace test
diff --git a/quic/test_tools/server_thread.cc b/quic/test_tools/server_thread.cc
index 77a23a6..11d567c 100644
--- a/quic/test_tools/server_thread.cc
+++ b/quic/test_tools/server_thread.cc
@@ -7,6 +7,7 @@
 #include "net/third_party/quiche/src/quic/core/quic_dispatcher.h"
 #include "net/third_party/quiche/src/quic/platform/api/quic_containers.h"
 #include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h"
+#include "net/third_party/quiche/src/quic/test_tools/quic_dispatcher_peer.h"
 #include "net/third_party/quiche/src/quic/test_tools/quic_server_peer.h"
 
 namespace quic {
@@ -114,11 +115,11 @@
     return;
   }
   QuicDispatcher* dispatcher = QuicServerPeer::GetDispatcher(server());
-  if (dispatcher->session_map().empty()) {
+  if (dispatcher->NumSessions() == 0) {
     // Wait for a session to be created.
     return;
   }
-  QuicSession* session = dispatcher->session_map().begin()->second.get();
+  QuicSession* session = QuicDispatcherPeer::GetFirstSessionIfAny(dispatcher);
   if (session->OneRttKeysAvailable()) {
     confirmed_.Notify();
   }