Group some client hello information into ParsedClientHello, a new struct that can be passed around easily.

PiperOrigin-RevId: 404857674
diff --git a/quic/core/quic_dispatcher.cc b/quic/core/quic_dispatcher.cc
index ad17281..02a0c8f 100644
--- a/quic/core/quic_dispatcher.cc
+++ b/quic/core/quic_dispatcher.cc
@@ -719,27 +719,27 @@
   QuicPacketFate fate = ValidityChecks(*packet_info);
 
   if (fate == kFateProcess) {
-    std::string sni, uaid, legacy_version_encapsulation_inner_packet;
-    std::vector<std::string> alpns;
-    if (!TryExtractChloOrBufferEarlyPacket(
-            *packet_info, &sni, &uaid, &alpns,
-            &legacy_version_encapsulation_inner_packet)) {
+    absl::optional<ParsedClientHello> parsed_chlo =
+        TryExtractChloOrBufferEarlyPacket(*packet_info);
+    if (!parsed_chlo.has_value()) {
       // Client Hello incomplete. Packet has been buffered or (rarely) dropped.
       return;
     }
 
     // Client Hello fully received.
-    fate = ValidityChecksOnFullChlo(*packet_info, sni, uaid, alpns);
+    fate = ValidityChecksOnFullChlo(*packet_info, *parsed_chlo);
 
     if (fate == kFateProcess) {
-      QUICHE_DCHECK(legacy_version_encapsulation_inner_packet.empty() ||
-                    !packet_info->version.UsesTls());
+      QUICHE_DCHECK(
+          parsed_chlo->legacy_version_encapsulation_inner_packet.empty() ||
+          !packet_info->version.UsesTls());
       if (MaybeHandleLegacyVersionEncapsulation(
-              this, legacy_version_encapsulation_inner_packet, *packet_info)) {
+              this, parsed_chlo->legacy_version_encapsulation_inner_packet,
+              *packet_info)) {
         return;
       }
 
-      ProcessChlo(alpns, sni, packet_info);
+      ProcessChlo(*parsed_chlo, packet_info);
       return;
     }
   }
@@ -775,26 +775,20 @@
   }
 }
 
-bool QuicDispatcher::TryExtractChloOrBufferEarlyPacket(
-    const ReceivedPacketInfo& packet_info,
-    std::string* sni,
-    std::string* uaid,
-    std::vector<std::string>* alpns,
-    std::string* legacy_version_encapsulation_inner_packet) {
-  sni->clear();
-  uaid->clear();
-  alpns->clear();
-  legacy_version_encapsulation_inner_packet->clear();
-
+absl::optional<QuicDispatcher::ParsedClientHello>
+QuicDispatcher::TryExtractChloOrBufferEarlyPacket(
+    const ReceivedPacketInfo& packet_info) {
   if (packet_info.version.UsesTls()) {
     bool has_full_tls_chlo = false;
+    std::string sni;
+    std::vector<std::string> alpns;
     if (buffered_packets_.HasBufferedPackets(
             packet_info.destination_connection_id)) {
       // If we already have buffered packets for this connection ID,
       // use the associated TlsChloExtractor to parse this packet.
       has_full_tls_chlo = buffered_packets_.IngestPacketForTlsChloExtraction(
           packet_info.destination_connection_id, packet_info.version,
-          packet_info.packet, alpns, sni);
+          packet_info.packet, &alpns, &sni);
     } else {
       // If we do not have a BufferedPacketList for this connection ID,
       // create a single-use one to check whether this packet contains a
@@ -804,8 +798,8 @@
       if (tls_chlo_extractor.HasParsedFullChlo()) {
         // This packet contains a full single-packet CHLO.
         has_full_tls_chlo = true;
-        *alpns = tls_chlo_extractor.alpns();
-        *sni = tls_chlo_extractor.server_name();
+        alpns = tls_chlo_extractor.alpns();
+        sni = tls_chlo_extractor.server_name();
       }
     }
     if (!has_full_tls_chlo) {
@@ -813,9 +807,13 @@
       // packet that arrived before the CHLO (due to loss or reordering),
       // or it could be a fragment of a multi-packet CHLO.
       BufferEarlyPacket(packet_info);
+      return absl::nullopt;
     }
 
-    return has_full_tls_chlo;
+    ParsedClientHello parsed_chlo;
+    parsed_chlo.sni = std::move(sni);
+    parsed_chlo.alpns = std::move(alpns);
+    return parsed_chlo;
   }
 
   ChloAlpnSniExtractor alpn_extractor;
@@ -826,7 +824,7 @@
                               packet_info.destination_connection_id.length())) {
     // Buffer non-CHLO packets.
     BufferEarlyPacket(packet_info);
-    return false;
+    return absl::nullopt;
   }
 
   // We only apply this check for versions that do not use the IETF
@@ -839,15 +837,16 @@
     QUIC_DVLOG(1) << "Dropping CHLO packet which is too short, length: "
                   << packet_info.packet.length();
     QUIC_CODE_COUNT(quic_drop_small_chlo_packets);
-    return false;
+    return absl::nullopt;
   }
 
-  *legacy_version_encapsulation_inner_packet =
+  ParsedClientHello parsed_chlo;
+  parsed_chlo.legacy_version_encapsulation_inner_packet =
       alpn_extractor.ConsumeLegacyVersionEncapsulationInnerPacket();
