1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "quiche/quic/core/quic_dispatcher.h"
6
7 #include <openssl/ssl.h>
8
9 #include <algorithm>
10 #include <cstddef>
11 #include <cstdint>
12 #include <list>
13 #include <memory>
14 #include <optional>
15 #include <ostream>
16 #include <string>
17 #include <utility>
18 #include <vector>
19
20 #include "absl/base/macros.h"
21 #include "absl/base/optimization.h"
22 #include "absl/container/flat_hash_set.h"
23 #include "absl/strings/str_cat.h"
24 #include "absl/strings/string_view.h"
25 #include "quiche/quic/core/chlo_extractor.h"
26 #include "quiche/quic/core/connection_id_generator.h"
27 #include "quiche/quic/core/crypto/crypto_handshake_message.h"
28 #include "quiche/quic/core/crypto/crypto_protocol.h"
29 #include "quiche/quic/core/crypto/quic_compressed_certs_cache.h"
30 #include "quiche/quic/core/frames/quic_connection_close_frame.h"
31 #include "quiche/quic/core/frames/quic_frame.h"
32 #include "quiche/quic/core/frames/quic_rst_stream_frame.h"
33 #include "quiche/quic/core/frames/quic_stop_sending_frame.h"
34 #include "quiche/quic/core/quic_alarm.h"
35 #include "quiche/quic/core/quic_alarm_factory.h"
36 #include "quiche/quic/core/quic_blocked_writer_interface.h"
37 #include "quiche/quic/core/quic_buffered_packet_store.h"
38 #include "quiche/quic/core/quic_connection.h"
39 #include "quiche/quic/core/quic_connection_id.h"
40 #include "quiche/quic/core/quic_constants.h"
41 #include "quiche/quic/core/quic_crypto_server_stream_base.h"
42 #include "quiche/quic/core/quic_data_writer.h"
43 #include "quiche/quic/core/quic_error_codes.h"
44 #include "quiche/quic/core/quic_framer.h"
45 #include "quiche/quic/core/quic_packet_creator.h"
46 #include "quiche/quic/core/quic_packet_writer.h"
47 #include "quiche/quic/core/quic_packets.h"
48 #include "quiche/quic/core/quic_session.h"
49 #include "quiche/quic/core/quic_stream_frame_data_producer.h"
50 #include "quiche/quic/core/quic_stream_send_buffer.h"
51 #include "quiche/quic/core/quic_time.h"
52 #include "quiche/quic/core/quic_time_wait_list_manager.h"
53 #include "quiche/quic/core/quic_types.h"
54 #include "quiche/quic/core/quic_utils.h"
55 #include "quiche/quic/core/quic_version_manager.h"
56 #include "quiche/quic/core/quic_versions.h"
57 #include "quiche/quic/core/tls_chlo_extractor.h"
58 #include "quiche/quic/platform/api/quic_bug_tracker.h"
59 #include "quiche/quic/platform/api/quic_flag_utils.h"
60 #include "quiche/quic/platform/api/quic_flags.h"
61 #include "quiche/quic/platform/api/quic_logging.h"
62 #include "quiche/quic/platform/api/quic_socket_address.h"
63 #include "quiche/quic/platform/api/quic_stack_trace.h"
64 #include "quiche/common/platform/api/quiche_logging.h"
65 #include "quiche/common/quiche_buffer_allocator.h"
66 #include "quiche/common/quiche_callbacks.h"
67 #include "quiche/common/quiche_text_utils.h"
68
69 namespace quic {
70
71 using BufferedPacket = QuicBufferedPacketStore::BufferedPacket;
72 using BufferedPacketList = QuicBufferedPacketStore::BufferedPacketList;
73 using EnqueuePacketResult = QuicBufferedPacketStore::EnqueuePacketResult;
74
75 namespace {
76
77 // Minimal INITIAL packet length sent by clients is 1200.
78 const QuicPacketLength kMinClientInitialPacketLength = 1200;
79
80 // An alarm that informs the QuicDispatcher to delete old sessions.
81 class DeleteSessionsAlarm : public QuicAlarm::DelegateWithoutContext {
82 public:
DeleteSessionsAlarm(QuicDispatcher * dispatcher)83 explicit DeleteSessionsAlarm(QuicDispatcher* dispatcher)
84 : dispatcher_(dispatcher) {}
85 DeleteSessionsAlarm(const DeleteSessionsAlarm&) = delete;
86 DeleteSessionsAlarm& operator=(const DeleteSessionsAlarm&) = delete;
87
OnAlarm()88 void OnAlarm() override { dispatcher_->DeleteSessions(); }
89
90 private:
91 // Not owned.
92 QuicDispatcher* dispatcher_;
93 };
94
95 // An alarm that informs the QuicDispatcher to clear
96 // recent_stateless_reset_addresses_.
97 class ClearStatelessResetAddressesAlarm
98 : public QuicAlarm::DelegateWithoutContext {
99 public:
ClearStatelessResetAddressesAlarm(QuicDispatcher * dispatcher)100 explicit ClearStatelessResetAddressesAlarm(QuicDispatcher* dispatcher)
101 : dispatcher_(dispatcher) {}
102 ClearStatelessResetAddressesAlarm(const DeleteSessionsAlarm&) = delete;
103 ClearStatelessResetAddressesAlarm& operator=(const DeleteSessionsAlarm&) =
104 delete;
105
OnAlarm()106 void OnAlarm() override { dispatcher_->ClearStatelessResetAddresses(); }
107
108 private:
109 // Not owned.
110 QuicDispatcher* dispatcher_;
111 };
112
113 // Collects packets serialized by a QuicPacketCreator in order
114 // to be handed off to the time wait list manager.
115 class PacketCollector : public QuicPacketCreator::DelegateInterface,
116 public QuicStreamFrameDataProducer {
117 public:
PacketCollector(quiche::QuicheBufferAllocator * allocator)118 explicit PacketCollector(quiche::QuicheBufferAllocator* allocator)
119 : send_buffer_(allocator) {}
120 ~PacketCollector() override = default;
121
122 // QuicPacketCreator::DelegateInterface methods:
OnSerializedPacket(SerializedPacket serialized_packet)123 void OnSerializedPacket(SerializedPacket serialized_packet) override {
124 // Make a copy of the serialized packet to send later.
125 packets_.emplace_back(
126 new QuicEncryptedPacket(CopyBuffer(serialized_packet),
127 serialized_packet.encrypted_length, true));
128 }
129
GetPacketBuffer()130 QuicPacketBuffer GetPacketBuffer() override {
131 // Let QuicPacketCreator to serialize packets on stack buffer.
132 return {nullptr, nullptr};
133 }
134
OnUnrecoverableError(QuicErrorCode,const std::string &)135 void OnUnrecoverableError(QuicErrorCode /*error*/,
136 const std::string& /*error_details*/) override {}
137
ShouldGeneratePacket(HasRetransmittableData,IsHandshake)138 bool ShouldGeneratePacket(HasRetransmittableData /*retransmittable*/,
139 IsHandshake /*handshake*/) override {
140 QUICHE_DCHECK(false);
141 return true;
142 }
143
MaybeBundleOpportunistically(TransmissionType)144 void MaybeBundleOpportunistically(
145 TransmissionType /*transmission_type*/) override {
146 QUICHE_DCHECK(false);
147 }
148
GetFlowControlSendWindowSize(QuicStreamId)149 QuicByteCount GetFlowControlSendWindowSize(QuicStreamId /*id*/) override {
150 QUICHE_DCHECK(false);
151 return std::numeric_limits<QuicByteCount>::max();
152 }
153
GetSerializedPacketFate(bool,EncryptionLevel)154 SerializedPacketFate GetSerializedPacketFate(
155 bool /*is_mtu_discovery*/,
156 EncryptionLevel /*encryption_level*/) override {
157 return SEND_TO_WRITER;
158 }
159
160 // QuicStreamFrameDataProducer
WriteStreamData(QuicStreamId,QuicStreamOffset offset,QuicByteCount data_length,QuicDataWriter * writer)161 WriteStreamDataResult WriteStreamData(QuicStreamId /*id*/,
162 QuicStreamOffset offset,
163 QuicByteCount data_length,
164 QuicDataWriter* writer) override {
165 if (send_buffer_.WriteStreamData(offset, data_length, writer)) {
166 return WRITE_SUCCESS;
167 }
168 return WRITE_FAILED;
169 }
WriteCryptoData(EncryptionLevel,QuicStreamOffset offset,QuicByteCount data_length,QuicDataWriter * writer)170 bool WriteCryptoData(EncryptionLevel /*level*/, QuicStreamOffset offset,
171 QuicByteCount data_length,
172 QuicDataWriter* writer) override {
173 return send_buffer_.WriteStreamData(offset, data_length, writer);
174 }
175
packets()176 std::vector<std::unique_ptr<QuicEncryptedPacket>>* packets() {
177 return &packets_;
178 }
179
180 private:
181 std::vector<std::unique_ptr<QuicEncryptedPacket>> packets_;
182 // This is only needed until the packets are encrypted. Once packets are
183 // encrypted, the stream data is no longer required.
184 QuicStreamSendBuffer send_buffer_;
185 };
186
187 // Helper for statelessly closing connections by generating the
188 // correct termination packets and adding the connection to the time wait
189 // list manager.
190 class StatelessConnectionTerminator {
191 public:
StatelessConnectionTerminator(QuicConnectionId server_connection_id,QuicConnectionId original_server_connection_id,const ParsedQuicVersion version,QuicConnectionHelperInterface * helper,QuicTimeWaitListManager * time_wait_list_manager)192 StatelessConnectionTerminator(QuicConnectionId server_connection_id,
193 QuicConnectionId original_server_connection_id,
194 const ParsedQuicVersion version,
195 QuicConnectionHelperInterface* helper,
196 QuicTimeWaitListManager* time_wait_list_manager)
197 : server_connection_id_(server_connection_id),
198 framer_(ParsedQuicVersionVector{version},
199 /*unused*/ QuicTime::Zero(), Perspective::IS_SERVER,
200 /*unused*/ kQuicDefaultConnectionIdLength),
201 collector_(helper->GetStreamSendBufferAllocator()),
202 creator_(server_connection_id, &framer_, &collector_),
203 time_wait_list_manager_(time_wait_list_manager) {
204 framer_.set_data_producer(&collector_);
205 // Always set encrypter with original_server_connection_id.
206 framer_.SetInitialObfuscators(original_server_connection_id);
207 }
208
~StatelessConnectionTerminator()209 ~StatelessConnectionTerminator() {
210 // Clear framer's producer.
211 framer_.set_data_producer(nullptr);
212 }
213
214 // Generates a packet containing a CONNECTION_CLOSE frame specifying
215 // |error_code| and |error_details| and add the connection to time wait.
CloseConnection(QuicErrorCode error_code,const std::string & error_details,bool ietf_quic,std::vector<QuicConnectionId> active_connection_ids)216 void CloseConnection(QuicErrorCode error_code,
217 const std::string& error_details, bool ietf_quic,
218 std::vector<QuicConnectionId> active_connection_ids) {
219 SerializeConnectionClosePacket(error_code, error_details);
220
221 time_wait_list_manager_->AddConnectionIdToTimeWait(
222 QuicTimeWaitListManager::SEND_TERMINATION_PACKETS,
223 TimeWaitConnectionInfo(ietf_quic, collector_.packets(),
224 std::move(active_connection_ids),
225 /*srtt=*/QuicTime::Delta::Zero()));
226 }
227
228 private:
SerializeConnectionClosePacket(QuicErrorCode error_code,const std::string & error_details)229 void SerializeConnectionClosePacket(QuicErrorCode error_code,
230 const std::string& error_details) {
231 QuicConnectionCloseFrame* frame =
232 new QuicConnectionCloseFrame(framer_.transport_version(), error_code,
233 NO_IETF_QUIC_ERROR, error_details,
234 /*transport_close_frame_type=*/0);
235
236 if (!creator_.AddFrame(QuicFrame(frame), NOT_RETRANSMISSION)) {
237 QUIC_BUG(quic_bug_10287_1) << "Unable to add frame to an empty packet";
238 delete frame;
239 return;
240 }
241 creator_.FlushCurrentPacket();
242 QUICHE_DCHECK_EQ(1u, collector_.packets()->size());
243 }
244
245 QuicConnectionId server_connection_id_;
246 QuicFramer framer_;
247 // Set as the visitor of |creator_| to collect any generated packets.
248 PacketCollector collector_;
249 QuicPacketCreator creator_;
250 QuicTimeWaitListManager* time_wait_list_manager_;
251 };
252
253 // Class which extracts the ALPN and SNI from a QUIC_CRYPTO CHLO packet.
254 class ChloAlpnSniExtractor : public ChloExtractor::Delegate {
255 public:
OnChlo(QuicTransportVersion,QuicConnectionId,const CryptoHandshakeMessage & chlo)256 void OnChlo(QuicTransportVersion /*version*/,
257 QuicConnectionId /*server_connection_id*/,
258 const CryptoHandshakeMessage& chlo) override {
259 absl::string_view alpn_value;
260 if (chlo.GetStringPiece(kALPN, &alpn_value)) {
261 alpn_ = std::string(alpn_value);
262 }
263 absl::string_view sni;
264 if (chlo.GetStringPiece(quic::kSNI, &sni)) {
265 sni_ = std::string(sni);
266 }
267 absl::string_view uaid_value;
268 if (chlo.GetStringPiece(quic::kUAID, &uaid_value)) {
269 uaid_ = std::string(uaid_value);
270 }
271 }
272
ConsumeAlpn()273 std::string&& ConsumeAlpn() { return std::move(alpn_); }
274
ConsumeSni()275 std::string&& ConsumeSni() { return std::move(sni_); }
276
ConsumeUaid()277 std::string&& ConsumeUaid() { return std::move(uaid_); }
278
279 private:
280 std::string alpn_;
281 std::string sni_;
282 std::string uaid_;
283 };
284
285 } // namespace
286
QuicDispatcher(const QuicConfig * config,const QuicCryptoServerConfig * crypto_config,QuicVersionManager * version_manager,std::unique_ptr<QuicConnectionHelperInterface> helper,std::unique_ptr<QuicCryptoServerStreamBase::Helper> session_helper,std::unique_ptr<QuicAlarmFactory> alarm_factory,uint8_t expected_server_connection_id_length,ConnectionIdGeneratorInterface & connection_id_generator)287 QuicDispatcher::QuicDispatcher(
288 const QuicConfig* config, const QuicCryptoServerConfig* crypto_config,
289 QuicVersionManager* version_manager,
290 std::unique_ptr<QuicConnectionHelperInterface> helper,
291 std::unique_ptr<QuicCryptoServerStreamBase::Helper> session_helper,
292 std::unique_ptr<QuicAlarmFactory> alarm_factory,
293 uint8_t expected_server_connection_id_length,
294 ConnectionIdGeneratorInterface& connection_id_generator)
295 : config_(config),
296 crypto_config_(crypto_config),
297 compressed_certs_cache_(
298 QuicCompressedCertsCache::kQuicCompressedCertsCacheSize),
299 helper_(std::move(helper)),
300 session_helper_(std::move(session_helper)),
301 alarm_factory_(std::move(alarm_factory)),
302 delete_sessions_alarm_(
303 alarm_factory_->CreateAlarm(new DeleteSessionsAlarm(this))),
304 buffered_packets_(this, helper_->GetClock(), alarm_factory_.get()),
305 version_manager_(version_manager),
306 last_error_(QUIC_NO_ERROR),
307 new_sessions_allowed_per_event_loop_(0u),
308 accept_new_connections_(true),
309 allow_short_initial_server_connection_ids_(false),
310 expected_server_connection_id_length_(
311 expected_server_connection_id_length),
312 clear_stateless_reset_addresses_alarm_(alarm_factory_->CreateAlarm(
313 new ClearStatelessResetAddressesAlarm(this))),
314 should_update_expected_server_connection_id_length_(false),
315 connection_id_generator_(connection_id_generator) {
316 QUIC_BUG_IF(quic_bug_12724_1, GetSupportedVersions().empty())
317 << "Trying to create dispatcher without any supported versions";
318 QUIC_DLOG(INFO) << "Created QuicDispatcher with versions: "
319 << ParsedQuicVersionVectorToString(GetSupportedVersions());
320 }
321
~QuicDispatcher()322 QuicDispatcher::~QuicDispatcher() {
323 if (delete_sessions_alarm_ != nullptr) {
324 delete_sessions_alarm_->PermanentCancel();
325 }
326 if (clear_stateless_reset_addresses_alarm_ != nullptr) {
327 clear_stateless_reset_addresses_alarm_->PermanentCancel();
328 }
329 reference_counted_session_map_.clear();
330 closed_session_list_.clear();
331 num_sessions_in_session_map_ = 0;
332 }
333
InitializeWithWriter(QuicPacketWriter * writer)334 void QuicDispatcher::InitializeWithWriter(QuicPacketWriter* writer) {
335 QUICHE_DCHECK(writer_ == nullptr);
336 writer_.reset(writer);
337 time_wait_list_manager_.reset(CreateQuicTimeWaitListManager());
338 }
339
ProcessPacket(const QuicSocketAddress & self_address,const QuicSocketAddress & peer_address,const QuicReceivedPacket & packet)340 void QuicDispatcher::ProcessPacket(const QuicSocketAddress& self_address,
341 const QuicSocketAddress& peer_address,
342 const QuicReceivedPacket& packet) {
343 QUIC_DVLOG(2) << "Dispatcher received encrypted " << packet.length()
344 << " bytes:" << std::endl
345 << quiche::QuicheTextUtils::HexDump(
346 absl::string_view(packet.data(), packet.length()));
347 ++num_packets_received_;
348 ReceivedPacketInfo packet_info(self_address, peer_address, packet);
349 std::string detailed_error;
350 QuicErrorCode error;
351 error = QuicFramer::ParsePublicHeaderDispatcherShortHeaderLengthUnknown(
352 packet, &packet_info.form, &packet_info.long_packet_type,
353 &packet_info.version_flag, &packet_info.use_length_prefix,
354 &packet_info.version_label, &packet_info.version,
355 &packet_info.destination_connection_id, &packet_info.source_connection_id,
356 &packet_info.retry_token, &detailed_error, connection_id_generator_);
357
358 if (error != QUIC_NO_ERROR) {
359 // Packet has framing error.
360 SetLastError(error);
361 QUIC_DLOG(ERROR) << detailed_error;
362 return;
363 }
364 if (packet_info.destination_connection_id.length() !=
365 expected_server_connection_id_length_ &&
366 !should_update_expected_server_connection_id_length_ &&
367 packet_info.version.IsKnown() &&
368 !packet_info.version.AllowsVariableLengthConnectionIds()) {
369 SetLastError(QUIC_INVALID_PACKET_HEADER);
370 QUIC_DLOG(ERROR) << "Invalid Connection Id Length";
371 return;
372 }
373
374 if (packet_info.version_flag && IsSupportedVersion(packet_info.version)) {
375 if (!QuicUtils::IsConnectionIdValidForVersion(
376 packet_info.destination_connection_id,
377 packet_info.version.transport_version)) {
378 SetLastError(QUIC_INVALID_PACKET_HEADER);
379 QUIC_DLOG(ERROR)
380 << "Invalid destination connection ID length for version";
381 return;
382 }
383 if (packet_info.version.SupportsClientConnectionIds() &&
384 !QuicUtils::IsConnectionIdValidForVersion(
385 packet_info.source_connection_id,
386 packet_info.version.transport_version)) {
387 SetLastError(QUIC_INVALID_PACKET_HEADER);
388 QUIC_DLOG(ERROR) << "Invalid source connection ID length for version";
389 return;
390 }
391 }
392
393 // Before introducing the flag, it was impossible for a short header to
394 // update |expected_server_connection_id_length_|.
395 if (should_update_expected_server_connection_id_length_ &&
396 packet_info.version_flag) {
397 expected_server_connection_id_length_ =
398 packet_info.destination_connection_id.length();
399 }
400
401 if (MaybeDispatchPacket(packet_info)) {
402 // Packet has been dropped or successfully dispatched, stop processing.
403 return;
404 }
405 // The framer might have extracted the incorrect Connection ID length from a
406 // short header. |packet| could be gQUIC; if Q043, the connection ID has been
407 // parsed correctly thanks to the fixed bit. If a Q046 short header,
408 // the dispatcher might have assumed it was a long connection ID when (because
409 // it was gQUIC) it actually issued or kept an 8-byte ID. The other case is
410 // where NEW_CONNECTION_IDs are not using the generator, and the dispatcher
411 // is, due to flag misconfiguration.
412 if (!packet_info.version_flag &&
413 IsSupportedVersion(ParsedQuicVersion::Q046())) {
414 ReceivedPacketInfo gquic_packet_info(self_address, peer_address, packet);
415 // Try again without asking |connection_id_generator_| for the length.
416 const QuicErrorCode gquic_error = QuicFramer::ParsePublicHeaderDispatcher(
417 packet, expected_server_connection_id_length_, &gquic_packet_info.form,
418 &gquic_packet_info.long_packet_type, &gquic_packet_info.version_flag,
419 &gquic_packet_info.use_length_prefix, &gquic_packet_info.version_label,
420 &gquic_packet_info.version,
421 &gquic_packet_info.destination_connection_id,
422 &gquic_packet_info.source_connection_id, &gquic_packet_info.retry_token,
423 &detailed_error);
424 if (gquic_error == QUIC_NO_ERROR) {
425 if (MaybeDispatchPacket(gquic_packet_info)) {
426 return;
427 }
428 } else {
429 QUICHE_VLOG(1) << "Tried to parse short header as gQUIC packet: "
430 << detailed_error;
431 }
432 }
433 ProcessHeader(&packet_info);
434 }
435
436 namespace {
IsSourceUdpPortBlocked(uint16_t port)437 constexpr bool IsSourceUdpPortBlocked(uint16_t port) {
438 // These UDP source ports have been observed in large scale denial of service
439 // attacks and are not expected to ever carry user traffic, they are therefore
440 // blocked as a safety measure. See section 8.1 of RFC 9308 for details.
441 // https://www.rfc-editor.org/rfc/rfc9308.html#section-8.1
442 constexpr uint16_t blocked_ports[] = {
443 0, // We cannot send to port 0 so drop that source port.
444 17, // Quote of the Day, can loop with QUIC.
445 19, // Chargen, can loop with QUIC.
446 53, // DNS, vulnerable to reflection attacks.
447 111, // Portmap.
448 123, // NTP, vulnerable to reflection attacks.
449 137, // NETBIOS Name Service,
450 138, // NETBIOS Datagram Service
451 161, // SNMP.
452 389, // CLDAP.
453 500, // IKE, can loop with QUIC.
454 1900, // SSDP, vulnerable to reflection attacks.
455 3702, // WS-Discovery, vulnerable to reflection attacks.
456 5353, // mDNS, vulnerable to reflection attacks.
457 5355, // LLMNR, vulnerable to reflection attacks.
458 11211, // memcache, vulnerable to reflection attacks.
459 // This list MUST be sorted in increasing order.
460 };
461 constexpr size_t num_blocked_ports = ABSL_ARRAYSIZE(blocked_ports);
462 constexpr uint16_t highest_blocked_port =
463 blocked_ports[num_blocked_ports - 1];
464 if (ABSL_PREDICT_TRUE(port > highest_blocked_port)) {
465 // Early-return to skip comparisons for the majority of traffic.
466 return false;
467 }
468 for (size_t i = 0; i < num_blocked_ports; i++) {
469 if (port == blocked_ports[i]) {
470 return true;
471 }
472 }
473 return false;
474 }
475 } // namespace
476
MaybeDispatchPacket(const ReceivedPacketInfo & packet_info)477 bool QuicDispatcher::MaybeDispatchPacket(
478 const ReceivedPacketInfo& packet_info) {
479 if (IsSourceUdpPortBlocked(packet_info.peer_address.port())) {
480 // Silently drop the received packet.
481 QUIC_CODE_COUNT(quic_dropped_blocked_port);
482 return true;
483 }
484
485 const QuicConnectionId server_connection_id =
486 packet_info.destination_connection_id;
487
488 // The IETF spec requires the client to generate an initial server
489 // connection ID that is at least 64 bits long. After that initial
490 // connection ID, the dispatcher picks a new one of its expected length.
491 // Therefore we should never receive a connection ID that is smaller
492 // than 64 bits and smaller than what we expect. Unless the version is
493 // unknown, in which case we allow short connection IDs for version
494 // negotiation because that version could allow those.
495 if (packet_info.version_flag && packet_info.version.IsKnown() &&
496 IsServerConnectionIdTooShort(server_connection_id)) {
497 QUICHE_DCHECK(packet_info.version_flag);
498 QUICHE_DCHECK(packet_info.version.AllowsVariableLengthConnectionIds());
499 QUIC_DLOG(INFO) << "Packet with short destination connection ID "
500 << server_connection_id << " expected "
501 << static_cast<int>(expected_server_connection_id_length_);
502 // Drop the packet silently.
503 QUIC_CODE_COUNT(quic_dropped_invalid_small_initial_connection_id);
504 return true;
505 }
506
507 if (packet_info.version_flag && packet_info.version.IsKnown() &&
508 !QuicUtils::IsConnectionIdLengthValidForVersion(
509 server_connection_id.length(),
510 packet_info.version.transport_version)) {
511 QUIC_DLOG(INFO) << "Packet with destination connection ID "
512 << server_connection_id << " is invalid with version "
513 << packet_info.version;
514 // Drop the packet silently.
515 QUIC_CODE_COUNT(quic_dropped_invalid_initial_connection_id);
516 return true;
517 }
518
519 // Packets with connection IDs for active connections are processed
520 // immediately.
521 auto it = reference_counted_session_map_.find(server_connection_id);
522 if (it != reference_counted_session_map_.end()) {
523 QUICHE_DCHECK(!buffered_packets_.HasBufferedPackets(server_connection_id));
524 it->second->ProcessUdpPacket(packet_info.self_address,
525 packet_info.peer_address, packet_info.packet);
526 return true;
527 }
528
529 if (buffered_packets_.HasChloForConnection(server_connection_id)) {
530 BufferEarlyPacket(packet_info);
531 return true;
532 }
533
534 if (OnFailedToDispatchPacket(packet_info)) {
535 return true;
536 }
537
538 if (time_wait_list_manager_->IsConnectionIdInTimeWait(server_connection_id)) {
539 // This connection ID is already in time-wait state.
540 time_wait_list_manager_->ProcessPacket(
541 packet_info.self_address, packet_info.peer_address,
542 packet_info.destination_connection_id, packet_info.form,
543 packet_info.packet.length(), GetPerPacketContext());
544 return true;
545 }
546
547 // The packet has an unknown connection ID.
548 if (!accept_new_connections_ && packet_info.version_flag) {
549 // If not accepting new connections, reject packets with version which can
550 // potentially result in new connection creation. But if the packet doesn't
551 // have version flag, leave it to ValidityChecks() to reset it.
552 // By adding the connection to time wait list, following packets on this
553 // connection will not reach ShouldAcceptNewConnections().
554 StatelesslyTerminateConnection(
555 packet_info.self_address, packet_info.peer_address,
556 packet_info.destination_connection_id, packet_info.form,
557 packet_info.version_flag, packet_info.use_length_prefix,
558 packet_info.version, QUIC_HANDSHAKE_FAILED,
559 "Stop accepting new connections",
560 quic::QuicTimeWaitListManager::SEND_STATELESS_RESET);
561 // Time wait list will reject the packet correspondingly..
562 time_wait_list_manager()->ProcessPacket(
563 packet_info.self_address, packet_info.peer_address,
564 packet_info.destination_connection_id, packet_info.form,
565 packet_info.packet.length(), GetPerPacketContext());
566 OnNewConnectionRejected();
567 return true;
568 }
569
570 // Unless the packet provides a version, assume that we can continue
571 // processing using our preferred version.
572 if (packet_info.version_flag) {
573 if (!IsSupportedVersion(packet_info.version)) {
574 if (ShouldCreateSessionForUnknownVersion(packet_info)) {
575 return false;
576 }
577 // Since the version is not supported, send a version negotiation
578 // packet and stop processing the current packet.
579 MaybeSendVersionNegotiationPacket(packet_info);
580 return true;
581 }
582
583 if (crypto_config()->validate_chlo_size() &&
584 packet_info.form == IETF_QUIC_LONG_HEADER_PACKET &&
585 packet_info.long_packet_type == INITIAL &&
586 packet_info.packet.length() < kMinClientInitialPacketLength) {
587 QUIC_DVLOG(1) << "Dropping initial packet which is too short, length: "
588 << packet_info.packet.length();
589 QUIC_CODE_COUNT(quic_drop_small_initial_packets);
590 return true;
591 }
592 }
593
594 return false;
595 }
596
ProcessHeader(ReceivedPacketInfo * packet_info)597 void QuicDispatcher::ProcessHeader(ReceivedPacketInfo* packet_info) {
598 QuicConnectionId server_connection_id =
599 packet_info->destination_connection_id;
600 // Packet's connection ID is unknown. Apply the validity checks.
601 QuicPacketFate fate = ValidityChecks(*packet_info);
602
603 // |connection_close_error_code| is used if the final packet fate is
604 // kFateTimeWait.
605 QuicErrorCode connection_close_error_code = QUIC_HANDSHAKE_FAILED;
606
607 // If a fatal TLS alert was received when extracting Client Hello,
608 // |tls_alert_error_detail| will be set and will be used as the error_details
609 // of the connection close.
610 std::string tls_alert_error_detail;
611
612 if (fate == kFateProcess) {
613 ExtractChloResult extract_chlo_result =
614 TryExtractChloOrBufferEarlyPacket(*packet_info);
615 auto& parsed_chlo = extract_chlo_result.parsed_chlo;
616
617 if (extract_chlo_result.tls_alert.has_value()) {
618 QUIC_BUG_IF(quic_dispatcher_parsed_chlo_and_tls_alert_coexist_1,
619 parsed_chlo.has_value())
620 << "parsed_chlo and tls_alert should not be set at the same time.";
621 // Fatal TLS alert when parsing Client Hello.
622 fate = kFateTimeWait;
623 uint8_t tls_alert = *extract_chlo_result.tls_alert;
624 connection_close_error_code = TlsAlertToQuicErrorCode(tls_alert);
625 tls_alert_error_detail =
626 absl::StrCat("TLS handshake failure (",
627 EncryptionLevelToString(ENCRYPTION_INITIAL), ") ",
628 static_cast<int>(tls_alert), ": ",
629 SSL_alert_desc_string_long(tls_alert));
630 } else if (!parsed_chlo.has_value()) {
631 // Client Hello incomplete. Packet has been buffered or (rarely) dropped.
632 return;
633 } else {
634 // Client Hello fully received.
635 fate = ValidityChecksOnFullChlo(*packet_info, *parsed_chlo);
636
637 if (fate == kFateProcess) {
638 ProcessChlo(*std::move(parsed_chlo), packet_info);
639 return;
640 }
641 }
642 }
643
644 switch (fate) {
645 case kFateProcess:
646 // kFateProcess have been processed above.
647 QUIC_BUG(quic_dispatcher_bad_packet_fate) << fate;
648 break;
649 case kFateTimeWait: {
650 // Add this connection_id to the time-wait state, to safely reject
651 // future packets.
652 QUIC_DLOG(INFO) << "Adding connection ID " << server_connection_id
653 << " to time-wait list.";
654 QUIC_CODE_COUNT(quic_reject_fate_time_wait);
655 const std::string& connection_close_error_detail =
656 tls_alert_error_detail.empty() ? "Reject connection"
657 : tls_alert_error_detail;
658 StatelesslyTerminateConnection(
659 packet_info->self_address, packet_info->peer_address,
660 server_connection_id, packet_info->form, packet_info->version_flag,
661 packet_info->use_length_prefix, packet_info->version,
662 connection_close_error_code, connection_close_error_detail,
663 quic::QuicTimeWaitListManager::SEND_STATELESS_RESET);
664
665 QUICHE_DCHECK(time_wait_list_manager_->IsConnectionIdInTimeWait(
666 server_connection_id));
667 time_wait_list_manager_->ProcessPacket(
668 packet_info->self_address, packet_info->peer_address,
669 server_connection_id, packet_info->form, packet_info->packet.length(),
670 GetPerPacketContext());
671
672 buffered_packets_.DiscardPackets(server_connection_id);
673 } break;
674 case kFateDrop:
675 break;
676 }
677 }
678
679 QuicDispatcher::ExtractChloResult
TryExtractChloOrBufferEarlyPacket(const ReceivedPacketInfo & packet_info)680 QuicDispatcher::TryExtractChloOrBufferEarlyPacket(
681 const ReceivedPacketInfo& packet_info) {
682 ExtractChloResult result;
683 if (packet_info.version.UsesTls()) {
684 bool has_full_tls_chlo = false;
685 std::string sni;
686 std::vector<uint16_t> supported_groups;
687 std::vector<std::string> alpns;
688 bool resumption_attempted = false, early_data_attempted = false;
689 if (buffered_packets_.HasBufferedPackets(
690 packet_info.destination_connection_id)) {
691 // If we already have buffered packets for this connection ID,
692 // use the associated TlsChloExtractor to parse this packet.
693 has_full_tls_chlo = buffered_packets_.IngestPacketForTlsChloExtraction(
694 packet_info.destination_connection_id, packet_info.version,
695 packet_info.packet, &supported_groups, &alpns, &sni,
696 &resumption_attempted, &early_data_attempted, &result.tls_alert);
697 } else {
698 // If we do not have a BufferedPacketList for this connection ID,
699 // create a single-use one to check whether this packet contains a
700 // full single-packet CHLO.
701 TlsChloExtractor tls_chlo_extractor;
702 tls_chlo_extractor.IngestPacket(packet_info.version, packet_info.packet);
703 if (tls_chlo_extractor.HasParsedFullChlo()) {
704 // This packet contains a full single-packet CHLO.
705 has_full_tls_chlo = true;
706 supported_groups = tls_chlo_extractor.supported_groups();
707 alpns = tls_chlo_extractor.alpns();
708 sni = tls_chlo_extractor.server_name();
709 resumption_attempted = tls_chlo_extractor.resumption_attempted();
710 early_data_attempted = tls_chlo_extractor.early_data_attempted();
711 } else {
712 result.tls_alert = tls_chlo_extractor.tls_alert();
713 }
714 }
715
716 if (result.tls_alert.has_value()) {
717 QUIC_BUG_IF(quic_dispatcher_parsed_chlo_and_tls_alert_coexist_2,
718 has_full_tls_chlo)
719 << "parsed_chlo and tls_alert should not be set at the same time.";
720 return result;
721 }
722
723 if (GetQuicFlag(quic_allow_chlo_buffering) && !has_full_tls_chlo) {
724 // This packet does not contain a full CHLO. It could be a 0-RTT
725 // packet that arrived before the CHLO (due to loss or reordering),
726 // or it could be a fragment of a multi-packet CHLO.
727 BufferEarlyPacket(packet_info);
728 return result;
729 }
730
731 ParsedClientHello& parsed_chlo = result.parsed_chlo.emplace();
732 parsed_chlo.sni = std::move(sni);
733 parsed_chlo.supported_groups = std::move(supported_groups);
734 parsed_chlo.alpns = std::move(alpns);
735 if (packet_info.retry_token.has_value()) {
736 parsed_chlo.retry_token = std::string(*packet_info.retry_token);
737 }
738 parsed_chlo.resumption_attempted = resumption_attempted;
739 parsed_chlo.early_data_attempted = early_data_attempted;
740 return result;
741 }
742
743 ChloAlpnSniExtractor alpn_extractor;
744 if (GetQuicFlag(quic_allow_chlo_buffering) &&
745 !ChloExtractor::Extract(packet_info.packet, packet_info.version,
746 config_->create_session_tag_indicators(),
747 &alpn_extractor,
748 packet_info.destination_connection_id.length())) {
749 // Buffer non-CHLO packets.
750 BufferEarlyPacket(packet_info);
751 return result;
752 }
753
754 ParsedClientHello& parsed_chlo = result.parsed_chlo.emplace();
755 parsed_chlo.sni = alpn_extractor.ConsumeSni();
756 parsed_chlo.uaid = alpn_extractor.ConsumeUaid();
757 parsed_chlo.alpns = {alpn_extractor.ConsumeAlpn()};
758 return result;
759 }
760
SelectAlpn(const std::vector<std::string> & alpns)761 std::string QuicDispatcher::SelectAlpn(const std::vector<std::string>& alpns) {
762 if (alpns.empty()) {
763 return "";
764 }
765 if (alpns.size() > 1u) {
766 const std::vector<std::string>& supported_alpns =
767 version_manager_->GetSupportedAlpns();
768 for (const std::string& alpn : alpns) {
769 if (std::find(supported_alpns.begin(), supported_alpns.end(), alpn) !=
770 supported_alpns.end()) {
771 return alpn;
772 }
773 }
774 }
775 return alpns[0];
776 }
777
ValidityChecks(const ReceivedPacketInfo & packet_info)778 QuicDispatcher::QuicPacketFate QuicDispatcher::ValidityChecks(
779 const ReceivedPacketInfo& packet_info) {
780 if (!packet_info.version_flag) {
781 QUIC_DLOG(INFO)
782 << "Packet without version arrived for unknown connection ID "
783 << packet_info.destination_connection_id;
784 MaybeResetPacketsWithNoVersion(packet_info);
785 return kFateDrop;
786 }
787
788 // Let the connection parse and validate packet number.
789 return kFateProcess;
790 }
791
CleanUpSession(QuicConnectionId server_connection_id,QuicConnection * connection,QuicErrorCode,const std::string &,ConnectionCloseSource)792 void QuicDispatcher::CleanUpSession(QuicConnectionId server_connection_id,
793 QuicConnection* connection,
794 QuicErrorCode /*error*/,
795 const std::string& /*error_details*/,
796 ConnectionCloseSource /*source*/) {
797 write_blocked_list_.erase(connection);
798 QuicTimeWaitListManager::TimeWaitAction action =
799 QuicTimeWaitListManager::SEND_STATELESS_RESET;
800 if (connection->termination_packets() != nullptr &&
801 !connection->termination_packets()->empty()) {
802 action = QuicTimeWaitListManager::SEND_CONNECTION_CLOSE_PACKETS;
803 } else {
804 if (!connection->IsHandshakeComplete()) {
805 // TODO(fayang): Do not serialize connection close packet if the
806 // connection is closed by the client.
807 QUIC_CODE_COUNT(quic_v44_add_to_time_wait_list_with_handshake_failed);
808 // This serializes a connection close termination packet and adds the
809 // connection to the time wait list.
810 StatelessConnectionTerminator terminator(
811 server_connection_id,
812 connection->GetOriginalDestinationConnectionId(),
813 connection->version(), helper_.get(), time_wait_list_manager_.get());
814 terminator.CloseConnection(
815 QUIC_HANDSHAKE_FAILED,
816 "Connection is closed by server before handshake confirmed",
817 /*ietf_quic=*/true, connection->GetActiveServerConnectionIds());
818 return;
819 }
820 QUIC_CODE_COUNT(quic_v44_add_to_time_wait_list_with_stateless_reset);
821 }
822 time_wait_list_manager_->AddConnectionIdToTimeWait(
823 action,
824 TimeWaitConnectionInfo(
825 /*ietf_quic=*/true, connection->termination_packets(),
826 connection->GetActiveServerConnectionIds(),
827 connection->sent_packet_manager().GetRttStats()->smoothed_rtt()));
828 }
829
StartAcceptingNewConnections()830 void QuicDispatcher::StartAcceptingNewConnections() {
831 accept_new_connections_ = true;
832 }
833
StopAcceptingNewConnections()834 void QuicDispatcher::StopAcceptingNewConnections() {
835 accept_new_connections_ = false;
836 // No more CHLO will arrive and buffered CHLOs shouldn't be able to create
837 // connections.
838 buffered_packets_.DiscardAllPackets();
839 }
840
PerformActionOnActiveSessions(quiche::UnretainedCallback<void (QuicSession *)> operation) const841 void QuicDispatcher::PerformActionOnActiveSessions(
842 quiche::UnretainedCallback<void(QuicSession*)> operation) const {
843 absl::flat_hash_set<QuicSession*> visited_session;
844 visited_session.reserve(reference_counted_session_map_.size());
845 for (auto const& kv : reference_counted_session_map_) {
846 QuicSession* session = kv.second.get();
847 if (visited_session.insert(session).second) {
848 operation(session);
849 }
850 }
851 }
852
853 // Get a snapshot of all sessions.
GetSessionsSnapshot() const854 std::vector<std::shared_ptr<QuicSession>> QuicDispatcher::GetSessionsSnapshot()
855 const {
856 std::vector<std::shared_ptr<QuicSession>> snapshot;
857 snapshot.reserve(reference_counted_session_map_.size());
858 absl::flat_hash_set<QuicSession*> visited_session;
859 visited_session.reserve(reference_counted_session_map_.size());
860 for (auto const& kv : reference_counted_session_map_) {
861 QuicSession* session = kv.second.get();
862 if (visited_session.insert(session).second) {
863 snapshot.push_back(kv.second);
864 }
865 }
866 return snapshot;
867 }
868
GetPerPacketContext() const869 std::unique_ptr<QuicPerPacketContext> QuicDispatcher::GetPerPacketContext()
870 const {
871 return nullptr;
872 }
873
DeleteSessions()874 void QuicDispatcher::DeleteSessions() {
875 if (!write_blocked_list_.empty()) {
876 for (const auto& session : closed_session_list_) {
877 if (write_blocked_list_.erase(session->connection()) != 0) {
878 QUIC_BUG(quic_bug_12724_2)
879 << "QuicConnection was in WriteBlockedList before destruction "
880 << session->connection()->connection_id();
881 }
882 }
883 }
884 closed_session_list_.clear();
885 }
886
ClearStatelessResetAddresses()887 void QuicDispatcher::ClearStatelessResetAddresses() {
888 recent_stateless_reset_addresses_.clear();
889 }
890
OnCanWrite()891 void QuicDispatcher::OnCanWrite() {
892 // The socket is now writable.
893 writer_->SetWritable();
894
895 // Move every blocked writer in |write_blocked_list_| to a temporary list.
896 const size_t num_blocked_writers_before = write_blocked_list_.size();
897 WriteBlockedList temp_list;
898 temp_list.swap(write_blocked_list_);
899 QUICHE_DCHECK(write_blocked_list_.empty());
900
901 // Give each blocked writer a chance to write what they intended to write.
902 // If they are blocked again, they will call |OnWriteBlocked| to add
903 // themselves back into |write_blocked_list_|.
904 while (!temp_list.empty()) {
905 QuicBlockedWriterInterface* blocked_writer = temp_list.begin()->first;
906 temp_list.erase(temp_list.begin());
907 blocked_writer->OnBlockedWriterCanWrite();
908 }
909 const size_t num_blocked_writers_after = write_blocked_list_.size();
910 if (num_blocked_writers_after != 0) {
911 if (num_blocked_writers_before == num_blocked_writers_after) {
912 QUIC_CODE_COUNT(quic_zero_progress_on_can_write);
913 } else {
914 QUIC_CODE_COUNT(quic_blocked_again_on_can_write);
915 }
916 }
917 }
918
HasPendingWrites() const919 bool QuicDispatcher::HasPendingWrites() const {
920 return !write_blocked_list_.empty();
921 }
922
Shutdown()923 void QuicDispatcher::Shutdown() {
924 while (!reference_counted_session_map_.empty()) {
925 QuicSession* session = reference_counted_session_map_.begin()->second.get();
926 session->connection()->CloseConnection(
927 QUIC_PEER_GOING_AWAY, "Server shutdown imminent",
928 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
929 // Validate that the session removes itself from the session map on close.
930 QUICHE_DCHECK(reference_counted_session_map_.empty() ||
931 reference_counted_session_map_.begin()->second.get() !=
932 session);
933 }
934 DeleteSessions();
935 }
936
OnConnectionClosed(QuicConnectionId server_connection_id,QuicErrorCode error,const std::string & error_details,ConnectionCloseSource source)937 void QuicDispatcher::OnConnectionClosed(QuicConnectionId server_connection_id,
938 QuicErrorCode error,
939 const std::string& error_details,
940 ConnectionCloseSource source) {
941 auto it = reference_counted_session_map_.find(server_connection_id);
942 if (it == reference_counted_session_map_.end()) {
943 QUIC_BUG(quic_bug_10287_3) << "ConnectionId " << server_connection_id
944 << " does not exist in the session map. Error: "
945 << QuicErrorCodeToString(error);
946 QUIC_BUG(quic_bug_10287_4) << QuicStackTrace();
947 return;
948 }
949
950 QUIC_DLOG_IF(INFO, error != QUIC_NO_ERROR)
951 << "Closing connection (" << server_connection_id
952 << ") due to error: " << QuicErrorCodeToString(error)
953 << ", with details: " << error_details;
954
955 const QuicSession* session = it->second.get();
956 QuicConnection* connection = it->second->connection();
957 // Set up alarm to fire immediately to bring destruction of this session
958 // out of current call stack.
959 if (closed_session_list_.empty()) {
960 delete_sessions_alarm_->Update(helper()->GetClock()->ApproximateNow(),
961 QuicTime::Delta::Zero());
962 }
963 closed_session_list_.push_back(std::move(it->second));
964 CleanUpSession(it->first, connection, error, error_details, source);
965 bool session_removed = false;
966 for (const QuicConnectionId& cid :
967 connection->GetActiveServerConnectionIds()) {
968 auto it1 = reference_counted_session_map_.find(cid);
969 if (it1 != reference_counted_session_map_.end()) {
970 const QuicSession* session2 = it1->second.get();
971 // For cid == server_connection_id, session2 is a nullptr (and hence
972 // session2 != session) now since we have std::move the session into
973 // closed_session_list_ above.
974 if (session2 == session || cid == server_connection_id) {
975 reference_counted_session_map_.erase(it1);
976 session_removed = true;
977 } else {
978 // Leave this session in the map.
979 QUIC_BUG(quic_dispatcher_session_mismatch)
980 << "Session is mismatched in the map. server_connection_id: "
981 << server_connection_id << ". Current cid: " << cid
982 << ". Cid of the other session "
983 << (session2 == nullptr
984 ? "null"
985 : session2->connection()->connection_id().ToString());
986 }
987 } else {
988 // GetActiveServerConnectionIds might return the original destination
989 // ID, which is not contained in the session map.
990 QUIC_BUG_IF(quic_dispatcher_session_not_found,
991 cid != connection->GetOriginalDestinationConnectionId())
992 << "Missing session for cid " << cid
993 << ". server_connection_id: " << server_connection_id;
994 }
995 }
996 QUIC_BUG_IF(quic_session_is_not_removed, !session_removed);
997 --num_sessions_in_session_map_;
998 }
999
OnWriteBlocked(QuicBlockedWriterInterface * blocked_writer)1000 void QuicDispatcher::OnWriteBlocked(
1001 QuicBlockedWriterInterface* blocked_writer) {
1002 if (!blocked_writer->IsWriterBlocked()) {
1003 // It is a programming error if this ever happens. When we are sure it is
1004 // not happening, replace it with a QUICHE_DCHECK.
1005 QUIC_BUG(quic_bug_12724_4)
1006 << "Tried to add writer into blocked list when it shouldn't be added";
1007 // Return without adding the connection to the blocked list, to avoid
1008 // infinite loops in OnCanWrite.
1009 return;
1010 }
1011
1012 write_blocked_list_.insert(std::make_pair(blocked_writer, true));
1013 }
1014
OnRstStreamReceived(const QuicRstStreamFrame &)1015 void QuicDispatcher::OnRstStreamReceived(const QuicRstStreamFrame& /*frame*/) {}
1016
OnStopSendingReceived(const QuicStopSendingFrame &)1017 void QuicDispatcher::OnStopSendingReceived(
1018 const QuicStopSendingFrame& /*frame*/) {}
1019
TryAddNewConnectionId(const QuicConnectionId & server_connection_id,const QuicConnectionId & new_connection_id)1020 bool QuicDispatcher::TryAddNewConnectionId(
1021 const QuicConnectionId& server_connection_id,
1022 const QuicConnectionId& new_connection_id) {
1023 auto it = reference_counted_session_map_.find(server_connection_id);
1024 if (it == reference_counted_session_map_.end()) {
1025 QUIC_BUG(quic_bug_10287_7)
1026 << "Couldn't locate the session that issues the connection ID in "
1027 "reference_counted_session_map_. server_connection_id:"
1028 << server_connection_id << " new_connection_id: " << new_connection_id;
1029 return false;
1030 }
1031 auto insertion_result = reference_counted_session_map_.insert(
1032 std::make_pair(new_connection_id, it->second));
1033 if (!insertion_result.second) {
1034 QUIC_CODE_COUNT(quic_cid_already_in_session_map);
1035 }
1036 return insertion_result.second;
1037 }
1038
OnConnectionIdRetired(const QuicConnectionId & server_connection_id)1039 void QuicDispatcher::OnConnectionIdRetired(
1040 const QuicConnectionId& server_connection_id) {
1041 reference_counted_session_map_.erase(server_connection_id);
1042 }
1043
OnConnectionAddedToTimeWaitList(QuicConnectionId server_connection_id)1044 void QuicDispatcher::OnConnectionAddedToTimeWaitList(
1045 QuicConnectionId server_connection_id) {
1046 QUIC_DLOG(INFO) << "Connection " << server_connection_id
1047 << " added to time wait list.";
1048 }
1049
StatelesslyTerminateConnection(const QuicSocketAddress & self_address,const QuicSocketAddress & peer_address,QuicConnectionId server_connection_id,PacketHeaderFormat format,bool version_flag,bool use_length_prefix,ParsedQuicVersion version,QuicErrorCode error_code,const std::string & error_details,QuicTimeWaitListManager::TimeWaitAction action)1050 void QuicDispatcher::StatelesslyTerminateConnection(
1051 const QuicSocketAddress& self_address,
1052 const QuicSocketAddress& peer_address,
1053 QuicConnectionId server_connection_id, PacketHeaderFormat format,
1054 bool version_flag, bool use_length_prefix, ParsedQuicVersion version,
1055 QuicErrorCode error_code, const std::string& error_details,
1056 QuicTimeWaitListManager::TimeWaitAction action) {
1057 if (format != IETF_QUIC_LONG_HEADER_PACKET && !version_flag) {
1058 QUIC_DVLOG(1) << "Statelessly terminating " << server_connection_id
1059 << " based on a non-ietf-long packet, action:" << action
1060 << ", error_code:" << error_code
1061 << ", error_details:" << error_details;
1062 time_wait_list_manager_->AddConnectionIdToTimeWait(
1063 action, TimeWaitConnectionInfo(format != GOOGLE_QUIC_PACKET, nullptr,
1064 {server_connection_id}));
1065 return;
1066 }
1067
1068 // If the version is known and supported by framer, send a connection close.
1069 if (IsSupportedVersion(version)) {
1070 QUIC_DVLOG(1)
1071 << "Statelessly terminating " << server_connection_id
1072 << " based on an ietf-long packet, which has a supported version:"
1073 << version << ", error_code:" << error_code
1074 << ", error_details:" << error_details;
1075
1076 StatelessConnectionTerminator terminator(
1077 server_connection_id, server_connection_id, version, helper_.get(),
1078 time_wait_list_manager_.get());
1079 // This also adds the connection to time wait list.
1080 terminator.CloseConnection(
1081 error_code, error_details, format != GOOGLE_QUIC_PACKET,
1082 /*active_connection_ids=*/{server_connection_id});
1083 QUIC_CODE_COUNT(quic_dispatcher_generated_connection_close);
1084 QuicSession::RecordConnectionCloseAtServer(
1085 error_code, ConnectionCloseSource::FROM_SELF);
1086 OnStatelessConnectionCloseGenerated(self_address, peer_address,
1087 server_connection_id, version,
1088 error_code, error_details);
1089 return;
1090 }
1091
1092 QUIC_DVLOG(1)
1093 << "Statelessly terminating " << server_connection_id
1094 << " based on an ietf-long packet, which has an unsupported version:"
1095 << version << ", error_code:" << error_code
1096 << ", error_details:" << error_details;
1097 // Version is unknown or unsupported by framer, send a version negotiation
1098 // with an empty version list, which can be understood by the client.
1099 std::vector<std::unique_ptr<QuicEncryptedPacket>> termination_packets;
1100 termination_packets.push_back(QuicFramer::BuildVersionNegotiationPacket(
1101 server_connection_id, EmptyQuicConnectionId(),
1102 /*ietf_quic=*/format != GOOGLE_QUIC_PACKET, use_length_prefix,
1103 /*versions=*/{}));
1104 time_wait_list_manager()->AddConnectionIdToTimeWait(
1105 QuicTimeWaitListManager::SEND_TERMINATION_PACKETS,
1106 TimeWaitConnectionInfo(/*ietf_quic=*/format != GOOGLE_QUIC_PACKET,
1107 &termination_packets, {server_connection_id}));
1108 }
1109
ShouldCreateSessionForUnknownVersion(const ReceivedPacketInfo &)1110 bool QuicDispatcher::ShouldCreateSessionForUnknownVersion(
1111 const ReceivedPacketInfo& /*packet_info*/) {
1112 return false;
1113 }
1114
OnExpiredPackets(QuicConnectionId server_connection_id,BufferedPacketList early_arrived_packets)1115 void QuicDispatcher::OnExpiredPackets(
1116 QuicConnectionId server_connection_id,
1117 BufferedPacketList early_arrived_packets) {
1118 QUIC_CODE_COUNT(quic_reject_buffered_packets_expired);
1119 QuicErrorCode error_code = QUIC_HANDSHAKE_FAILED;
1120 if (GetQuicReloadableFlag(
1121 quic_new_error_code_when_packets_buffered_too_long)) {
1122 QUIC_RELOADABLE_FLAG_COUNT(
1123 quic_new_error_code_when_packets_buffered_too_long);
1124 error_code = QUIC_HANDSHAKE_FAILED_PACKETS_BUFFERED_TOO_LONG;
1125 }
1126 QuicSocketAddress self_address, peer_address;
1127 if (!early_arrived_packets.buffered_packets.empty()) {
1128 self_address = early_arrived_packets.buffered_packets.front().self_address;
1129 peer_address = early_arrived_packets.buffered_packets.front().peer_address;
1130 }
1131 StatelesslyTerminateConnection(
1132 self_address, peer_address, server_connection_id,
1133 early_arrived_packets.ietf_quic ? IETF_QUIC_LONG_HEADER_PACKET
1134 : GOOGLE_QUIC_PACKET,
1135 /*version_flag=*/true,
1136 early_arrived_packets.version.HasLengthPrefixedConnectionIds(),
1137 early_arrived_packets.version, error_code,
1138 "Packets buffered for too long",
1139 quic::QuicTimeWaitListManager::SEND_STATELESS_RESET);
1140 }
1141
ProcessBufferedChlos(size_t max_connections_to_create)1142 void QuicDispatcher::ProcessBufferedChlos(size_t max_connections_to_create) {
1143 // Reset the counter before starting creating connections.
1144 new_sessions_allowed_per_event_loop_ = max_connections_to_create;
1145 for (; new_sessions_allowed_per_event_loop_ > 0;
1146 --new_sessions_allowed_per_event_loop_) {
1147 QuicConnectionId server_connection_id;
1148 BufferedPacketList packet_list =
1149 buffered_packets_.DeliverPacketsForNextConnection(
1150 &server_connection_id);
1151 const std::list<BufferedPacket>& packets = packet_list.buffered_packets;
1152 if (packets.empty()) {
1153 return;
1154 }
1155 if (!packet_list.parsed_chlo.has_value()) {
1156 QUIC_BUG(quic_dispatcher_no_parsed_chlo_in_buffered_packets)
1157 << "Buffered connection has no CHLO. connection_id:"
1158 << server_connection_id;
1159 continue;
1160 }
1161 auto session_ptr = CreateSessionFromChlo(
1162 server_connection_id, *packet_list.parsed_chlo, packet_list.version,
1163 packets.front().self_address, packets.front().peer_address,
1164 packet_list.connection_id_generator);
1165 if (session_ptr != nullptr) {
1166 DeliverPacketsToSession(packets, session_ptr.get());
1167 }
1168 }
1169 }
1170
HasChlosBuffered() const1171 bool QuicDispatcher::HasChlosBuffered() const {
1172 return buffered_packets_.HasChlosBuffered();
1173 }
1174
1175 // Return true if there is any packet buffered in the store.
HasBufferedPackets(QuicConnectionId server_connection_id)1176 bool QuicDispatcher::HasBufferedPackets(QuicConnectionId server_connection_id) {
1177 return buffered_packets_.HasBufferedPackets(server_connection_id);
1178 }
1179
OnBufferPacketFailure(EnqueuePacketResult result,QuicConnectionId server_connection_id)1180 void QuicDispatcher::OnBufferPacketFailure(
1181 EnqueuePacketResult result, QuicConnectionId server_connection_id) {
1182 QUIC_DLOG(INFO) << "Fail to buffer packet on connection "
1183 << server_connection_id << " because of " << result;
1184 }
1185
CreateQuicTimeWaitListManager()1186 QuicTimeWaitListManager* QuicDispatcher::CreateQuicTimeWaitListManager() {
1187 return new QuicTimeWaitListManager(writer_.get(), this, helper_->GetClock(),
1188 alarm_factory_.get());
1189 }
1190
BufferEarlyPacket(const ReceivedPacketInfo & packet_info)1191 void QuicDispatcher::BufferEarlyPacket(const ReceivedPacketInfo& packet_info) {
1192 // The connection ID generator will only be set for CHLOs, not for early
1193 // packets.
1194 EnqueuePacketResult rs = buffered_packets_.EnqueuePacket(
1195 packet_info.destination_connection_id,
1196 packet_info.form != GOOGLE_QUIC_PACKET, packet_info.packet,
1197 packet_info.self_address, packet_info.peer_address, packet_info.version,
1198 /*parsed_chlo=*/std::nullopt, /*connection_id_generator=*/nullptr);
1199 if (rs != EnqueuePacketResult::SUCCESS) {
1200 OnBufferPacketFailure(rs, packet_info.destination_connection_id);
1201 }
1202 }
1203
ProcessChlo(ParsedClientHello parsed_chlo,ReceivedPacketInfo * packet_info)1204 void QuicDispatcher::ProcessChlo(ParsedClientHello parsed_chlo,
1205 ReceivedPacketInfo* packet_info) {
1206 if (GetQuicFlag(quic_allow_chlo_buffering) &&
1207 new_sessions_allowed_per_event_loop_ <= 0) {
1208 // Can't create new session any more. Wait till next event loop.
1209 QUIC_BUG_IF(quic_bug_12724_7, buffered_packets_.HasChloForConnection(
1210 packet_info->destination_connection_id));
1211 EnqueuePacketResult rs = buffered_packets_.EnqueuePacket(
1212 packet_info->destination_connection_id,
1213 packet_info->form != GOOGLE_QUIC_PACKET, packet_info->packet,
1214 packet_info->self_address, packet_info->peer_address,
1215 packet_info->version, std::move(parsed_chlo), &ConnectionIdGenerator());
1216 if (rs != EnqueuePacketResult::SUCCESS) {
1217 OnBufferPacketFailure(rs, packet_info->destination_connection_id);
1218 }
1219 return;
1220 }
1221
1222 auto session_ptr = CreateSessionFromChlo(
1223 packet_info->destination_connection_id, parsed_chlo, packet_info->version,
1224 packet_info->self_address, packet_info->peer_address,
1225 &ConnectionIdGenerator());
1226 if (session_ptr == nullptr) {
1227 return;
1228 }
1229 std::list<BufferedPacket> packets =
1230 buffered_packets_.DeliverPackets(packet_info->destination_connection_id)
1231 .buffered_packets;
1232 if (packet_info->destination_connection_id != session_ptr->connection_id()) {
1233 // Provide the calling function with access to the new connection ID.
1234 packet_info->destination_connection_id = session_ptr->connection_id();
1235 if (!packets.empty()) {
1236 QUIC_CODE_COUNT(
1237 quic_delivered_buffered_packets_to_connection_with_replaced_id);
1238 }
1239 }
1240 // Process CHLO at first.
1241 session_ptr->ProcessUdpPacket(packet_info->self_address,
1242 packet_info->peer_address, packet_info->packet);
1243 // Deliver queued-up packets in the same order as they arrived.
1244 // Do this even when flag is off because there might be still some packets
1245 // buffered in the store before flag is turned off.
1246 DeliverPacketsToSession(packets, session_ptr.get());
1247 --new_sessions_allowed_per_event_loop_;
1248 }
1249
SetLastError(QuicErrorCode error)1250 void QuicDispatcher::SetLastError(QuicErrorCode error) { last_error_ = error; }
1251
OnFailedToDispatchPacket(const ReceivedPacketInfo &)1252 bool QuicDispatcher::OnFailedToDispatchPacket(
1253 const ReceivedPacketInfo& /*packet_info*/) {
1254 return false;
1255 }
1256
GetSupportedVersions()1257 const ParsedQuicVersionVector& QuicDispatcher::GetSupportedVersions() {
1258 return version_manager_->GetSupportedVersions();
1259 }
1260
DeliverPacketsToSession(const std::list<BufferedPacket> & packets,QuicSession * session)1261 void QuicDispatcher::DeliverPacketsToSession(
1262 const std::list<BufferedPacket>& packets, QuicSession* session) {
1263 for (const BufferedPacket& packet : packets) {
1264 session->ProcessUdpPacket(packet.self_address, packet.peer_address,
1265 *(packet.packet));
1266 }
1267 }
1268
IsSupportedVersion(const ParsedQuicVersion version)1269 bool QuicDispatcher::IsSupportedVersion(const ParsedQuicVersion version) {
1270 for (const ParsedQuicVersion& supported_version :
1271 version_manager_->GetSupportedVersions()) {
1272 if (version == supported_version) {
1273 return true;
1274 }
1275 }
1276 return false;
1277 }
1278
IsServerConnectionIdTooShort(QuicConnectionId connection_id) const1279 bool QuicDispatcher::IsServerConnectionIdTooShort(
1280 QuicConnectionId connection_id) const {
1281 if (connection_id.length() >= kQuicMinimumInitialConnectionIdLength ||
1282 connection_id.length() >= expected_server_connection_id_length_ ||
1283 allow_short_initial_server_connection_ids_) {
1284 return false;
1285 }
1286 uint8_t generator_output =
1287 connection_id.IsEmpty()
1288 ? connection_id_generator_.ConnectionIdLength(0x00)
1289 : connection_id_generator_.ConnectionIdLength(
1290 static_cast<uint8_t>(*connection_id.data()));
1291 return connection_id.length() < generator_output;
1292 }
1293
CreateSessionFromChlo(const QuicConnectionId original_connection_id,const ParsedClientHello & parsed_chlo,const ParsedQuicVersion version,const QuicSocketAddress self_address,const QuicSocketAddress peer_address,ConnectionIdGeneratorInterface * connection_id_generator)1294 std::shared_ptr<QuicSession> QuicDispatcher::CreateSessionFromChlo(
1295 const QuicConnectionId original_connection_id,
1296 const ParsedClientHello& parsed_chlo, const ParsedQuicVersion version,
1297 const QuicSocketAddress self_address, const QuicSocketAddress peer_address,
1298 ConnectionIdGeneratorInterface* connection_id_generator) {
1299 if (connection_id_generator == nullptr) {
1300 connection_id_generator = &ConnectionIdGenerator();
1301 }
1302 std::optional<QuicConnectionId> server_connection_id =
1303 connection_id_generator->MaybeReplaceConnectionId(original_connection_id,
1304 version);
1305 const bool replaced_connection_id = server_connection_id.has_value();
1306 if (!replaced_connection_id) {
1307 server_connection_id = original_connection_id;
1308 }
1309 QUIC_CODE_COUNT(quic_connection_id_chosen);
1310 if (reference_counted_session_map_.count(*server_connection_id) > 0) {
1311 // The new connection ID is owned by another session. Avoid creating one
1312 // altogether, as this connection attempt cannot possibly succeed.
1313 QUIC_CODE_COUNT(quic_connection_id_collision);
1314 QuicConnection* other_connection =
1315 reference_counted_session_map_[*server_connection_id]->connection();
1316 if (other_connection != nullptr) { // Just make sure there is no crash.
1317 QUIC_LOG_EVERY_N_SEC(ERROR, 10)
1318 << "QUIC Connection ID collision. original_connection_id:"
1319 << original_connection_id.ToString()
1320 << " server_connection_id:" << server_connection_id->ToString()
1321 << ", version:" << version << ", self_address:" << self_address
1322 << ", peer_address:" << peer_address
1323 << ", parsed_chlo:" << parsed_chlo
1324 << ", other peer address: " << other_connection->peer_address();
1325 }
1326 if (replaced_connection_id) {
1327 QUIC_CODE_COUNT(quic_replaced_connection_id_collision);
1328 // The original connection ID does not correspond to an existing
1329 // session. It is safe to send CONNECTION_CLOSE and add to TIME_WAIT.
1330 StatelesslyTerminateConnection(
1331 self_address, peer_address, original_connection_id,
1332 IETF_QUIC_LONG_HEADER_PACKET,
1333 /*version_flag=*/true, version.HasLengthPrefixedConnectionIds(),
1334 version, QUIC_HANDSHAKE_FAILED,
1335 "Connection ID collision, please retry",
1336 QuicTimeWaitListManager::SEND_CONNECTION_CLOSE_PACKETS);
1337 }
1338 return nullptr;
1339 }
1340 // Creates a new session and process all buffered packets for this connection.
1341 std::string alpn = SelectAlpn(parsed_chlo.alpns);
1342 std::unique_ptr<QuicSession> session =
1343 CreateQuicSession(*server_connection_id, self_address, peer_address, alpn,
1344 version, parsed_chlo, *connection_id_generator);
1345 if (ABSL_PREDICT_FALSE(session == nullptr)) {
1346 QUIC_BUG(quic_bug_10287_8)
1347 << "CreateQuicSession returned nullptr for " << *server_connection_id
1348 << " from " << peer_address << " to " << self_address << " ALPN \""
1349 << alpn << "\" version " << version;
1350 return nullptr;
1351 }
1352
1353 if (replaced_connection_id) {
1354 session->connection()->SetOriginalDestinationConnectionId(
1355 original_connection_id);
1356 }
1357 QUIC_DLOG(INFO) << "Created new session for " << *server_connection_id;
1358
1359 auto insertion_result = reference_counted_session_map_.insert(std::make_pair(
1360 *server_connection_id, std::shared_ptr<QuicSession>(std::move(session))));
1361 std::shared_ptr<QuicSession> session_ptr = insertion_result.first->second;
1362 if (!insertion_result.second) {
1363 QUIC_BUG(quic_bug_10287_9)
1364 << "Tried to add a session to session_map with existing "
1365 "connection id: "
1366 << *server_connection_id;
1367 } else {
1368 ++num_sessions_in_session_map_;
1369 if (replaced_connection_id) {
1370 auto insertion_result2 = reference_counted_session_map_.insert(
1371 std::make_pair(original_connection_id, session_ptr));
1372 QUIC_BUG_IF(quic_460317833_02, !insertion_result2.second)
1373 << "Original connection ID already in session_map: "
1374 << original_connection_id;
1375 // If insertion of the original connection ID fails, it might cause
1376 // loss of 0-RTT and other first flight packets, but the connection
1377 // will usually progress.
1378 }
1379 }
1380 return session_ptr;
1381 }
1382
MaybeResetPacketsWithNoVersion(const ReceivedPacketInfo & packet_info)1383 void QuicDispatcher::MaybeResetPacketsWithNoVersion(
1384 const ReceivedPacketInfo& packet_info) {
1385 QUICHE_DCHECK(!packet_info.version_flag);
1386 // Do not send a stateless reset if a reset has been sent to this address
1387 // recently.
1388 if (recent_stateless_reset_addresses_.contains(packet_info.peer_address)) {
1389 QUIC_CODE_COUNT(quic_donot_send_reset_repeatedly);
1390 return;
1391 }
1392 if (packet_info.form != GOOGLE_QUIC_PACKET) {
1393 // Drop IETF packets smaller than the minimal stateless reset length.
1394 if (packet_info.packet.length() <=
1395 QuicFramer::GetMinStatelessResetPacketLength()) {
1396 QUIC_CODE_COUNT(quic_drop_too_small_short_header_packets);
1397 return;
1398 }
1399 } else {
1400 const size_t MinValidPacketLength =
1401 kPacketHeaderTypeSize + expected_server_connection_id_length_ +
1402 PACKET_1BYTE_PACKET_NUMBER + /*payload size=*/1 + /*tag size=*/12;
1403 if (packet_info.packet.length() < MinValidPacketLength) {
1404 // The packet size is too small.
1405 QUIC_CODE_COUNT(drop_too_small_packets);
1406 return;
1407 }
1408 }
1409 // Do not send a stateless reset if there are too many stateless reset
1410 // addresses.
1411 if (recent_stateless_reset_addresses_.size() >=
1412 GetQuicFlag(quic_max_recent_stateless_reset_addresses)) {
1413 QUIC_CODE_COUNT(quic_too_many_recent_reset_addresses);
1414 return;
1415 }
1416 if (recent_stateless_reset_addresses_.empty()) {
1417 clear_stateless_reset_addresses_alarm_->Update(
1418 helper()->GetClock()->ApproximateNow() +
1419 QuicTime::Delta::FromMilliseconds(
1420 GetQuicFlag(quic_recent_stateless_reset_addresses_lifetime_ms)),
1421 QuicTime::Delta::Zero());
1422 }
1423 recent_stateless_reset_addresses_.emplace(packet_info.peer_address);
1424
1425 time_wait_list_manager()->SendPublicReset(
1426 packet_info.self_address, packet_info.peer_address,
1427 packet_info.destination_connection_id,
1428 packet_info.form != GOOGLE_QUIC_PACKET, packet_info.packet.length(),
1429 GetPerPacketContext());
1430 }
1431
MaybeSendVersionNegotiationPacket(const ReceivedPacketInfo & packet_info)1432 void QuicDispatcher::MaybeSendVersionNegotiationPacket(
1433 const ReceivedPacketInfo& packet_info) {
1434 if (crypto_config()->validate_chlo_size() &&
1435 packet_info.packet.length() < kMinPacketSizeForVersionNegotiation) {
1436 return;
1437 }
1438 time_wait_list_manager()->SendVersionNegotiationPacket(
1439 packet_info.destination_connection_id, packet_info.source_connection_id,
1440 packet_info.form != GOOGLE_QUIC_PACKET, packet_info.use_length_prefix,
1441 GetSupportedVersions(), packet_info.self_address,
1442 packet_info.peer_address, GetPerPacketContext());
1443 }
1444
NumSessions() const1445 size_t QuicDispatcher::NumSessions() const {
1446 return num_sessions_in_session_map_;
1447 }
1448
1449 } // namespace quic
1450