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(