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