Fix replacing connection IDs when initial crypters are in use
When the client uses an initial destination connection ID length different than 8 bytes, we replace that connection ID with a random 8-byte one. However, the initial crypters are still based on that original connection ID. This change makes sure that we initialize the TLS crypters with the right connection ID. This also removes the code that would set the crypters in tls_server_handshaker because that is no longer required now that we've completely removed in-connection version negotiation.
This change also makes sure we correctly check the QuicDispatcher::session_map_ for the replaced connection ID which is required to properly route subsequent long header packets after the first one.
This change is safe without flag protection because it only impacts versions that allow connection IDs of length different than 8, and all those versions are disabled by flags.
gfe-relnote: fix connection ID replacement, protected by quic_enable_v47/48/99
PiperOrigin-RevId: 257697143
Change-Id: Ifc3779e292104656abd72fae79fba8b7604cabe2
diff --git a/quic/core/quic_dispatcher.cc b/quic/core/quic_dispatcher.cc
index f7973e0..0a83ca8 100644
--- a/quic/core/quic_dispatcher.cc
+++ b/quic/core/quic_dispatcher.cc
@@ -276,6 +276,9 @@
session_helper_->GenerateConnectionIdForReject(version.transport_version,
server_connection_id);
DCHECK_EQ(expected_server_connection_id_length_, new_connection_id.length());
+ // TODO(dschinazi) Prevent connection_id_map_ from growing indefinitely
+ // before we ship a version that supports variable length connection IDs
+ // to production.
connection_id_map_.insert(
std::make_pair(server_connection_id, new_connection_id));
QUIC_DLOG(INFO) << "Replacing incoming connection ID " << server_connection_id
@@ -340,6 +343,21 @@
it->second->ProcessUdpPacket(packet_info.self_address,
packet_info.peer_address, packet_info.packet);
return true;
+ } else {
+ // We did not find the connection ID, check if we've replaced it.
+ QuicConnectionId replaced_connection_id = MaybeReplaceServerConnectionId(
+ server_connection_id, packet_info.version);
+ if (replaced_connection_id != server_connection_id) {
+ // Search for the replacement.
+ auto it2 = session_map_.find(replaced_connection_id);
+ if (it2 != session_map_.end()) {
+ DCHECK(!buffered_packets_.HasBufferedPackets(replaced_connection_id));
+ it2->second->ProcessUdpPacket(packet_info.self_address,
+ packet_info.peer_address,
+ packet_info.packet);
+ return true;
+ }
+ }
}
if (buffered_packets_.HasChloForConnection(server_connection_id)) {
@@ -723,8 +741,13 @@
packet_list.alpn, packet_list.version);
if (original_connection_id != server_connection_id) {
session->connection()->AddIncomingConnectionId(original_connection_id);
+ session->connection()->InstallInitialCrypters(original_connection_id);
}
QUIC_DLOG(INFO) << "Created new session for " << server_connection_id;
+
+ DCHECK(session_map_.find(server_connection_id) == session_map_.end())
+ << "Tried to add session map existing entry " << server_connection_id;
+
session_map_.insert(
std::make_pair(server_connection_id, QuicWrapUnique(session)));
DeliverPacketsToSession(packets, session);
@@ -825,9 +848,16 @@
packet_info->peer_address, alpn, packet_info->version);
if (original_connection_id != packet_info->destination_connection_id) {
session->connection()->AddIncomingConnectionId(original_connection_id);
+ session->connection()->InstallInitialCrypters(original_connection_id);
}
QUIC_DLOG(INFO) << "Created new session for "
<< packet_info->destination_connection_id;
+
+ DCHECK(session_map_.find(packet_info->destination_connection_id) ==
+ session_map_.end())
+ << "Tried to add session map existing entry "
+ << packet_info->destination_connection_id;
+
session_map_.insert(std::make_pair(packet_info->destination_connection_id,
QuicWrapUnique(session)));
std::list<BufferedPacket> packets =