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_;
};