Key Connect(Udp) tunnels by (connection_id, stream_id)

Keying by stream_id alone is not sufficient if multiple connections occur
simultaneously, such as from Chromium.

This change only affects QUIC testing binaries.

PiperOrigin-RevId: 578628865
diff --git a/quiche/quic/core/quic_connection_id.h b/quiche/quic/core/quic_connection_id.h
index 2e6e035..6bf5cc4 100644
--- a/quiche/quic/core/quic_connection_id.h
+++ b/quiche/quic/core/quic_connection_id.h
@@ -81,6 +81,12 @@
   // a hash over the network.
   size_t Hash() const;
 
+  // Allow absl::Hash to hash std::pair<QuicConnectionId, H>.
+  template <typename H>
+  friend H AbslHashValue(H h, const QuicConnectionId& c) {
+    return H::combine(std::move(h), c.Hash());
+  }
+
   // Generates an ASCII string that represents
   // the contents of the connection ID, or "0" if it is empty.
   std::string ToString() const;
diff --git a/quiche/quic/tools/connect_server_backend.cc b/quiche/quic/tools/connect_server_backend.cc
index 6de2917..ba17bea 100644
--- a/quiche/quic/tools/connect_server_backend.cc
+++ b/quiche/quic/tools/connect_server_backend.cc
@@ -93,7 +93,8 @@
   if (!request_headers.contains(":protocol")) {
     // normal CONNECT
     auto [tunnel_it, inserted] = connect_tunnels_.emplace(
-        request_handler->stream_id(),
+        std::make_pair(request_handler->connection_id(),
+                       request_handler->stream_id()),
         std::make_unique<ConnectTunnel>(request_handler, socket_factory_,
                                         acceptable_connect_destinations_));
     QUICHE_DCHECK(inserted);
@@ -102,7 +103,8 @@
   } else if (request_headers.find(":protocol")->second == "connect-udp") {
     // CONNECT-UDP
     auto [tunnel_it, inserted] = connect_udp_tunnels_.emplace(
-        request_handler->stream_id(),
+        std::make_pair(request_handler->connection_id(),
+                       request_handler->stream_id()),
         std::make_unique<ConnectUdpTunnel>(request_handler, socket_factory_,
                                            server_label_,
                                            acceptable_connect_udp_targets_));
@@ -122,9 +124,11 @@
   // Expect ConnectUdpTunnels to register a datagram visitor, causing the
   // stream to process data as capsules.  HandleConnectData() should therefore
   // never be called for streams with a ConnectUdpTunnel.
-  QUICHE_DCHECK(!connect_udp_tunnels_.contains(request_handler->stream_id()));
+  QUICHE_DCHECK(!connect_udp_tunnels_.contains(std::make_pair(
+      request_handler->connection_id(), request_handler->stream_id())));
 
-  auto tunnel_it = connect_tunnels_.find(request_handler->stream_id());
+  auto tunnel_it = connect_tunnels_.find(std::make_pair(
+      request_handler->connection_id(), request_handler->stream_id()));
   if (tunnel_it == connect_tunnels_.end()) {
     // If tunnel not found, perhaps it's something being handled for
     // non-CONNECT. Possible because this method could be called for anything
@@ -146,13 +150,15 @@
 
 void ConnectServerBackend::CloseBackendResponseStream(
     QuicSimpleServerBackend::RequestHandler* request_handler) {
-  auto tunnel_it = connect_tunnels_.find(request_handler->stream_id());
+  auto tunnel_it = connect_tunnels_.find(std::make_pair(
+      request_handler->connection_id(), request_handler->stream_id()));
   if (tunnel_it != connect_tunnels_.end()) {
     tunnel_it->second->OnClientStreamClose();
     connect_tunnels_.erase(tunnel_it);
   }
 
-  auto udp_tunnel_it = connect_udp_tunnels_.find(request_handler->stream_id());
+  auto udp_tunnel_it = connect_udp_tunnels_.find(std::pair(
+      request_handler->connection_id(), request_handler->stream_id()));
   if (udp_tunnel_it != connect_udp_tunnels_.end()) {
     udp_tunnel_it->second->OnClientStreamClose();
     connect_udp_tunnels_.erase(udp_tunnel_it);
diff --git a/quiche/quic/tools/connect_server_backend.h b/quiche/quic/tools/connect_server_backend.h
index f4d848c..4aa8967 100644
--- a/quiche/quic/tools/connect_server_backend.h
+++ b/quiche/quic/tools/connect_server_backend.h
@@ -59,9 +59,11 @@
   const std::string server_label_;
 
   SocketFactory* socket_factory_ = nullptr;  // unowned
-  absl::flat_hash_map<QuicStreamId, std::unique_ptr<ConnectTunnel>>
+  absl::flat_hash_map<std::pair<QuicConnectionId, QuicStreamId>,
+                      std::unique_ptr<ConnectTunnel>>
       connect_tunnels_;
-  absl::flat_hash_map<QuicStreamId, std::unique_ptr<ConnectUdpTunnel>>
+  absl::flat_hash_map<std::pair<QuicConnectionId, QuicStreamId>,
+                      std::unique_ptr<ConnectUdpTunnel>>
       connect_udp_tunnels_;
 };