Pass ParsedClientHello to QuicDispatcher::CreateQuicSession. This makes it easier to pass CHLO information into CreateQuicSession, which is responsible for creating a QUIC session. The information I'd like to add into ParsedClientHello, in a follow up CL, are - Whether TLS resumption is attempted - Whether Early Data is attempted - The address token from the last packet of a CHLO, which will contain CachedNetworkParameters after cl/405481550. PiperOrigin-RevId: 406887508
diff --git a/quic/core/quic_buffered_packet_store.cc b/quic/core/quic_buffered_packet_store.cc index f235e45..291434f 100644 --- a/quic/core/quic_buffered_packet_store.cc +++ b/quic/core/quic_buffered_packet_store.cc
@@ -83,22 +83,16 @@ } EnqueuePacketResult QuicBufferedPacketStore::EnqueuePacket( - QuicConnectionId connection_id, - bool ietf_quic, - const QuicReceivedPacket& packet, - QuicSocketAddress self_address, - QuicSocketAddress peer_address, - bool is_chlo, - const std::vector<std::string>& alpns, - const absl::string_view sni, - const ParsedQuicVersion& version) { + QuicConnectionId connection_id, bool ietf_quic, + const QuicReceivedPacket& packet, QuicSocketAddress self_address, + QuicSocketAddress peer_address, const ParsedQuicVersion& version, + absl::optional<ParsedClientHello> parsed_chlo) { + const bool is_chlo = parsed_chlo.has_value(); QUIC_BUG_IF(quic_bug_12410_1, !GetQuicFlag(FLAGS_quic_allow_chlo_buffering)) << "Shouldn't buffer packets if disabled via flag."; QUIC_BUG_IF(quic_bug_12410_2, is_chlo && connections_with_chlo_.contains(connection_id)) << "Shouldn't buffer duplicated CHLO on connection " << connection_id; - QUIC_BUG_IF(quic_bug_12410_3, !is_chlo && !alpns.empty()) - << "Shouldn't have an ALPN defined for a non-CHLO packet."; QUIC_BUG_IF(quic_bug_12410_4, is_chlo && !version.IsKnown()) << "Should have version for CHLO packet."; @@ -143,8 +137,7 @@ // Add CHLO to the beginning of buffered packets so that it can be delivered // first later. queue.buffered_packets.push_front(std::move(new_entry)); - queue.alpns = alpns; - queue.sni = std::string(sni); + queue.parsed_chlo = std::move(parsed_chlo); connections_with_chlo_[connection_id] = false; // Dummy value. // Set the version of buffered packets of this connection on CHLO. queue.version = version; @@ -248,8 +241,11 @@ connections_with_chlo_.pop_front(); BufferedPacketList packets = DeliverPackets(*connection_id); - QUICHE_DCHECK(!packets.buffered_packets.empty()) - << "Try to deliver connectons without CHLO"; + QUICHE_DCHECK(!packets.buffered_packets.empty() && + packets.parsed_chlo.has_value()) + << "Try to deliver connectons without CHLO. # packets:" + << packets.buffered_packets.size() + << ", has_parsed_chlo:" << packets.parsed_chlo.has_value(); return packets; }
diff --git a/quic/core/quic_buffered_packet_store.h b/quic/core/quic_buffered_packet_store.h index 5ba0a25..b363802 100644 --- a/quic/core/quic_buffered_packet_store.h +++ b/quic/core/quic_buffered_packet_store.h
@@ -67,9 +67,8 @@ std::list<BufferedPacket> buffered_packets; QuicTime creation_time; - // The ALPNs from the CHLO, if found. - std::vector<std::string> alpns; - std::string sni; + // |parsed_chlo| is set iff the entire CHLO has been received. + absl::optional<ParsedClientHello> parsed_chlo; // Indicating whether this is an IETF QUIC connection. bool ietf_quic; // If buffered_packets contains the CHLO, it is the version of the CHLO. @@ -101,18 +100,14 @@ QuicBufferedPacketStore& operator=(const QuicBufferedPacketStore&) = delete; - // Adds a copy of packet into packet queue for given connection. - // TODO(danzh): Consider to split this method to EnqueueChlo() and - // EnqueueDataPacket(). - EnqueuePacketResult EnqueuePacket(QuicConnectionId connection_id, - bool ietf_quic, - const QuicReceivedPacket& packet, - QuicSocketAddress self_address, - QuicSocketAddress peer_address, - bool is_chlo, - const std::vector<std::string>& alpns, - const absl::string_view sni, - const ParsedQuicVersion& version); + // Adds a copy of packet into the packet queue for given connection. If the + // packet is the last one of the CHLO, |parsed_chlo| will contain a parsed + // version of the CHLO. + EnqueuePacketResult EnqueuePacket( + QuicConnectionId connection_id, bool ietf_quic, + const QuicReceivedPacket& packet, QuicSocketAddress self_address, + QuicSocketAddress peer_address, const ParsedQuicVersion& version, + absl::optional<ParsedClientHello> parsed_chlo); // Returns true if there are any packets buffered for |connection_id|. bool HasBufferedPackets(QuicConnectionId connection_id) const;
diff --git a/quic/core/quic_buffered_packet_store_test.cc b/quic/core/quic_buffered_packet_store_test.cc index c5d11f2..7e51751 100644 --- a/quic/core/quic_buffered_packet_store_test.cc +++ b/quic/core/quic_buffered_packet_store_test.cc
@@ -22,6 +22,10 @@ namespace test { namespace { +const absl::optional<ParsedClientHello> kNoParsedChlo; +const absl::optional<ParsedClientHello> kDefaultParsedChlo = + absl::make_optional<ParsedClientHello>(); + using BufferedPacket = QuicBufferedPacketStore::BufferedPacket; using BufferedPacketList = QuicBufferedPacketStore::BufferedPacketList; using EnqueuePacketResult = QuicBufferedPacketStore::EnqueuePacketResult; @@ -70,13 +74,12 @@ TEST_F(QuicBufferedPacketStoreTest, SimpleEnqueueAndDeliverPacket) { QuicConnectionId connection_id = TestConnectionId(1); store_.EnqueuePacket(connection_id, false, packet_, self_address_, - peer_address_, false, {}, "", invalid_version_); + peer_address_, invalid_version_, kNoParsedChlo); EXPECT_TRUE(store_.HasBufferedPackets(connection_id)); auto packets = store_.DeliverPackets(connection_id); const std::list<BufferedPacket>& queue = packets.buffered_packets; ASSERT_EQ(1u, queue.size()); - // The alpn should be ignored for non-chlo packets. - ASSERT_TRUE(packets.alpns.empty()); + ASSERT_FALSE(packets.parsed_chlo.has_value()); // There is no valid version because CHLO has not arrived. EXPECT_EQ(invalid_version_, packets.version); // Check content of the only packet in the queue. @@ -93,9 +96,9 @@ QuicSocketAddress addr_with_new_port(QuicIpAddress::Any4(), 256); QuicConnectionId connection_id = TestConnectionId(1); store_.EnqueuePacket(connection_id, false, packet_, self_address_, - peer_address_, false, {}, "", invalid_version_); + peer_address_, invalid_version_, kNoParsedChlo); store_.EnqueuePacket(connection_id, false, packet_, self_address_, - addr_with_new_port, false, {}, "", invalid_version_); + addr_with_new_port, invalid_version_, kNoParsedChlo); std::list<BufferedPacket> queue = store_.DeliverPackets(connection_id).buffered_packets; ASSERT_EQ(2u, queue.size()); @@ -110,9 +113,9 @@ for (uint64_t conn_id = 1; conn_id <= num_connections; ++conn_id) { QuicConnectionId connection_id = TestConnectionId(conn_id); store_.EnqueuePacket(connection_id, false, packet_, self_address_, - peer_address_, false, {}, "", invalid_version_); + peer_address_, invalid_version_, kNoParsedChlo); store_.EnqueuePacket(connection_id, false, packet_, self_address_, - peer_address_, false, {}, "", invalid_version_); + peer_address_, invalid_version_, kNoParsedChlo); } // Deliver packets in reversed order. @@ -132,14 +135,15 @@ QuicConnectionId connection_id = TestConnectionId(1); // Arrived CHLO packet shouldn't affect how many non-CHLO pacekts store can // keep. - EXPECT_EQ(QuicBufferedPacketStore::SUCCESS, - store_.EnqueuePacket(connection_id, false, packet_, self_address_, - peer_address_, true, {}, "", valid_version_)); + EXPECT_EQ( + QuicBufferedPacketStore::SUCCESS, + store_.EnqueuePacket(connection_id, false, packet_, self_address_, + peer_address_, valid_version_, kDefaultParsedChlo)); for (size_t i = 1; i <= num_packets; ++i) { // Only first |kDefaultMaxUndecryptablePackets packets| will be buffered. EnqueuePacketResult result = store_.EnqueuePacket(connection_id, false, packet_, self_address_, - peer_address_, false, {}, "", invalid_version_); + peer_address_, invalid_version_, kNoParsedChlo); if (i <= kDefaultMaxUndecryptablePackets) { EXPECT_EQ(EnqueuePacketResult::SUCCESS, result); } else { @@ -161,7 +165,7 @@ QuicConnectionId connection_id = TestConnectionId(conn_id); EnqueuePacketResult result = store_.EnqueuePacket(connection_id, false, packet_, self_address_, - peer_address_, false, {}, "", invalid_version_); + peer_address_, invalid_version_, kNoParsedChlo); if (conn_id <= kMaxConnectionsWithoutCHLO) { EXPECT_EQ(EnqueuePacketResult::SUCCESS, result); } else { @@ -190,8 +194,8 @@ for (uint64_t conn_id = 1; conn_id <= num_chlos; ++conn_id) { EXPECT_EQ(EnqueuePacketResult::SUCCESS, store_.EnqueuePacket(TestConnectionId(conn_id), false, packet_, - self_address_, peer_address_, true, {}, "", - valid_version_)); + self_address_, peer_address_, valid_version_, + kDefaultParsedChlo)); } // Send data packets on another |kMaxConnectionsWithoutCHLO| connections. @@ -201,7 +205,7 @@ QuicConnectionId connection_id = TestConnectionId(conn_id); EnqueuePacketResult result = store_.EnqueuePacket(connection_id, false, packet_, self_address_, - peer_address_, true, {}, "", valid_version_); + peer_address_, valid_version_, kDefaultParsedChlo); if (conn_id <= kDefaultMaxConnectionsInStore) { EXPECT_EQ(EnqueuePacketResult::SUCCESS, result); } else { @@ -217,7 +221,7 @@ EXPECT_EQ( EnqueuePacketResult::SUCCESS, store_.EnqueuePacket(connection_id, false, packet_, self_address_, - peer_address_, false, {}, "", invalid_version_)); + peer_address_, invalid_version_, kNoParsedChlo)); } // Buffer CHLOs on other connections till store is full. @@ -226,7 +230,7 @@ QuicConnectionId connection_id = TestConnectionId(i); EnqueuePacketResult rs = store_.EnqueuePacket(connection_id, false, packet_, self_address_, - peer_address_, true, {}, "", valid_version_); + peer_address_, valid_version_, kDefaultParsedChlo); if (i <= kDefaultMaxConnectionsInStore) { EXPECT_EQ(EnqueuePacketResult::SUCCESS, rs); EXPECT_TRUE(store_.HasChloForConnection(connection_id)); @@ -240,10 +244,11 @@ // But buffering a CHLO belonging to a connection already has data packet // buffered in the store should success. This is the connection should be // delivered at last. - EXPECT_EQ(EnqueuePacketResult::SUCCESS, - store_.EnqueuePacket( - /*connection_id=*/TestConnectionId(1), false, packet_, - self_address_, peer_address_, true, {}, "", valid_version_)); + EXPECT_EQ( + EnqueuePacketResult::SUCCESS, + store_.EnqueuePacket( + /*connection_id=*/TestConnectionId(1), false, packet_, self_address_, + peer_address_, valid_version_, kDefaultParsedChlo)); EXPECT_TRUE(store_.HasChloForConnection( /*connection_id=*/TestConnectionId(1))); @@ -271,15 +276,16 @@ TEST_F(QuicBufferedPacketStoreTest, PacketQueueExpiredBeforeDelivery) { QuicConnectionId connection_id = TestConnectionId(1); store_.EnqueuePacket(connection_id, false, packet_, self_address_, - peer_address_, false, {}, "", invalid_version_); - EXPECT_EQ(EnqueuePacketResult::SUCCESS, - store_.EnqueuePacket(connection_id, false, packet_, self_address_, - peer_address_, true, {}, "", valid_version_)); + peer_address_, invalid_version_, kNoParsedChlo); + EXPECT_EQ( + EnqueuePacketResult::SUCCESS, + store_.EnqueuePacket(connection_id, false, packet_, self_address_, + peer_address_, valid_version_, kDefaultParsedChlo)); QuicConnectionId connection_id2 = TestConnectionId(2); EXPECT_EQ( EnqueuePacketResult::SUCCESS, store_.EnqueuePacket(connection_id2, false, packet_, self_address_, - peer_address_, false, {}, "", invalid_version_)); + peer_address_, invalid_version_, kNoParsedChlo)); // CHLO on connection 3 arrives 1ms later. clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(1)); @@ -288,7 +294,8 @@ // connections. QuicSocketAddress another_client_address(QuicIpAddress::Any4(), 255); store_.EnqueuePacket(connection_id3, false, packet_, self_address_, - another_client_address, true, {}, "", valid_version_); + another_client_address, valid_version_, + kDefaultParsedChlo); // Advance clock to the time when connection 1 and 2 expires. clock_.AdvanceTime( @@ -320,9 +327,9 @@ // for them to expire. QuicConnectionId connection_id4 = TestConnectionId(4); store_.EnqueuePacket(connection_id4, false, packet_, self_address_, - peer_address_, false, {}, "", invalid_version_); + peer_address_, invalid_version_, kNoParsedChlo); store_.EnqueuePacket(connection_id4, false, packet_, self_address_, - peer_address_, false, {}, "", invalid_version_); + peer_address_, invalid_version_, kNoParsedChlo); clock_.AdvanceTime( QuicBufferedPacketStorePeer::expiration_alarm(&store_)->deadline() - clock_.ApproximateNow()); @@ -337,9 +344,9 @@ // Enqueue some packets store_.EnqueuePacket(connection_id, false, packet_, self_address_, - peer_address_, false, {}, "", invalid_version_); + peer_address_, invalid_version_, kNoParsedChlo); store_.EnqueuePacket(connection_id, false, packet_, self_address_, - peer_address_, false, {}, "", invalid_version_); + peer_address_, invalid_version_, kNoParsedChlo); EXPECT_TRUE(store_.HasBufferedPackets(connection_id)); EXPECT_FALSE(store_.HasChlosBuffered()); @@ -363,11 +370,11 @@ // Enqueue some packets, which include a CHLO store_.EnqueuePacket(connection_id, false, packet_, self_address_, - peer_address_, false, {}, "", invalid_version_); + peer_address_, invalid_version_, kNoParsedChlo); store_.EnqueuePacket(connection_id, false, packet_, self_address_, - peer_address_, true, {}, "", valid_version_); + peer_address_, valid_version_, kDefaultParsedChlo); store_.EnqueuePacket(connection_id, false, packet_, self_address_, - peer_address_, false, {}, "", invalid_version_); + peer_address_, invalid_version_, kNoParsedChlo); EXPECT_TRUE(store_.HasBufferedPackets(connection_id)); EXPECT_TRUE(store_.HasChlosBuffered()); @@ -392,12 +399,15 @@ // Enqueue some packets for two connection IDs store_.EnqueuePacket(connection_id_1, false, packet_, self_address_, - peer_address_, false, {}, "", invalid_version_); + peer_address_, invalid_version_, kNoParsedChlo); store_.EnqueuePacket(connection_id_1, false, packet_, self_address_, - peer_address_, false, {}, "", invalid_version_); + peer_address_, invalid_version_, kNoParsedChlo); + + ParsedClientHello parsed_chlo; + parsed_chlo.alpns.push_back("h3"); + parsed_chlo.sni = TestHostname(); store_.EnqueuePacket(connection_id_2, false, packet_, self_address_, - peer_address_, true, {"h3"}, TestHostname(), - valid_version_); + peer_address_, valid_version_, parsed_chlo); EXPECT_TRUE(store_.HasBufferedPackets(connection_id_1)); EXPECT_TRUE(store_.HasBufferedPackets(connection_id_2)); EXPECT_TRUE(store_.HasChlosBuffered()); @@ -414,9 +424,9 @@ EXPECT_TRUE(store_.HasBufferedPackets(connection_id_2)); auto packets = store_.DeliverPackets(connection_id_2); EXPECT_EQ(1u, packets.buffered_packets.size()); - ASSERT_EQ(1u, packets.alpns.size()); - EXPECT_EQ("h3", packets.alpns[0]); - EXPECT_EQ(TestHostname(), packets.sni); + ASSERT_EQ(1u, packets.parsed_chlo->alpns.size()); + EXPECT_EQ("h3", packets.parsed_chlo->alpns[0]); + EXPECT_EQ(TestHostname(), packets.parsed_chlo->sni); // Since connection_id_2's chlo arrives, verify version is set. EXPECT_EQ(valid_version_, packets.version); EXPECT_TRUE(store_.HasChlosBuffered());
diff --git a/quic/core/quic_dispatcher.cc b/quic/core/quic_dispatcher.cc index 2d3a260..1484b74 100644 --- a/quic/core/quic_dispatcher.cc +++ b/quic/core/quic_dispatcher.cc
@@ -737,7 +737,7 @@ return; } - ProcessChlo(*parsed_chlo, packet_info); + ProcessChlo(*std::move(parsed_chlo), packet_info); return; } } @@ -773,7 +773,7 @@ } } -absl::optional<QuicDispatcher::ParsedClientHello> +absl::optional<ParsedClientHello> QuicDispatcher::TryExtractChloOrBufferEarlyPacket( const ReceivedPacketInfo& packet_info) { if (packet_info.version.UsesTls()) { @@ -1234,14 +1234,20 @@ if (packets.empty()) { return; } + if (!packet_list.parsed_chlo.has_value()) { + QUIC_BUG(quic_dispatcher_no_parsed_chlo_in_buffered_packets) + << "Buffered connection has no CHLO. connection_id:" + << server_connection_id; + continue; + } + const ParsedClientHello& parsed_chlo = *packet_list.parsed_chlo; QuicConnectionId original_connection_id = server_connection_id; server_connection_id = MaybeReplaceServerConnectionId(server_connection_id, packet_list.version); - std::string alpn = SelectAlpn(packet_list.alpns); - std::unique_ptr<QuicSession> session = - CreateQuicSession(server_connection_id, packets.front().self_address, - packets.front().peer_address, alpn, - packet_list.version, packet_list.sni); + std::string alpn = SelectAlpn(parsed_chlo.alpns); + std::unique_ptr<QuicSession> session = CreateQuicSession( + server_connection_id, packets.front().self_address, + packets.front().peer_address, alpn, packet_list.version, parsed_chlo); if (original_connection_id != server_connection_id) { session->connection()->SetOriginalDestinationConnectionId( original_connection_id); @@ -1302,14 +1308,14 @@ EnqueuePacketResult rs = buffered_packets_.EnqueuePacket( packet_info.destination_connection_id, packet_info.form != GOOGLE_QUIC_PACKET, packet_info.packet, - packet_info.self_address, packet_info.peer_address, /*is_chlo=*/false, - /*alpns=*/{}, /*sni=*/absl::string_view(), packet_info.version); + packet_info.self_address, packet_info.peer_address, packet_info.version, + /*parsed_chlo=*/absl::nullopt); if (rs != EnqueuePacketResult::SUCCESS) { OnBufferPacketFailure(rs, packet_info.destination_connection_id); } } -void QuicDispatcher::ProcessChlo(const ParsedClientHello& parsed_chlo, +void QuicDispatcher::ProcessChlo(ParsedClientHello parsed_chlo, ReceivedPacketInfo* packet_info) { if (!buffered_packets_.HasBufferedPackets( packet_info->destination_connection_id) && @@ -1325,8 +1331,7 @@ 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, parsed_chlo.alpns, parsed_chlo.sni, - packet_info->version); + packet_info->version, std::move(parsed_chlo)); if (rs != EnqueuePacketResult::SUCCESS) { OnBufferPacketFailure(rs, packet_info->destination_connection_id); } @@ -1341,7 +1346,7 @@ 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, parsed_chlo.sni); + packet_info->peer_address, alpn, packet_info->version, parsed_chlo); 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 1c4e53b..71e3914 100644 --- a/quic/core/quic_dispatcher.h +++ b/quic/core/quic_dispatcher.h
@@ -169,22 +169,14 @@ } 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. - }; - + // Creates a QUIC session based on the given information. + // |alpn| is the selected ALPN from |parsed_chlo.alpns|. virtual std::unique_ptr<QuicSession> CreateQuicSession( QuicConnectionId server_connection_id, const QuicSocketAddress& self_address, - const QuicSocketAddress& peer_address, - absl::string_view alpn, + const QuicSocketAddress& peer_address, absl::string_view alpn, const ParsedQuicVersion& version, - absl::string_view sni) = 0; + const ParsedClientHello& parsed_chlo) = 0; // Tries to validate and dispatch packet based on available information. // Returns true if packet is dropped or successfully dispatched (e.g., @@ -255,7 +247,7 @@ // 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, + void ProcessChlo(ParsedClientHello parsed_chlo, ReceivedPacketInfo* packet_info); // Return true if dispatcher wants to destroy session outside of
diff --git a/quic/core/quic_dispatcher_test.cc b/quic/core/quic_dispatcher_test.cc index 276f59c..1dfda6c 100644 --- a/quic/core/quic_dispatcher_test.cc +++ b/quic/core/quic_dispatcher_test.cc
@@ -130,14 +130,12 @@ kQuicDefaultConnectionIdLength), random_(random) {} - MOCK_METHOD(std::unique_ptr<QuicSession>, - CreateQuicSession, + MOCK_METHOD(std::unique_ptr<QuicSession>, CreateQuicSession, (QuicConnectionId connection_id, const QuicSocketAddress& self_address, - const QuicSocketAddress& peer_address, - absl::string_view alpn, - const quic::ParsedQuicVersion& version, - absl::string_view sni), + const QuicSocketAddress& peer_address, absl::string_view alpn, + const ParsedQuicVersion& version, + const ParsedClientHello& parsed_chlo), (override)); MOCK_METHOD(bool, @@ -458,6 +456,13 @@ std::string ExpectedAlpn() { return ExpectedAlpnForVersion(version_); } + ParsedClientHello ParsedClientHelloForTest() { + ParsedClientHello parsed_chlo; + parsed_chlo.alpns = {ExpectedAlpn()}; + parsed_chlo.sni = TestHostname(); + return parsed_chlo; + } + void MarkSession1Deleted() { session1_ = nullptr; } void VerifyVersionSupported(ParsedQuicVersion version) { @@ -588,9 +593,10 @@ << "No session should be created before the rest of the CHLO arrives."; // Processing the second packet should create the new session. - EXPECT_CALL(*dispatcher_, - CreateQuicSession(server_connection_id, _, client_address, - Eq(ExpectedAlpn()), _, TestHostname())) + EXPECT_CALL( + *dispatcher_, + CreateQuicSession(server_connection_id, _, client_address, + Eq(ExpectedAlpn()), _, Eq(ParsedClientHelloForTest()))) .WillOnce(Return(ByMove(CreateSession( dispatcher_.get(), config_, server_connection_id, client_address, &mock_helper_, &mock_alarm_factory_, &crypto_config_, @@ -679,9 +685,10 @@ TEST_P(QuicDispatcherTestAllVersions, ProcessPackets) { QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1); - EXPECT_CALL(*dispatcher_, - CreateQuicSession(TestConnectionId(1), _, client_address, - Eq(ExpectedAlpn()), _, TestHostname())) + EXPECT_CALL( + *dispatcher_, + CreateQuicSession(TestConnectionId(1), _, client_address, + Eq(ExpectedAlpn()), _, Eq(ParsedClientHelloForTest()))) .WillOnce(Return(ByMove(CreateSession( dispatcher_.get(), config_, TestConnectionId(1), client_address, &mock_helper_, &mock_alarm_factory_, &crypto_config_, @@ -696,9 +703,10 @@ ReceivedPacketInfoConnectionIdEquals(TestConnectionId(1)))); ProcessFirstFlight(client_address, TestConnectionId(1)); - EXPECT_CALL(*dispatcher_, - CreateQuicSession(TestConnectionId(2), _, client_address, - Eq(ExpectedAlpn()), _, TestHostname())) + EXPECT_CALL( + *dispatcher_, + CreateQuicSession(TestConnectionId(2), _, client_address, + Eq(ExpectedAlpn()), _, Eq(ParsedClientHelloForTest()))) .WillOnce(Return(ByMove(CreateSession( dispatcher_.get(), config_, TestConnectionId(2), client_address, &mock_helper_, &mock_alarm_factory_, &crypto_config_, @@ -2407,7 +2415,7 @@ // buffered should be delivered to the session. EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id, _, client_addr_, Eq(ExpectedAlpn()), _, - TestHostname())) + Eq(ParsedClientHelloForTest()))) .WillOnce(Return(ByMove(CreateSession( dispatcher_.get(), config_, conn_id, client_addr_, &mock_helper_, &mock_alarm_factory_, &crypto_config_, @@ -2611,7 +2619,8 @@ if (conn_id <= kMaxNumSessionsToCreate) { EXPECT_CALL(*dispatcher_, CreateQuicSession(TestConnectionId(conn_id), _, client_addr_, - Eq(ExpectedAlpn()), _, TestHostname())) + Eq(ExpectedAlpn()), _, + Eq(ParsedClientHelloForTest()))) .WillOnce(Return(ByMove(CreateSession( dispatcher_.get(), config_, TestConnectionId(conn_id), client_addr_, &mock_helper_, &mock_alarm_factory_, @@ -2646,7 +2655,8 @@ ++conn_id) { EXPECT_CALL(*dispatcher_, CreateQuicSession(TestConnectionId(conn_id), _, client_addr_, - Eq(ExpectedAlpn()), _, TestHostname())) + Eq(ExpectedAlpn()), _, + Eq(ParsedClientHelloForTest()))) .WillOnce(Return(ByMove(CreateSession( dispatcher_.get(), config_, TestConnectionId(conn_id), client_addr_, &mock_helper_, &mock_alarm_factory_, &crypto_config_,
diff --git a/quic/core/quic_types.cc b/quic/core/quic_types.cc index f578bb4..8c155c4 100644 --- a/quic/core/quic_types.cc +++ b/quic/core/quic_types.cc
@@ -8,6 +8,7 @@ #include "absl/strings/str_cat.h" #include "quic/core/quic_error_codes.h" +#include "common/print_elements.h" namespace quic { @@ -382,6 +383,21 @@ return os; } +bool operator==(const ParsedClientHello& a, const ParsedClientHello& b) { + return a.sni == b.sni && a.uaid == b.uaid && a.alpns == b.alpns && + a.legacy_version_encapsulation_inner_packet == + b.legacy_version_encapsulation_inner_packet; +} + +std::ostream& operator<<(std::ostream& os, + const ParsedClientHello& parsed_chlo) { + os << "{ sni:" << parsed_chlo.sni << ", uaid:" << parsed_chlo.uaid + << ", alpns:" << quiche::PrintElements(parsed_chlo.alpns) + << ", len(inner_packet):" + << parsed_chlo.legacy_version_encapsulation_inner_packet.size() << " }"; + return os; +} + #undef RETURN_STRING_LITERAL // undef for jumbo builds } // namespace quic
diff --git a/quic/core/quic_types.h b/quic/core/quic_types.h index edfa78b..b0f32cd 100644 --- a/quic/core/quic_types.h +++ b/quic/core/quic_types.h
@@ -848,6 +848,21 @@ absl::optional<absl::InlinedVector<uint16_t, 8>> signing_algorithm_prefs; }; +// 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. +}; + +QUIC_EXPORT_PRIVATE bool operator==(const ParsedClientHello& a, + const ParsedClientHello& b); + +QUIC_EXPORT_PRIVATE std::ostream& operator<<( + std::ostream& os, const ParsedClientHello& parsed_chlo); + } // namespace quic #endif // QUICHE_QUIC_CORE_QUIC_TYPES_H_
diff --git a/quic/masque/masque_dispatcher.cc b/quic/masque/masque_dispatcher.cc index 5729d54..c14e03d 100644 --- a/quic/masque/masque_dispatcher.cc +++ b/quic/masque/masque_dispatcher.cc
@@ -31,12 +31,10 @@ masque_server_backend_(masque_server_backend) {} std::unique_ptr<QuicSession> MasqueDispatcher::CreateQuicSession( - QuicConnectionId connection_id, - const QuicSocketAddress& self_address, - const QuicSocketAddress& peer_address, - absl::string_view /*alpn*/, + QuicConnectionId connection_id, const QuicSocketAddress& self_address, + const QuicSocketAddress& peer_address, absl::string_view /*alpn*/, const ParsedQuicVersion& version, - absl::string_view /*sni*/) { + const ParsedClientHello& /*parsed_chlo*/) { // The MasqueServerSession takes ownership of |connection| below. QuicConnection* connection = new QuicConnection(connection_id, self_address, peer_address, helper(),
diff --git a/quic/masque/masque_dispatcher.h b/quic/masque/masque_dispatcher.h index 368219e..35c5e0f 100644 --- a/quic/masque/masque_dispatcher.h +++ b/quic/masque/masque_dispatcher.h
@@ -38,12 +38,10 @@ // From QuicSimpleDispatcher. std::unique_ptr<QuicSession> CreateQuicSession( - QuicConnectionId connection_id, - const QuicSocketAddress& self_address, - const QuicSocketAddress& peer_address, - absl::string_view alpn, + QuicConnectionId connection_id, const QuicSocketAddress& self_address, + const QuicSocketAddress& peer_address, absl::string_view alpn, const ParsedQuicVersion& version, - absl::string_view sni) override; + const quic::ParsedClientHello& parsed_chlo) override; bool OnFailedToDispatchPacket(const ReceivedPacketInfo& packet_info) override;
diff --git a/quic/qbone/qbone_client_test.cc b/quic/qbone/qbone_client_test.cc index 91bb82d..371a8b6 100644 --- a/quic/qbone/qbone_client_test.cc +++ b/quic/qbone/qbone_client_test.cc
@@ -123,12 +123,10 @@ writer_(writer) {} std::unique_ptr<QuicSession> CreateQuicSession( - QuicConnectionId id, - const QuicSocketAddress& self_address, - const QuicSocketAddress& peer_address, - absl::string_view alpn, - const quic::ParsedQuicVersion& version, - absl::string_view sni) override { + QuicConnectionId id, const QuicSocketAddress& self_address, + const QuicSocketAddress& peer_address, absl::string_view alpn, + const ParsedQuicVersion& version, + const ParsedClientHello& /*parsed_chlo*/) override { QUICHE_CHECK_EQ(alpn, "qbone"); QuicConnection* connection = new QuicConnection( id, self_address, peer_address, helper(), alarm_factory(), writer(),
diff --git a/quic/test_tools/quic_test_server.cc b/quic/test_tools/quic_test_server.cc index 020a34c..1d85805 100644 --- a/quic/test_tools/quic_test_server.cc +++ b/quic/test_tools/quic_test_server.cc
@@ -96,7 +96,8 @@ std::unique_ptr<QuicSession> CreateQuicSession( QuicConnectionId id, const QuicSocketAddress& self_address, const QuicSocketAddress& peer_address, absl::string_view /*alpn*/, - const ParsedQuicVersion& version, absl::string_view /*sni*/) override { + const ParsedQuicVersion& version, + const ParsedClientHello& /*parsed_chlo*/) override { QuicReaderMutexLock lock(&factory_lock_); // The QuicServerSessionBase takes ownership of |connection| below. QuicConnection* connection = new QuicConnection(
diff --git a/quic/tools/quic_simple_dispatcher.cc b/quic/tools/quic_simple_dispatcher.cc index aa9a9c1..7864ce7 100644 --- a/quic/tools/quic_simple_dispatcher.cc +++ b/quic/tools/quic_simple_dispatcher.cc
@@ -49,12 +49,10 @@ } std::unique_ptr<QuicSession> QuicSimpleDispatcher::CreateQuicSession( - QuicConnectionId connection_id, - const QuicSocketAddress& self_address, - const QuicSocketAddress& peer_address, - absl::string_view /*alpn*/, + QuicConnectionId connection_id, const QuicSocketAddress& self_address, + const QuicSocketAddress& peer_address, absl::string_view /*alpn*/, const ParsedQuicVersion& version, - absl::string_view /*sni*/) { + const ParsedClientHello& /*parsed_chlo*/) { // The QuicServerSessionBase takes ownership of |connection| below. QuicConnection* connection = new QuicConnection(connection_id, self_address, peer_address, helper(),
diff --git a/quic/tools/quic_simple_dispatcher.h b/quic/tools/quic_simple_dispatcher.h index c790f21..ce9d680 100644 --- a/quic/tools/quic_simple_dispatcher.h +++ b/quic/tools/quic_simple_dispatcher.h
@@ -32,12 +32,10 @@ protected: std::unique_ptr<QuicSession> CreateQuicSession( - QuicConnectionId connection_id, - const QuicSocketAddress& self_address, - const QuicSocketAddress& peer_address, - absl::string_view alpn, + QuicConnectionId connection_id, const QuicSocketAddress& self_address, + const QuicSocketAddress& peer_address, absl::string_view alpn, const ParsedQuicVersion& version, - absl::string_view sni) override; + const ParsedClientHello& parsed_chlo) override; QuicSimpleServerBackend* server_backend() { return quic_simple_server_backend_;
diff --git a/quic/tools/quic_transport_simple_server_dispatcher.cc b/quic/tools/quic_transport_simple_server_dispatcher.cc index 25730ed..b767434 100644 --- a/quic/tools/quic_transport_simple_server_dispatcher.cc +++ b/quic/tools/quic_transport_simple_server_dispatcher.cc
@@ -37,10 +37,9 @@ QuicTransportSimpleServerDispatcher::CreateQuicSession( QuicConnectionId server_connection_id, const QuicSocketAddress& self_address, - const QuicSocketAddress& peer_address, - absl::string_view /*alpn*/, + const QuicSocketAddress& peer_address, absl::string_view /*alpn*/, const ParsedQuicVersion& version, - absl::string_view /*sni*/) { + const ParsedClientHello& /*parsed_chlo*/) { auto connection = std::make_unique<QuicConnection>( server_connection_id, self_address, peer_address, helper(), alarm_factory(), writer(),
diff --git a/quic/tools/quic_transport_simple_server_dispatcher.h b/quic/tools/quic_transport_simple_server_dispatcher.h index bb38596..d8761f6 100644 --- a/quic/tools/quic_transport_simple_server_dispatcher.h +++ b/quic/tools/quic_transport_simple_server_dispatcher.h
@@ -30,10 +30,9 @@ std::unique_ptr<QuicSession> CreateQuicSession( QuicConnectionId server_connection_id, const QuicSocketAddress& self_address, - const QuicSocketAddress& peer_address, - absl::string_view alpn, + const QuicSocketAddress& peer_address, absl::string_view alpn, const ParsedQuicVersion& version, - absl::string_view sni) override; + const ParsedClientHello& parsed_chlo) override; std::vector<url::Origin> accepted_origins_; };