-  *sni = alpn_extractor.ConsumeSni();
-  *uaid = alpn_extractor.ConsumeUaid();
-  *alpns = {alpn_extractor.ConsumeAlpn()};
-  return true;
+  parsed_chlo.sni = alpn_extractor.ConsumeSni();
+  parsed_chlo.uaid = alpn_extractor.ConsumeUaid();
+  parsed_chlo.alpns = {alpn_extractor.ConsumeAlpn()};
+  return parsed_chlo;
 }
 
 std::string QuicDispatcher::SelectAlpn(const std::vector<std::string>& alpns) {
@@ -1312,8 +1311,7 @@
   }
 }
 
-void QuicDispatcher::ProcessChlo(const std::vector<std::string>& alpns,
-                                 absl::string_view sni,
+void QuicDispatcher::ProcessChlo(const ParsedClientHello& parsed_chlo,
                                  ReceivedPacketInfo* packet_info) {
   if (!buffered_packets_.HasBufferedPackets(
           packet_info->destination_connection_id) &&
@@ -1329,7 +1327,8 @@
         packet_info->destination_connection_id,
         packet_info->form != GOOGLE_QUIC_PACKET, packet_info->packet,
         packet_info->self_address, packet_info->peer_address,
-        /*is_chlo=*/true, alpns, sni, packet_info->version);
+        /*is_chlo=*/true, parsed_chlo.alpns, parsed_chlo.sni,
+        packet_info->version);
     if (rs != EnqueuePacketResult::SUCCESS) {
       OnBufferPacketFailure(rs, packet_info->destination_connection_id);
     }
@@ -1341,10 +1340,10 @@
   packet_info->destination_connection_id = MaybeReplaceServerConnectionId(
       original_connection_id, packet_info->version);
   // Creates a new session and process all buffered packets for this connection.
-  std::string alpn = SelectAlpn(alpns);
+  std::string alpn = SelectAlpn(parsed_chlo.alpns);
   std::unique_ptr<QuicSession> session = CreateQuicSession(
       packet_info->destination_connection_id, packet_info->self_address,
-      packet_info->peer_address, alpn, packet_info->version, sni);
+      packet_info->peer_address, alpn, packet_info->version, parsed_chlo.sni);
   if (QUIC_PREDICT_FALSE(session == nullptr)) {
     QUIC_BUG(quic_bug_10287_8)
         << "CreateQuicSession returned nullptr for "
diff --git a/quic/core/quic_dispatcher.h b/quic/core/quic_dispatcher.h
index 0073666..1c4e53b 100644
--- a/quic/core/quic_dispatcher.h
+++ b/quic/core/quic_dispatcher.h
@@ -169,6 +169,15 @@
   }
 
  protected:
+  // ParsedClientHello contains client hello information extracted from a fully
+  // received client hello.
+  struct QUIC_NO_EXPORT ParsedClientHello {
+    std::string sni;                 // QUIC crypto and TLS.
+    std::string uaid;                // QUIC crypto only.
+    std::vector<std::string> alpns;  // QUIC crypto and TLS.
+    std::string legacy_version_encapsulation_inner_packet;  // QUIC crypto only.
+  };
+
   virtual std::unique_ptr<QuicSession> CreateQuicSession(
       QuicConnectionId server_connection_id,
       const QuicSocketAddress& self_address,
@@ -232,9 +241,7 @@
   // Only called if ValidityChecks returns kFateProcess.
   virtual QuicPacketFate ValidityChecksOnFullChlo(
       const ReceivedPacketInfo& /*packet_info*/,
-      const std::string& /*sni*/,
-      const std::string& /*uaid*/,
-      const std::vector<std::string>& /*alpns*/) const {
+      const ParsedClientHello& /*parsed_chlo*/) const {
     return kFateProcess;
   }
 
@@ -245,10 +252,10 @@
   // Buffers packet until it can be delivered to a connection.
   void BufferEarlyPacket(const ReceivedPacketInfo& packet_info);
 
-  // Called when |packet_info| is a CHLO packet. Creates a new connection and
-  // delivers any buffered packets for that connection id.
-  void ProcessChlo(const std::vector<std::string>& alpns,
-                   absl::string_view sni,
+  // Called when |packet_info| is the last received packet of the client hello.
+  // |parsed_chlo| is the parsed version of the client hello. Creates a new
+  // connection and delivers any buffered packets for that connection id.
+  void ProcessChlo(const ParsedClientHello& parsed_chlo,
                    ReceivedPacketInfo* packet_info);
 
   // Return true if dispatcher wants to destroy session outside of
@@ -387,17 +394,13 @@
   // Try to extract information(sni, alpns, ...) if the full Client Hello has
   // been parsed.
   //
-  // If the full Client Hello has been parsed, return true and set |sni|,
-  // |alpns| and |legacy_version_encapsulation_inner_packet|. |uaid| will be
-  // populated for QUIC_CRYPTO only.
+  // Return the parsed client hello if the full Client Hello has been
+  // successfully parsed.
   //
-  // Otherwise return false and either buffer or (rarely) drop the packet.
-  bool TryExtractChloOrBufferEarlyPacket(
-      const ReceivedPacketInfo& packet_info,
-      std::string* sni,
-      std::string* uaid,
-      std::vector<std::string>* alpns,
-      std::string* legacy_version_encapsulation_inner_packet);
+  // Otherwise return absl::nullopt and either buffer or (rarely) drop the
+  // packet.
+  absl::optional<ParsedClientHello> TryExtractChloOrBufferEarlyPacket(
+      const ReceivedPacketInfo& packet_info);
 
   // Deliver |packets| to |session| for further processing.
   void DeliverPacketsToSession(