blob: ea2450d8b1492024ca2b2ac5e828dfebabbf5a75 [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// 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 "net/third_party/quiche/src/quic/core/quic_dispatcher.h"
6
vasilvv872e7a32019-03-12 16:42:44 -07007#include <string>
QUICHE teama6ef0a62019-03-07 20:34:33 -05008#include <utility>
9
QUICHE teama6ef0a62019-03-07 20:34:33 -050010#include "net/third_party/quiche/src/quic/core/chlo_extractor.h"
11#include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
12#include "net/third_party/quiche/src/quic/core/crypto/quic_random.h"
fayangccbab732019-05-13 10:11:25 -070013#include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050014#include "net/third_party/quiche/src/quic/core/quic_time_wait_list_manager.h"
15#include "net/third_party/quiche/src/quic/core/quic_types.h"
16#include "net/third_party/quiche/src/quic/core/quic_utils.h"
17#include "net/third_party/quiche/src/quic/core/stateless_rejector.h"
18#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
19#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
20#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
21#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
22#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
23#include "net/third_party/quiche/src/quic/platform/api/quic_stack_trace.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050024#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
25
26namespace quic {
27
28typedef QuicBufferedPacketStore::BufferedPacket BufferedPacket;
29typedef QuicBufferedPacketStore::BufferedPacketList BufferedPacketList;
30typedef QuicBufferedPacketStore::EnqueuePacketResult EnqueuePacketResult;
31
32namespace {
33
34// An alarm that informs the QuicDispatcher to delete old sessions.
35class DeleteSessionsAlarm : public QuicAlarm::Delegate {
36 public:
37 explicit DeleteSessionsAlarm(QuicDispatcher* dispatcher)
38 : dispatcher_(dispatcher) {}
39 DeleteSessionsAlarm(const DeleteSessionsAlarm&) = delete;
40 DeleteSessionsAlarm& operator=(const DeleteSessionsAlarm&) = delete;
41
42 void OnAlarm() override { dispatcher_->DeleteSessions(); }
43
44 private:
45 // Not owned.
46 QuicDispatcher* dispatcher_;
47};
48
49// Collects packets serialized by a QuicPacketCreator in order
50// to be handed off to the time wait list manager.
51class PacketCollector : public QuicPacketCreator::DelegateInterface,
52 public QuicStreamFrameDataProducer {
53 public:
54 explicit PacketCollector(QuicBufferAllocator* allocator)
55 : send_buffer_(allocator) {}
56 ~PacketCollector() override = default;
57
58 // QuicPacketCreator::DelegateInterface methods:
59 void OnSerializedPacket(SerializedPacket* serialized_packet) override {
60 // Make a copy of the serialized packet to send later.
61 packets_.emplace_back(
62 new QuicEncryptedPacket(CopyBuffer(*serialized_packet),
63 serialized_packet->encrypted_length, true));
64 serialized_packet->encrypted_buffer = nullptr;
65 DeleteFrames(&(serialized_packet->retransmittable_frames));
66 serialized_packet->retransmittable_frames.clear();
67 }
68
69 char* GetPacketBuffer() override {
70 // Let QuicPacketCreator to serialize packets on stack buffer.
71 return nullptr;
72 }
73
74 void OnUnrecoverableError(QuicErrorCode error,
vasilvvc48c8712019-03-11 13:38:16 -070075 const std::string& error_details,
QUICHE teama6ef0a62019-03-07 20:34:33 -050076 ConnectionCloseSource source) override {}
77
78 void SaveStatelessRejectFrameData(QuicStringPiece reject) {
79 struct iovec iovec;
80 iovec.iov_base = const_cast<char*>(reject.data());
81 iovec.iov_len = reject.length();
82 send_buffer_.SaveStreamData(&iovec, 1, 0, iovec.iov_len);
83 }
84
85 // QuicStreamFrameDataProducer
86 WriteStreamDataResult WriteStreamData(QuicStreamId id,
87 QuicStreamOffset offset,
88 QuicByteCount data_length,
89 QuicDataWriter* writer) override {
90 if (send_buffer_.WriteStreamData(offset, data_length, writer)) {
91 return WRITE_SUCCESS;
92 }
93 return WRITE_FAILED;
94 }
95 bool WriteCryptoData(EncryptionLevel level,
96 QuicStreamOffset offset,
97 QuicByteCount data_length,
98 QuicDataWriter* writer) override {
99 return send_buffer_.WriteStreamData(offset, data_length, writer);
100 }
101
102 std::vector<std::unique_ptr<QuicEncryptedPacket>>* packets() {
103 return &packets_;
104 }
105
106 private:
107 std::vector<std::unique_ptr<QuicEncryptedPacket>> packets_;
108 // This is only needed until the packets are encrypted. Once packets are
109 // encrypted, the stream data is no longer required.
110 QuicStreamSendBuffer send_buffer_;
111};
112
113// Helper for statelessly closing connections by generating the
114// correct termination packets and adding the connection to the time wait
115// list manager.
116class StatelessConnectionTerminator {
117 public:
118 StatelessConnectionTerminator(QuicConnectionId connection_id,
fayangf7c569c2019-05-07 11:56:51 -0700119 const ParsedQuicVersion version,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500120 QuicConnectionHelperInterface* helper,
121 QuicTimeWaitListManager* time_wait_list_manager)
122 : connection_id_(connection_id),
fayangf7c569c2019-05-07 11:56:51 -0700123 framer_(ParsedQuicVersionVector{version},
124 /*unused*/ QuicTime::Zero(),
125 Perspective::IS_SERVER,
126 /*unused*/ kQuicDefaultConnectionIdLength),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500127 collector_(helper->GetStreamSendBufferAllocator()),
fayangf7c569c2019-05-07 11:56:51 -0700128 creator_(connection_id, &framer_, &collector_),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500129 time_wait_list_manager_(time_wait_list_manager) {
fayangf7c569c2019-05-07 11:56:51 -0700130 framer_.set_data_producer(&collector_);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500131 }
132
133 ~StatelessConnectionTerminator() {
134 // Clear framer's producer.
fayangf7c569c2019-05-07 11:56:51 -0700135 framer_.set_data_producer(nullptr);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500136 }
137
138 // Generates a packet containing a CONNECTION_CLOSE frame specifying
139 // |error_code| and |error_details| and add the connection to time wait.
140 void CloseConnection(QuicErrorCode error_code,
vasilvvc48c8712019-03-11 13:38:16 -0700141 const std::string& error_details,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500142 bool ietf_quic) {
fkastenholze9d71a82019-04-09 05:12:13 -0700143 QuicConnectionCloseFrame* frame =
144 new QuicConnectionCloseFrame(error_code, error_details);
fayangf7c569c2019-05-07 11:56:51 -0700145 if (framer_.transport_version() == QUIC_VERSION_99) {
fkastenholz72f509b2019-04-10 09:17:49 -0700146 frame->close_type = IETF_QUIC_TRANSPORT_CONNECTION_CLOSE;
147 }
148
QUICHE teama6ef0a62019-03-07 20:34:33 -0500149 if (!creator_.AddSavedFrame(QuicFrame(frame), NOT_RETRANSMISSION)) {
150 QUIC_BUG << "Unable to add frame to an empty packet";
151 delete frame;
152 return;
153 }
154 creator_.Flush();
155 DCHECK_EQ(1u, collector_.packets()->size());
156 time_wait_list_manager_->AddConnectionIdToTimeWait(
157 connection_id_, ietf_quic,
158 QuicTimeWaitListManager::SEND_TERMINATION_PACKETS,
QUICHE team6987b4a2019-03-15 16:23:04 -0700159 quic::ENCRYPTION_INITIAL, collector_.packets());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500160 }
161
162 // Generates a series of termination packets containing the crypto handshake
163 // message |reject|. Adds the connection to time wait list with the
164 // generated packets.
165 void RejectConnection(QuicStringPiece reject, bool ietf_quic) {
166 QuicStreamOffset offset = 0;
167 collector_.SaveStatelessRejectFrameData(reject);
168 while (offset < reject.length()) {
169 QuicFrame frame;
fayangf7c569c2019-05-07 11:56:51 -0700170 if (!QuicVersionUsesCryptoFrames(framer_.transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500171 if (!creator_.ConsumeData(
fayangf7c569c2019-05-07 11:56:51 -0700172 QuicUtils::GetCryptoStreamId(framer_.transport_version()),
ianswette28f0222019-04-04 13:31:22 -0700173 reject.length() - offset, offset,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500174 /*fin=*/false,
175 /*needs_full_padding=*/true, NOT_RETRANSMISSION, &frame)) {
176 QUIC_BUG << "Unable to consume data into an empty packet.";
177 return;
178 }
179 offset += frame.stream_frame.data_length;
180 } else {
nharper51961cf2019-05-13 13:23:24 -0700181 if (!creator_.ConsumeCryptoData(
182 ENCRYPTION_INITIAL, reject.length() - offset, offset,
183 /*needs_full_padding=*/true, NOT_RETRANSMISSION, &frame)) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500184 QUIC_BUG << "Unable to consume crypto data into an empty packet.";
185 return;
186 }
187 offset += frame.crypto_frame->data_length;
188 }
189 if (offset < reject.length()) {
190 DCHECK(!creator_.HasRoomForStreamFrame(
fayangf7c569c2019-05-07 11:56:51 -0700191 QuicUtils::GetCryptoStreamId(framer_.transport_version()), offset,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500192 frame.stream_frame.data_length));
193 }
194 creator_.Flush();
195 }
196 time_wait_list_manager_->AddConnectionIdToTimeWait(
197 connection_id_, ietf_quic,
QUICHE team6987b4a2019-03-15 16:23:04 -0700198 QuicTimeWaitListManager::SEND_TERMINATION_PACKETS, ENCRYPTION_INITIAL,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500199 collector_.packets());
200 DCHECK(time_wait_list_manager_->IsConnectionIdInTimeWait(connection_id_));
201 }
202
203 private:
204 QuicConnectionId connection_id_;
fayangf7c569c2019-05-07 11:56:51 -0700205 QuicFramer framer_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500206 // Set as the visitor of |creator_| to collect any generated packets.
207 PacketCollector collector_;
208 QuicPacketCreator creator_;
209 QuicTimeWaitListManager* time_wait_list_manager_;
210};
211
212// Class which extracts the ALPN from a CHLO packet.
213class ChloAlpnExtractor : public ChloExtractor::Delegate {
214 public:
215 void OnChlo(QuicTransportVersion version,
216 QuicConnectionId connection_id,
217 const CryptoHandshakeMessage& chlo) override {
218 QuicStringPiece alpn_value;
219 if (chlo.GetStringPiece(kALPN, &alpn_value)) {
vasilvvc48c8712019-03-11 13:38:16 -0700220 alpn_ = std::string(alpn_value);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500221 }
222 }
223
vasilvvc48c8712019-03-11 13:38:16 -0700224 std::string&& ConsumeAlpn() { return std::move(alpn_); }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500225
226 private:
vasilvvc48c8712019-03-11 13:38:16 -0700227 std::string alpn_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500228};
229
230// Class which sits between the ChloExtractor and the StatelessRejector
231// to give the QuicDispatcher a chance to apply policy checks to the CHLO.
232class ChloValidator : public ChloAlpnExtractor {
233 public:
234 ChloValidator(QuicCryptoServerStream::Helper* helper,
235 const QuicSocketAddress& client_address,
236 const QuicSocketAddress& peer_address,
237 const QuicSocketAddress& self_address,
238 StatelessRejector* rejector)
239 : helper_(helper),
240 client_address_(client_address),
241 peer_address_(peer_address),
242 self_address_(self_address),
243 rejector_(rejector),
244 can_accept_(false),
245 error_details_("CHLO not processed") {}
246
247 // ChloExtractor::Delegate implementation.
248 void OnChlo(QuicTransportVersion version,
249 QuicConnectionId connection_id,
250 const CryptoHandshakeMessage& chlo) override {
251 // Extract the ALPN
252 ChloAlpnExtractor::OnChlo(version, connection_id, chlo);
253 if (helper_->CanAcceptClientHello(chlo, client_address_, peer_address_,
254 self_address_, &error_details_)) {
255 can_accept_ = true;
256 rejector_->OnChlo(
257 version, connection_id,
258 helper_->GenerateConnectionIdForReject(version, connection_id), chlo);
259 }
260 }
261
262 bool can_accept() const { return can_accept_; }
263
vasilvvc48c8712019-03-11 13:38:16 -0700264 const std::string& error_details() const { return error_details_; }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500265
266 private:
267 QuicCryptoServerStream::Helper* helper_; // Unowned.
268 // client_address_ and peer_address_ could be different values for proxy
269 // connections.
270 QuicSocketAddress client_address_;
271 QuicSocketAddress peer_address_;
272 QuicSocketAddress self_address_;
273 StatelessRejector* rejector_; // Unowned.
274 bool can_accept_;
vasilvvc48c8712019-03-11 13:38:16 -0700275 std::string error_details_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500276};
277
278} // namespace
279
280QuicDispatcher::QuicDispatcher(
281 const QuicConfig* config,
282 const QuicCryptoServerConfig* crypto_config,
283 QuicVersionManager* version_manager,
284 std::unique_ptr<QuicConnectionHelperInterface> helper,
285 std::unique_ptr<QuicCryptoServerStream::Helper> session_helper,
286 std::unique_ptr<QuicAlarmFactory> alarm_factory,
287 uint8_t expected_connection_id_length)
288 : config_(config),
289 crypto_config_(crypto_config),
290 compressed_certs_cache_(
291 QuicCompressedCertsCache::kQuicCompressedCertsCacheSize),
292 helper_(std::move(helper)),
293 session_helper_(std::move(session_helper)),
294 alarm_factory_(std::move(alarm_factory)),
295 delete_sessions_alarm_(
296 alarm_factory_->CreateAlarm(new DeleteSessionsAlarm(this))),
297 buffered_packets_(this, helper_->GetClock(), alarm_factory_.get()),
298 current_packet_(nullptr),
299 version_manager_(version_manager),
300 framer_(GetSupportedVersions(),
301 /*unused*/ QuicTime::Zero(),
302 Perspective::IS_SERVER,
303 expected_connection_id_length),
304 last_error_(QUIC_NO_ERROR),
305 new_sessions_allowed_per_event_loop_(0u),
QUICHE team963d57e2019-03-21 10:58:47 -0700306 accept_new_connections_(true),
fayangccbab732019-05-13 10:11:25 -0700307 allow_short_initial_connection_ids_(false),
308 last_version_label_(0),
309 expected_connection_id_length_(expected_connection_id_length),
310 should_update_expected_connection_id_length_(false),
311 no_framer_(GetQuicRestartFlag(quic_no_framer_object_in_dispatcher)) {
312 if (!no_framer_) {
313 framer_.set_visitor(this);
314 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500315}
316
317QuicDispatcher::~QuicDispatcher() {
318 session_map_.clear();
319 closed_session_list_.clear();
320}
321
322void QuicDispatcher::InitializeWithWriter(QuicPacketWriter* writer) {
323 DCHECK(writer_ == nullptr);
324 writer_.reset(writer);
325 time_wait_list_manager_.reset(CreateQuicTimeWaitListManager());
326}
327
328void QuicDispatcher::ProcessPacket(const QuicSocketAddress& self_address,
329 const QuicSocketAddress& peer_address,
330 const QuicReceivedPacket& packet) {
331 current_self_address_ = self_address;
332 current_peer_address_ = peer_address;
333 // GetClientAddress must be called after current_peer_address_ is set.
334 current_client_address_ = GetClientAddress();
335 current_packet_ = &packet;
fayangccbab732019-05-13 10:11:25 -0700336 if (!no_framer_) {
337 // ProcessPacket will cause the packet to be dispatched in
338 // OnUnauthenticatedPublicHeader, or sent to the time wait list manager
339 // in OnUnauthenticatedHeader.
340 framer_.ProcessPacket(packet);
341 // TODO(rjshade): Return a status describing if/why a packet was dropped,
342 // and log somehow. Maybe expose as a varz.
343 return;
344 }
345 QUIC_RESTART_FLAG_COUNT(quic_no_framer_object_in_dispatcher);
346 QuicPacketHeader header;
347 uint8_t destination_connection_id_length;
348 string detailed_error;
349 const QuicErrorCode error = QuicFramer::ProcessPacketDispatcher(
350 packet, expected_connection_id_length_, &header.form,
351 &header.version_flag, &last_version_label_,
352 &destination_connection_id_length, &header.destination_connection_id,
353 &detailed_error);
354 if (error != QUIC_NO_ERROR) {
355 // Packet has framing error.
356 SetLastError(error);
357 QUIC_DLOG(ERROR) << detailed_error;
358 return;
359 }
360 header.version = ParseQuicVersionLabel(last_version_label_);
361 if (destination_connection_id_length != expected_connection_id_length_ &&
362 !should_update_expected_connection_id_length_ &&
363 !QuicUtils::VariableLengthConnectionIdAllowedForVersion(
364 header.version.transport_version)) {
365 SetLastError(QUIC_INVALID_PACKET_HEADER);
366 QUIC_DLOG(ERROR) << "Invalid Connection Id Length";
367 return;
368 }
369 if (should_update_expected_connection_id_length_) {
370 expected_connection_id_length_ = destination_connection_id_length;
371 }
372 // TODO(fayang): Instead of passing in QuicPacketHeader, pass format,
373 // version_flag, version and destination_connection_id. Combine
374 // OnUnauthenticatedPublicHeader and OnUnauthenticatedHeader to a single
375 // function when deprecating quic_no_framer_object_in_dispatcher.
376 if (!OnUnauthenticatedPublicHeader(header)) {
377 return;
378 }
379 OnUnauthenticatedHeader(header);
380 // TODO(wub): Consider invalidate the current_* variables so processing of
381 // the next packet does not use them incorrectly.
QUICHE teama6ef0a62019-03-07 20:34:33 -0500382}
383
QUICHE teamc65d1d12019-03-19 20:58:04 -0700384QuicConnectionId QuicDispatcher::MaybeReplaceConnectionId(
385 QuicConnectionId connection_id,
386 ParsedQuicVersion version) {
387 const uint8_t expected_connection_id_length =
fayangccbab732019-05-13 10:11:25 -0700388 no_framer_ ? expected_connection_id_length_
389 : framer_.GetExpectedConnectionIdLength();
QUICHE teamc65d1d12019-03-19 20:58:04 -0700390 if (connection_id.length() == expected_connection_id_length) {
391 return connection_id;
392 }
393 DCHECK(QuicUtils::VariableLengthConnectionIdAllowedForVersion(
394 version.transport_version));
395 auto it = connection_id_map_.find(connection_id);
396 if (it != connection_id_map_.end()) {
397 return it->second;
398 }
399 QuicConnectionId new_connection_id =
400 session_helper_->GenerateConnectionIdForReject(version.transport_version,
401 connection_id);
402 DCHECK_EQ(expected_connection_id_length, new_connection_id.length());
403 connection_id_map_.insert(std::make_pair(connection_id, new_connection_id));
404 QUIC_DLOG(INFO) << "Replacing incoming connection ID " << connection_id
405 << " with " << new_connection_id;
406 return new_connection_id;
407}
408
QUICHE teama6ef0a62019-03-07 20:34:33 -0500409bool QuicDispatcher::OnUnauthenticatedPublicHeader(
410 const QuicPacketHeader& header) {
411 current_connection_id_ = header.destination_connection_id;
412
413 // Port zero is only allowed for unidirectional UDP, so is disallowed by QUIC.
414 // Given that we can't even send a reply rejecting the packet, just drop the
415 // packet.
416 if (current_peer_address_.port() == 0) {
417 return false;
418 }
419
420 // The dispatcher requires the connection ID to be present in order to
421 // look up the matching QuicConnection, so we error out if it is absent.
422 if (header.destination_connection_id_included != CONNECTION_ID_PRESENT) {
423 return false;
424 }
QUICHE teamc65d1d12019-03-19 20:58:04 -0700425 QuicConnectionId connection_id = header.destination_connection_id;
QUICHE team8e2e4532019-03-14 14:37:56 -0700426
QUICHE team963d57e2019-03-21 10:58:47 -0700427 // The IETF spec requires the client to generate an initial server
428 // connection ID that is at least 64 bits long. After that initial
429 // connection ID, the dispatcher picks a new one of its expected length.
430 // Therefore we should never receive a connection ID that is smaller
431 // than 64 bits and smaller than what we expect.
fayangccbab732019-05-13 10:11:25 -0700432 const uint8_t expected_connection_id_length =
433 no_framer_ ? expected_connection_id_length_
434 : framer_.GetExpectedConnectionIdLength();
QUICHE team963d57e2019-03-21 10:58:47 -0700435 if (connection_id.length() < kQuicMinimumInitialConnectionIdLength &&
fayangccbab732019-05-13 10:11:25 -0700436 connection_id.length() < expected_connection_id_length &&
QUICHE team963d57e2019-03-21 10:58:47 -0700437 !allow_short_initial_connection_ids_) {
438 DCHECK(header.version_flag);
439 DCHECK(QuicUtils::VariableLengthConnectionIdAllowedForVersion(
440 header.version.transport_version));
441 QUIC_DLOG(INFO) << "Packet with short destination connection ID "
442 << connection_id << " expected "
fayangccbab732019-05-13 10:11:25 -0700443 << static_cast<int>(expected_connection_id_length);
QUICHE team963d57e2019-03-21 10:58:47 -0700444 ProcessUnauthenticatedHeaderFate(kFateTimeWait, connection_id, header.form,
fayang1de67892019-04-19 05:59:45 -0700445 header.version_flag, header.version);
QUICHE team963d57e2019-03-21 10:58:47 -0700446 return false;
447 }
448
QUICHE teama6ef0a62019-03-07 20:34:33 -0500449 // Packets with connection IDs for active connections are processed
450 // immediately.
QUICHE teama6ef0a62019-03-07 20:34:33 -0500451 auto it = session_map_.find(connection_id);
452 if (it != session_map_.end()) {
453 DCHECK(!buffered_packets_.HasBufferedPackets(connection_id));
454 it->second->ProcessUdpPacket(current_self_address_, current_peer_address_,
455 *current_packet_);
456 return false;
457 }
458
459 if (buffered_packets_.HasChloForConnection(connection_id)) {
460 BufferEarlyPacket(connection_id, header.form != GOOGLE_QUIC_PACKET,
461 header.version);
462 return false;
463 }
464
465 // Check if we are buffering packets for this connection ID
466 if (temporarily_buffered_connections_.find(connection_id) !=
467 temporarily_buffered_connections_.end()) {
468 // This packet was received while the a CHLO for the same connection ID was
469 // being processed. Buffer it.
470 BufferEarlyPacket(connection_id, header.form != GOOGLE_QUIC_PACKET,
471 header.version);
472 return false;
473 }
474
475 if (!OnUnauthenticatedUnknownPublicHeader(header)) {
476 return false;
477 }
478
479 // If the packet is a public reset for a connection ID that is not active,
480 // there is nothing we must do or can do.
481 if (header.reset_flag) {
482 return false;
483 }
484
485 if (time_wait_list_manager_->IsConnectionIdInTimeWait(connection_id)) {
486 // This connection ID is already in time-wait state.
487 time_wait_list_manager_->ProcessPacket(
488 current_self_address_, current_peer_address_,
489 header.destination_connection_id, header.form, GetPerPacketContext());
490 return false;
491 }
492
493 // The packet has an unknown connection ID.
494
495 // Unless the packet provides a version, assume that we can continue
496 // processing using our preferred version.
497 ParsedQuicVersion version = GetSupportedVersions().front();
498 if (header.version_flag) {
499 ParsedQuicVersion packet_version = header.version;
fayangccbab732019-05-13 10:11:25 -0700500 if (!no_framer_ && framer_.supported_versions() != GetSupportedVersions()) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500501 // Reset framer's version if version flags change in flight.
502 framer_.SetSupportedVersions(GetSupportedVersions());
503 }
fayangccbab732019-05-13 10:11:25 -0700504 if (!IsSupportedVersion(packet_version)) {
505 if (ShouldCreateSessionForUnknownVersion(
506 no_framer_ ? last_version_label_
507 : framer_.last_version_label())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500508 return true;
509 }
510 if (!crypto_config()->validate_chlo_size() ||
511 current_packet_->length() >= kMinPacketSizeForVersionNegotiation) {
512 // Since the version is not supported, send a version negotiation
513 // packet and stop processing the current packet.
514 time_wait_list_manager()->SendVersionNegotiationPacket(
515 connection_id, header.form != GOOGLE_QUIC_PACKET,
516 GetSupportedVersions(), current_self_address_,
517 current_peer_address_, GetPerPacketContext());
518 }
519 return false;
520 }
521 version = packet_version;
522 }
fayangccbab732019-05-13 10:11:25 -0700523 if (!no_framer_) {
524 // Set the framer's version and continue processing.
525 framer_.set_version(version);
526 }
nharper55fa6132019-05-07 19:37:21 -0700527
528 if (version.HasHeaderProtection()) {
529 ProcessHeader(header);
530 return false;
531 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500532 return true;
533}
534
535bool QuicDispatcher::OnUnauthenticatedHeader(const QuicPacketHeader& header) {
nharper55fa6132019-05-07 19:37:21 -0700536 ProcessHeader(header);
537 return false;
538}
539
540void QuicDispatcher::ProcessHeader(const QuicPacketHeader& header) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500541 QuicConnectionId connection_id = header.destination_connection_id;
542 // Packet's connection ID is unknown. Apply the validity checks.
543 QuicPacketFate fate = ValidityChecks(header);
544 if (fate == kFateProcess) {
545 // Execute stateless rejection logic to determine the packet fate, then
546 // invoke ProcessUnauthenticatedHeaderFate.
fayang1de67892019-04-19 05:59:45 -0700547 MaybeRejectStatelessly(connection_id, header.form, header.version_flag,
548 header.version);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500549 } else {
550 // If the fate is already known, process it without executing stateless
551 // rejection logic.
552 ProcessUnauthenticatedHeaderFate(fate, connection_id, header.form,
fayang1de67892019-04-19 05:59:45 -0700553 header.version_flag, header.version);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500554 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500555}
556
557void QuicDispatcher::ProcessUnauthenticatedHeaderFate(
558 QuicPacketFate fate,
559 QuicConnectionId connection_id,
560 PacketHeaderFormat form,
fayang1de67892019-04-19 05:59:45 -0700561 bool version_flag,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500562 ParsedQuicVersion version) {
563 switch (fate) {
564 case kFateProcess: {
565 ProcessChlo(form, version);
566 break;
567 }
568 case kFateTimeWait:
569 // MaybeRejectStatelessly or OnExpiredPackets might have already added the
570 // connection to time wait, in which case it should not be added again.
571 if (!GetQuicReloadableFlag(quic_use_cheap_stateless_rejects) ||
572 !time_wait_list_manager_->IsConnectionIdInTimeWait(connection_id)) {
573 // Add this connection_id to the time-wait state, to safely reject
574 // future packets.
575 QUIC_DLOG(INFO) << "Adding connection ID " << connection_id
QUICHE team8e2e4532019-03-14 14:37:56 -0700576 << " to time-wait list.";
QUICHE teama6ef0a62019-03-07 20:34:33 -0500577 QUIC_CODE_COUNT(quic_reject_fate_time_wait);
578 StatelesslyTerminateConnection(
fayang1de67892019-04-19 05:59:45 -0700579 connection_id, form, version_flag, version, QUIC_HANDSHAKE_FAILED,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500580 "Reject connection",
581 quic::QuicTimeWaitListManager::SEND_STATELESS_RESET);
582 }
583 DCHECK(time_wait_list_manager_->IsConnectionIdInTimeWait(connection_id));
584 time_wait_list_manager_->ProcessPacket(
585 current_self_address_, current_peer_address_, connection_id, form,
586 GetPerPacketContext());
587
588 // Any packets which were buffered while the stateless rejector logic was
589 // running should be discarded. Do not inform the time wait list manager,
590 // which should already have a made a decision about sending a reject
591 // based on the CHLO alone.
592 buffered_packets_.DiscardPackets(connection_id);
593 break;
594 case kFateBuffer:
595 // This packet is a non-CHLO packet which has arrived before the
596 // corresponding CHLO, *or* this packet was received while the
597 // corresponding CHLO was being processed. Buffer it.
598 BufferEarlyPacket(connection_id, form != GOOGLE_QUIC_PACKET, version);
599 break;
600 case kFateDrop:
601 // Do nothing with the packet.
602 break;
603 }
604}
605
606QuicDispatcher::QuicPacketFate QuicDispatcher::ValidityChecks(
607 const QuicPacketHeader& header) {
608 // To have all the checks work properly without tears, insert any new check
609 // into the framework of this method in the section for checks that return the
610 // check's fate value. The sections for checks must be ordered with the
611 // highest priority fate first.
612
613 // Checks that return kFateDrop.
614
615 // Checks that return kFateTimeWait.
616
617 // All packets within a connection sent by a client before receiving a
618 // response from the server are required to have the version negotiation flag
619 // set. Since this may be a client continuing a connection we lost track of
620 // via server restart, send a rejection to fast-fail the connection.
621 if (!header.version_flag) {
622 QUIC_DLOG(INFO)
623 << "Packet without version arrived for unknown connection ID "
624 << header.destination_connection_id;
625 return kFateTimeWait;
626 }
627
fayangccbab732019-05-13 10:11:25 -0700628 if (no_framer_) {
629 // Let the connection parse and validate packet number.
630 return kFateProcess;
631 }
632
QUICHE teama6ef0a62019-03-07 20:34:33 -0500633 // initial packet number of 0 is always invalid.
nharper55fa6132019-05-07 19:37:21 -0700634 if (!framer_.version().HasHeaderProtection()) {
635 if (!header.packet_number.IsInitialized()) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500636 return kFateTimeWait;
637 }
nharper55fa6132019-05-07 19:37:21 -0700638 if (GetQuicRestartFlag(quic_enable_accept_random_ipn)) {
639 QUIC_RESTART_FLAG_COUNT_N(quic_enable_accept_random_ipn, 1, 2);
640 // Accepting Initial Packet Numbers in 1...((2^31)-1) range... check
641 // maximum accordingly.
642 if (header.packet_number > MaxRandomInitialPacketNumber()) {
643 return kFateTimeWait;
644 }
645 } else {
646 // Count those that would have been accepted if FLAGS..random_ipn
647 // were true -- to detect/diagnose potential issues prior to
648 // enabling the flag.
649 if ((header.packet_number >
650 QuicPacketNumber(kMaxReasonableInitialPacketNumber)) &&
651 (header.packet_number <= MaxRandomInitialPacketNumber())) {
652 QUIC_CODE_COUNT_N(had_possibly_random_ipn, 1, 2);
653 }
654 // Check that the sequence number is within the range that the client is
655 // expected to send before receiving a response from the server.
656 if (header.packet_number >
657 QuicPacketNumber(kMaxReasonableInitialPacketNumber)) {
658 return kFateTimeWait;
659 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500660 }
661 }
662 return kFateProcess;
663}
664
665void QuicDispatcher::CleanUpSession(SessionMap::iterator it,
666 QuicConnection* connection,
667 bool should_close_statelessly,
668 ConnectionCloseSource source) {
669 write_blocked_list_.erase(connection);
670 if (should_close_statelessly) {
671 DCHECK(connection->termination_packets() != nullptr &&
672 !connection->termination_packets()->empty());
673 }
674 QuicTimeWaitListManager::TimeWaitAction action =
675 QuicTimeWaitListManager::SEND_STATELESS_RESET;
676 if (connection->termination_packets() != nullptr &&
677 !connection->termination_packets()->empty()) {
678 action = QuicTimeWaitListManager::SEND_TERMINATION_PACKETS;
fayang1de67892019-04-19 05:59:45 -0700679 } else if (connection->transport_version() > QUIC_VERSION_43 ||
680 GetQuicReloadableFlag(quic_terminate_gquic_connection_as_ietf)) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500681 if (!connection->IsHandshakeConfirmed()) {
fayang1de67892019-04-19 05:59:45 -0700682 if (connection->transport_version() <= QUIC_VERSION_43) {
683 QUIC_CODE_COUNT(gquic_add_to_time_wait_list_with_handshake_failed);
684 } else {
685 QUIC_CODE_COUNT(quic_v44_add_to_time_wait_list_with_handshake_failed);
686 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500687 action = QuicTimeWaitListManager::SEND_TERMINATION_PACKETS;
688 // This serializes a connection close termination packet with error code
689 // QUIC_HANDSHAKE_FAILED and adds the connection to the time wait list.
690 StatelesslyTerminateConnection(
fayang1de67892019-04-19 05:59:45 -0700691 connection->connection_id(),
692 connection->transport_version() > QUIC_VERSION_43
693 ? IETF_QUIC_LONG_HEADER_PACKET
694 : GOOGLE_QUIC_PACKET,
695 /*version_flag=*/true, connection->version(), QUIC_HANDSHAKE_FAILED,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500696 "Connection is closed by server before handshake confirmed",
697 // Although it is our intention to send termination packets, the
698 // |action| argument is not used by this call to
699 // StatelesslyTerminateConnection().
700 action);
701 session_map_.erase(it);
702 return;
703 }
704 QUIC_CODE_COUNT(quic_v44_add_to_time_wait_list_with_stateless_reset);
705 }
706 time_wait_list_manager_->AddConnectionIdToTimeWait(
707 it->first, connection->transport_version() > QUIC_VERSION_43, action,
708 connection->encryption_level(), connection->termination_packets());
709 session_map_.erase(it);
710}
711
712void QuicDispatcher::StopAcceptingNewConnections() {
713 accept_new_connections_ = false;
714}
715
716std::unique_ptr<QuicPerPacketContext> QuicDispatcher::GetPerPacketContext()
717 const {
718 return nullptr;
719}
720
721void QuicDispatcher::DeleteSessions() {
QUICHE teamaa1d6a82019-03-13 09:14:13 -0700722 if (!write_blocked_list_.empty()) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500723 for (const std::unique_ptr<QuicSession>& session : closed_session_list_) {
724 if (write_blocked_list_.erase(session->connection()) != 0) {
725 QUIC_BUG << "QuicConnection was in WriteBlockedList before destruction";
726 }
727 }
728 }
729 closed_session_list_.clear();
730}
731
732void QuicDispatcher::OnCanWrite() {
733 // The socket is now writable.
734 writer_->SetWritable();
735
736 // Move every blocked writer in |write_blocked_list_| to a temporary list.
737 const size_t num_blocked_writers_before = write_blocked_list_.size();
738 WriteBlockedList temp_list;
739 temp_list.swap(write_blocked_list_);
740 DCHECK(write_blocked_list_.empty());
741
742 // Give each blocked writer a chance to write what they indended to write.
743 // If they are blocked again, they will call |OnWriteBlocked| to add
744 // themselves back into |write_blocked_list_|.
745 while (!temp_list.empty()) {
746 QuicBlockedWriterInterface* blocked_writer = temp_list.begin()->first;
747 temp_list.erase(temp_list.begin());
748 blocked_writer->OnBlockedWriterCanWrite();
749 }
750 const size_t num_blocked_writers_after = write_blocked_list_.size();
751 if (num_blocked_writers_after != 0) {
752 if (num_blocked_writers_before == num_blocked_writers_after) {
753 QUIC_CODE_COUNT(quic_zero_progress_on_can_write);
754 } else {
755 QUIC_CODE_COUNT(quic_blocked_again_on_can_write);
756 }
757 }
758}
759
760bool QuicDispatcher::HasPendingWrites() const {
761 return !write_blocked_list_.empty();
762}
763
764void QuicDispatcher::Shutdown() {
765 while (!session_map_.empty()) {
766 QuicSession* session = session_map_.begin()->second.get();
767 session->connection()->CloseConnection(
768 QUIC_PEER_GOING_AWAY, "Server shutdown imminent",
769 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
770 // Validate that the session removes itself from the session map on close.
771 DCHECK(session_map_.empty() ||
772 session_map_.begin()->second.get() != session);
773 }
774 DeleteSessions();
775}
776
777void QuicDispatcher::OnConnectionClosed(QuicConnectionId connection_id,
778 QuicErrorCode error,
vasilvvc48c8712019-03-11 13:38:16 -0700779 const std::string& error_details,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500780 ConnectionCloseSource source) {
781 auto it = session_map_.find(connection_id);
782 if (it == session_map_.end()) {
783 QUIC_BUG << "ConnectionId " << connection_id
784 << " does not exist in the session map. Error: "
785 << QuicErrorCodeToString(error);
786 QUIC_BUG << QuicStackTrace();
787 return;
788 }
789
790 QUIC_DLOG_IF(INFO, error != QUIC_NO_ERROR)
791 << "Closing connection (" << connection_id
792 << ") due to error: " << QuicErrorCodeToString(error)
793 << ", with details: " << error_details;
794
795 QuicConnection* connection = it->second->connection();
796 if (ShouldDestroySessionAsynchronously()) {
797 // Set up alarm to fire immediately to bring destruction of this session
798 // out of current call stack.
799 if (closed_session_list_.empty()) {
800 delete_sessions_alarm_->Update(helper()->GetClock()->ApproximateNow(),
801 QuicTime::Delta::Zero());
802 }
803 closed_session_list_.push_back(std::move(it->second));
804 }
805 const bool should_close_statelessly =
806 (error == QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT);
807 CleanUpSession(it, connection, should_close_statelessly, source);
808}
809
810void QuicDispatcher::OnWriteBlocked(
811 QuicBlockedWriterInterface* blocked_writer) {
812 if (!blocked_writer->IsWriterBlocked()) {
813 // It is a programming error if this ever happens. When we are sure it is
814 // not happening, replace it with a DCHECK.
815 QUIC_BUG
816 << "Tried to add writer into blocked list when it shouldn't be added";
817 // Return without adding the connection to the blocked list, to avoid
818 // infinite loops in OnCanWrite.
819 return;
820 }
821
822 write_blocked_list_.insert(std::make_pair(blocked_writer, true));
823}
824
825void QuicDispatcher::OnRstStreamReceived(const QuicRstStreamFrame& frame) {}
826
827void QuicDispatcher::OnStopSendingReceived(const QuicStopSendingFrame& frame) {}
828
829void QuicDispatcher::OnConnectionAddedToTimeWaitList(
830 QuicConnectionId connection_id) {
831 QUIC_DLOG(INFO) << "Connection " << connection_id
832 << " added to time wait list.";
833}
834
835void QuicDispatcher::StatelesslyTerminateConnection(
836 QuicConnectionId connection_id,
837 PacketHeaderFormat format,
fayang1de67892019-04-19 05:59:45 -0700838 bool version_flag,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500839 ParsedQuicVersion version,
840 QuicErrorCode error_code,
vasilvvc48c8712019-03-11 13:38:16 -0700841 const std::string& error_details,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500842 QuicTimeWaitListManager::TimeWaitAction action) {
fayang1de67892019-04-19 05:59:45 -0700843 if (format != IETF_QUIC_LONG_HEADER_PACKET &&
844 (!GetQuicReloadableFlag(quic_terminate_gquic_connection_as_ietf) ||
845 !version_flag)) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500846 QUIC_DVLOG(1) << "Statelessly terminating " << connection_id
847 << " based on a non-ietf-long packet, action:" << action
848 << ", error_code:" << error_code
849 << ", error_details:" << error_details;
850 time_wait_list_manager_->AddConnectionIdToTimeWait(
QUICHE team6987b4a2019-03-15 16:23:04 -0700851 connection_id, format != GOOGLE_QUIC_PACKET, action, ENCRYPTION_INITIAL,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500852 nullptr);
853 return;
854 }
855
856 // If the version is known and supported by framer, send a connection close.
fayangccbab732019-05-13 10:11:25 -0700857 if (IsSupportedVersion(version)) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500858 QUIC_DVLOG(1)
859 << "Statelessly terminating " << connection_id
860 << " based on an ietf-long packet, which has a supported version:"
861 << version << ", error_code:" << error_code
862 << ", error_details:" << error_details;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500863
864 StatelessConnectionTerminator terminator(
fayangf7c569c2019-05-07 11:56:51 -0700865 connection_id, version, helper_.get(), time_wait_list_manager_.get());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500866 // This also adds the connection to time wait list.
fayang1de67892019-04-19 05:59:45 -0700867 if (format == GOOGLE_QUIC_PACKET) {
868 QUIC_RELOADABLE_FLAG_COUNT_N(quic_terminate_gquic_connection_as_ietf, 1,
869 2);
870 }
871 terminator.CloseConnection(error_code, error_details,
872 format != GOOGLE_QUIC_PACKET);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500873 return;
874 }
875
876 QUIC_DVLOG(1)
877 << "Statelessly terminating " << connection_id
878 << " based on an ietf-long packet, which has an unsupported version:"
879 << version << ", error_code:" << error_code
880 << ", error_details:" << error_details;
881 // Version is unknown or unsupported by framer, send a version negotiation
882 // with an empty version list, which can be understood by the client.
883 std::vector<std::unique_ptr<QuicEncryptedPacket>> termination_packets;
884 termination_packets.push_back(QuicFramer::BuildVersionNegotiationPacket(
fayang1de67892019-04-19 05:59:45 -0700885 connection_id, /*ietf_quic=*/format != GOOGLE_QUIC_PACKET,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500886 ParsedQuicVersionVector{UnsupportedQuicVersion()}));
fayang1de67892019-04-19 05:59:45 -0700887 if (format == GOOGLE_QUIC_PACKET) {
888 QUIC_RELOADABLE_FLAG_COUNT_N(quic_terminate_gquic_connection_as_ietf, 2, 2);
889 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500890 time_wait_list_manager()->AddConnectionIdToTimeWait(
fayang1de67892019-04-19 05:59:45 -0700891 connection_id, /*ietf_quic=*/format != GOOGLE_QUIC_PACKET,
QUICHE team6987b4a2019-03-15 16:23:04 -0700892 QuicTimeWaitListManager::SEND_TERMINATION_PACKETS, ENCRYPTION_INITIAL,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500893 &termination_packets);
894}
895
896void QuicDispatcher::OnPacket() {}
897
898void QuicDispatcher::OnError(QuicFramer* framer) {
899 QuicErrorCode error = framer->error();
900 SetLastError(error);
901 QUIC_DLOG(INFO) << QuicErrorCodeToString(error);
902}
903
904bool QuicDispatcher::ShouldCreateSessionForUnknownVersion(
905 QuicVersionLabel /*version_label*/) {
906 return false;
907}
908
909bool QuicDispatcher::OnProtocolVersionMismatch(
910 ParsedQuicVersion /*received_version*/,
911 PacketHeaderFormat /*form*/) {
fayangccbab732019-05-13 10:11:25 -0700912 DCHECK(!no_framer_);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500913 QUIC_BUG_IF(
914 !time_wait_list_manager_->IsConnectionIdInTimeWait(
915 current_connection_id_) &&
916 !ShouldCreateSessionForUnknownVersion(framer_.last_version_label()))
917 << "Unexpected version mismatch: "
918 << QuicVersionLabelToString(framer_.last_version_label());
919
920 // Keep processing after protocol mismatch - this will be dealt with by the
921 // time wait list or connection that we will create.
922 return true;
923}
924
925void QuicDispatcher::OnPublicResetPacket(
926 const QuicPublicResetPacket& /*packet*/) {
927 DCHECK(false);
928}
929
930void QuicDispatcher::OnVersionNegotiationPacket(
931 const QuicVersionNegotiationPacket& /*packet*/) {
932 DCHECK(false);
933}
934
dschinazi244f6dc2019-05-06 15:45:16 -0700935void QuicDispatcher::OnRetryPacket(QuicConnectionId /*original_connection_id*/,
936 QuicConnectionId /*new_connection_id*/,
937 QuicStringPiece /*retry_token*/) {
938 DCHECK(false);
939}
940
QUICHE teama6ef0a62019-03-07 20:34:33 -0500941void QuicDispatcher::OnDecryptedPacket(EncryptionLevel level) {
942 DCHECK(false);
943}
944
945bool QuicDispatcher::OnPacketHeader(const QuicPacketHeader& /*header*/) {
946 DCHECK(false);
947 return false;
948}
949
950void QuicDispatcher::OnCoalescedPacket(const QuicEncryptedPacket& /*packet*/) {
951 DCHECK(false);
952}
953
954bool QuicDispatcher::OnStreamFrame(const QuicStreamFrame& /*frame*/) {
955 DCHECK(false);
956 return false;
957}
958
959bool QuicDispatcher::OnCryptoFrame(const QuicCryptoFrame& /*frame*/) {
960 DCHECK(false);
961 return false;
962}
963
964bool QuicDispatcher::OnAckFrameStart(QuicPacketNumber /*largest_acked*/,
965 QuicTime::Delta /*ack_delay_time*/) {
966 DCHECK(false);
967 return false;
968}
969
970bool QuicDispatcher::OnAckRange(QuicPacketNumber /*start*/,
971 QuicPacketNumber /*end*/) {
972 DCHECK(false);
973 return false;
974}
975
976bool QuicDispatcher::OnAckTimestamp(QuicPacketNumber /*packet_number*/,
977 QuicTime /*timestamp*/) {
978 DCHECK(false);
979 return false;
980}
981
982bool QuicDispatcher::OnAckFrameEnd(QuicPacketNumber /*start*/) {
983 DCHECK(false);
984 return false;
985}
986
987bool QuicDispatcher::OnStopWaitingFrame(const QuicStopWaitingFrame& /*frame*/) {
988 DCHECK(false);
989 return false;
990}
991
992bool QuicDispatcher::OnPaddingFrame(const QuicPaddingFrame& /*frame*/) {
993 DCHECK(false);
994 return false;
995}
996
997bool QuicDispatcher::OnPingFrame(const QuicPingFrame& /*frame*/) {
998 DCHECK(false);
999 return false;
1000}
1001
1002bool QuicDispatcher::OnRstStreamFrame(const QuicRstStreamFrame& /*frame*/) {
1003 DCHECK(false);
1004 return false;
1005}
1006
1007bool QuicDispatcher::OnConnectionCloseFrame(
1008 const QuicConnectionCloseFrame& /*frame*/) {
1009 DCHECK(false);
1010 return false;
1011}
1012
fkastenholz3c4eabf2019-04-22 07:49:59 -07001013bool QuicDispatcher::OnMaxStreamsFrame(const QuicMaxStreamsFrame& frame) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001014 return true;
1015}
1016
fkastenholz3c4eabf2019-04-22 07:49:59 -07001017bool QuicDispatcher::OnStreamsBlockedFrame(
1018 const QuicStreamsBlockedFrame& frame) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001019 return true;
1020}
1021
1022bool QuicDispatcher::OnStopSendingFrame(const QuicStopSendingFrame& /*frame*/) {
1023 DCHECK(false);
1024 return false;
1025}
1026
1027bool QuicDispatcher::OnPathChallengeFrame(
1028 const QuicPathChallengeFrame& /*frame*/) {
1029 DCHECK(false);
1030 return false;
1031}
1032
1033bool QuicDispatcher::OnPathResponseFrame(
1034 const QuicPathResponseFrame& /*frame*/) {
1035 DCHECK(false);
1036 return false;
1037}
1038
1039bool QuicDispatcher::OnGoAwayFrame(const QuicGoAwayFrame& /*frame*/) {
1040 DCHECK(false);
1041 return false;
1042}
1043
1044bool QuicDispatcher::OnWindowUpdateFrame(
1045 const QuicWindowUpdateFrame& /*frame*/) {
1046 DCHECK(false);
1047 return false;
1048}
1049
1050bool QuicDispatcher::OnBlockedFrame(const QuicBlockedFrame& frame) {
1051 DCHECK(false);
1052 return false;
1053}
1054
1055bool QuicDispatcher::OnNewConnectionIdFrame(
1056 const QuicNewConnectionIdFrame& frame) {
1057 DCHECK(false);
1058 return false;
1059}
1060
1061bool QuicDispatcher::OnRetireConnectionIdFrame(
1062 const QuicRetireConnectionIdFrame& frame) {
1063 DCHECK(false);
1064 return false;
1065}
1066
1067bool QuicDispatcher::OnNewTokenFrame(const QuicNewTokenFrame& frame) {
1068 DCHECK(false);
1069 return false;
1070}
1071
1072bool QuicDispatcher::OnMessageFrame(const QuicMessageFrame& frame) {
1073 DCHECK(false);
1074 return false;
1075}
1076
1077void QuicDispatcher::OnPacketComplete() {
1078 DCHECK(false);
1079}
1080
1081bool QuicDispatcher::IsValidStatelessResetToken(QuicUint128 token) const {
1082 DCHECK(false);
1083 return false;
1084}
1085
1086void QuicDispatcher::OnAuthenticatedIetfStatelessResetPacket(
1087 const QuicIetfStatelessResetPacket& packet) {
1088 DCHECK(false);
1089}
1090
1091void QuicDispatcher::OnExpiredPackets(
1092 QuicConnectionId connection_id,
1093 BufferedPacketList early_arrived_packets) {
1094 QUIC_CODE_COUNT(quic_reject_buffered_packets_expired);
1095 StatelesslyTerminateConnection(
1096 connection_id,
1097 early_arrived_packets.ietf_quic ? IETF_QUIC_LONG_HEADER_PACKET
1098 : GOOGLE_QUIC_PACKET,
fayang1de67892019-04-19 05:59:45 -07001099 /*version_flag=*/true, early_arrived_packets.version,
1100 QUIC_HANDSHAKE_FAILED, "Packets buffered for too long",
QUICHE teama6ef0a62019-03-07 20:34:33 -05001101 quic::QuicTimeWaitListManager::SEND_STATELESS_RESET);
1102}
1103
1104void QuicDispatcher::ProcessBufferedChlos(size_t max_connections_to_create) {
1105 // Reset the counter before starting creating connections.
1106 new_sessions_allowed_per_event_loop_ = max_connections_to_create;
1107 for (; new_sessions_allowed_per_event_loop_ > 0;
1108 --new_sessions_allowed_per_event_loop_) {
1109 QuicConnectionId connection_id;
1110 BufferedPacketList packet_list =
1111 buffered_packets_.DeliverPacketsForNextConnection(&connection_id);
1112 const std::list<BufferedPacket>& packets = packet_list.buffered_packets;
1113 if (packets.empty()) {
1114 return;
1115 }
QUICHE teamc65d1d12019-03-19 20:58:04 -07001116 QuicConnectionId original_connection_id = connection_id;
1117 connection_id =
1118 MaybeReplaceConnectionId(connection_id, packet_list.version);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001119 QuicSession* session =
1120 CreateQuicSession(connection_id, packets.front().peer_address,
1121 packet_list.alpn, packet_list.version);
QUICHE teamc65d1d12019-03-19 20:58:04 -07001122 if (original_connection_id != connection_id) {
1123 session->connection()->AddIncomingConnectionId(original_connection_id);
1124 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001125 QUIC_DLOG(INFO) << "Created new session for " << connection_id;
1126 session_map_.insert(std::make_pair(connection_id, QuicWrapUnique(session)));
1127 DeliverPacketsToSession(packets, session);
1128 }
1129}
1130
1131bool QuicDispatcher::HasChlosBuffered() const {
1132 return buffered_packets_.HasChlosBuffered();
1133}
1134
1135bool QuicDispatcher::ShouldCreateOrBufferPacketForConnection(
1136 QuicConnectionId connection_id,
1137 bool ietf_quic) {
dschinazi244f6dc2019-05-06 15:45:16 -07001138 QUIC_VLOG(1) << "Received packet from new connection " << connection_id;
QUICHE teama6ef0a62019-03-07 20:34:33 -05001139 return true;
1140}
1141
1142// Return true if there is any packet buffered in the store.
1143bool QuicDispatcher::HasBufferedPackets(QuicConnectionId connection_id) {
1144 return buffered_packets_.HasBufferedPackets(connection_id);
1145}
1146
1147void QuicDispatcher::OnBufferPacketFailure(EnqueuePacketResult result,
1148 QuicConnectionId connection_id) {
1149 QUIC_DLOG(INFO) << "Fail to buffer packet on connection " << connection_id
1150 << " because of " << result;
1151}
1152
QUICHE teama6ef0a62019-03-07 20:34:33 -05001153bool QuicDispatcher::ShouldAttemptCheapStatelessRejection() {
1154 return true;
1155}
1156
1157QuicTimeWaitListManager* QuicDispatcher::CreateQuicTimeWaitListManager() {
1158 return new QuicTimeWaitListManager(writer_.get(), this, helper_->GetClock(),
1159 alarm_factory_.get());
1160}
1161
1162void QuicDispatcher::BufferEarlyPacket(QuicConnectionId connection_id,
1163 bool ietf_quic,
1164 ParsedQuicVersion version) {
1165 bool is_new_connection = !buffered_packets_.HasBufferedPackets(connection_id);
1166 if (is_new_connection &&
1167 !ShouldCreateOrBufferPacketForConnection(connection_id, ietf_quic)) {
1168 return;
1169 }
1170
1171 EnqueuePacketResult rs = buffered_packets_.EnqueuePacket(
1172 connection_id, ietf_quic, *current_packet_, current_self_address_,
1173 current_peer_address_, /*is_chlo=*/false,
1174 /*alpn=*/"", version);
1175 if (rs != EnqueuePacketResult::SUCCESS) {
1176 OnBufferPacketFailure(rs, connection_id);
1177 }
1178}
1179
1180void QuicDispatcher::ProcessChlo(PacketHeaderFormat form,
1181 ParsedQuicVersion version) {
1182 if (!accept_new_connections_) {
1183 // Don't any create new connection.
1184 QUIC_CODE_COUNT(quic_reject_stop_accepting_new_connections);
1185 StatelesslyTerminateConnection(
fayang1de67892019-04-19 05:59:45 -07001186 current_connection_id(), form, /*version_flag=*/true, version,
1187 QUIC_HANDSHAKE_FAILED, "Stop accepting new connections",
QUICHE teama6ef0a62019-03-07 20:34:33 -05001188 quic::QuicTimeWaitListManager::SEND_STATELESS_RESET);
1189 // Time wait list will reject the packet correspondingly.
1190 time_wait_list_manager()->ProcessPacket(
1191 current_self_address(), current_peer_address(), current_connection_id(),
1192 form, GetPerPacketContext());
1193 return;
1194 }
1195 if (!buffered_packets_.HasBufferedPackets(current_connection_id_) &&
1196 !ShouldCreateOrBufferPacketForConnection(current_connection_id_,
1197 form != GOOGLE_QUIC_PACKET)) {
1198 return;
1199 }
1200 if (FLAGS_quic_allow_chlo_buffering &&
1201 new_sessions_allowed_per_event_loop_ <= 0) {
1202 // Can't create new session any more. Wait till next event loop.
1203 QUIC_BUG_IF(buffered_packets_.HasChloForConnection(current_connection_id_));
1204 EnqueuePacketResult rs = buffered_packets_.EnqueuePacket(
1205 current_connection_id_, form != GOOGLE_QUIC_PACKET, *current_packet_,
1206 current_self_address_, current_peer_address_,
fayangccbab732019-05-13 10:11:25 -07001207 /*is_chlo=*/true, current_alpn_, version);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001208 if (rs != EnqueuePacketResult::SUCCESS) {
1209 OnBufferPacketFailure(rs, current_connection_id_);
1210 }
1211 return;
1212 }
QUICHE teamc65d1d12019-03-19 20:58:04 -07001213
1214 QuicConnectionId original_connection_id = current_connection_id_;
1215 current_connection_id_ =
fayangccbab732019-05-13 10:11:25 -07001216 MaybeReplaceConnectionId(current_connection_id_, version);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001217 // Creates a new session and process all buffered packets for this connection.
fayangccbab732019-05-13 10:11:25 -07001218 QuicSession* session = CreateQuicSession(
1219 current_connection_id_, current_peer_address_, current_alpn_, version);
QUICHE teamc65d1d12019-03-19 20:58:04 -07001220 if (original_connection_id != current_connection_id_) {
1221 session->connection()->AddIncomingConnectionId(original_connection_id);
1222 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001223 QUIC_DLOG(INFO) << "Created new session for " << current_connection_id_;
1224 session_map_.insert(
1225 std::make_pair(current_connection_id_, QuicWrapUnique(session)));
1226 std::list<BufferedPacket> packets =
1227 buffered_packets_.DeliverPackets(current_connection_id_).buffered_packets;
1228 // Process CHLO at first.
1229 session->ProcessUdpPacket(current_self_address_, current_peer_address_,
1230 *current_packet_);
1231 // Deliver queued-up packets in the same order as they arrived.
1232 // Do this even when flag is off because there might be still some packets
1233 // buffered in the store before flag is turned off.
1234 DeliverPacketsToSession(packets, session);
1235 --new_sessions_allowed_per_event_loop_;
1236}
1237
1238const QuicSocketAddress QuicDispatcher::GetClientAddress() const {
1239 return current_peer_address_;
1240}
1241
1242bool QuicDispatcher::ShouldDestroySessionAsynchronously() {
1243 return true;
1244}
1245
1246void QuicDispatcher::SetLastError(QuicErrorCode error) {
1247 last_error_ = error;
1248}
1249
1250bool QuicDispatcher::OnUnauthenticatedUnknownPublicHeader(
1251 const QuicPacketHeader& header) {
1252 return true;
1253}
1254
1255class StatelessRejectorProcessDoneCallback
1256 : public StatelessRejector::ProcessDoneCallback {
1257 public:
1258 StatelessRejectorProcessDoneCallback(QuicDispatcher* dispatcher,
1259 ParsedQuicVersion first_version,
fayang1de67892019-04-19 05:59:45 -07001260 PacketHeaderFormat form,
1261 bool version_flag)
QUICHE teama6ef0a62019-03-07 20:34:33 -05001262 : dispatcher_(dispatcher),
1263 current_client_address_(dispatcher->current_client_address_),
1264 current_peer_address_(dispatcher->current_peer_address_),
1265 current_self_address_(dispatcher->current_self_address_),
1266 additional_context_(dispatcher->GetPerPacketContext()),
1267 current_packet_(
1268 dispatcher->current_packet_->Clone()), // Note: copies the packet
1269 first_version_(first_version),
fayang1de67892019-04-19 05:59:45 -07001270 current_packet_format_(form),
1271 current_version_flag_(version_flag) {}
QUICHE teama6ef0a62019-03-07 20:34:33 -05001272
1273 void Run(std::unique_ptr<StatelessRejector> rejector) override {
1274 if (additional_context_ != nullptr) {
1275 dispatcher_->RestorePerPacketContext(std::move(additional_context_));
1276 }
1277 dispatcher_->OnStatelessRejectorProcessDone(
1278 std::move(rejector), current_client_address_, current_peer_address_,
1279 current_self_address_, std::move(current_packet_), first_version_,
fayang1de67892019-04-19 05:59:45 -07001280 current_packet_format_, current_version_flag_);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001281 }
1282
1283 private:
1284 QuicDispatcher* dispatcher_;
1285 QuicSocketAddress current_client_address_;
1286 QuicSocketAddress current_peer_address_;
1287 QuicSocketAddress current_self_address_;
1288 // TODO(wub): Wrap all current_* variables into PerPacketContext. And rename
1289 // |additional_context_| to |context_|.
1290 std::unique_ptr<QuicPerPacketContext> additional_context_;
1291 std::unique_ptr<QuicReceivedPacket> current_packet_;
1292 ParsedQuicVersion first_version_;
1293 const PacketHeaderFormat current_packet_format_;
fayang1de67892019-04-19 05:59:45 -07001294 bool current_version_flag_;
QUICHE teama6ef0a62019-03-07 20:34:33 -05001295};
1296
1297void QuicDispatcher::MaybeRejectStatelessly(QuicConnectionId connection_id,
QUICHE teama6ef0a62019-03-07 20:34:33 -05001298 PacketHeaderFormat form,
fayang1de67892019-04-19 05:59:45 -07001299 bool version_flag,
QUICHE teama6ef0a62019-03-07 20:34:33 -05001300 ParsedQuicVersion version) {
1301 if (version.handshake_protocol == PROTOCOL_TLS1_3) {
1302 ProcessUnauthenticatedHeaderFate(kFateProcess, connection_id, form,
fayang1de67892019-04-19 05:59:45 -07001303 version_flag, version);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001304 return;
1305 // TODO(nharper): Support buffering non-ClientHello packets when using TLS.
1306 }
1307 // TODO(rch): This logic should probably live completely inside the rejector.
1308 if (!FLAGS_quic_allow_chlo_buffering ||
1309 !GetQuicReloadableFlag(quic_use_cheap_stateless_rejects) ||
1310 !GetQuicReloadableFlag(enable_quic_stateless_reject_support) ||
1311 !ShouldAttemptCheapStatelessRejection()) {
1312 // Not use cheap stateless reject.
1313 ChloAlpnExtractor alpn_extractor;
1314 if (FLAGS_quic_allow_chlo_buffering &&
1315 !ChloExtractor::Extract(*current_packet_, GetSupportedVersions(),
1316 config_->create_session_tag_indicators(),
1317 &alpn_extractor, connection_id.length())) {
1318 // Buffer non-CHLO packets.
1319 ProcessUnauthenticatedHeaderFate(kFateBuffer, connection_id, form,
fayang1de67892019-04-19 05:59:45 -07001320 version_flag, version);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001321 return;
1322 }
1323 current_alpn_ = alpn_extractor.ConsumeAlpn();
1324 ProcessUnauthenticatedHeaderFate(kFateProcess, connection_id, form,
fayang1de67892019-04-19 05:59:45 -07001325 version_flag, version);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001326 return;
1327 }
1328
1329 std::unique_ptr<StatelessRejector> rejector(new StatelessRejector(
1330 version, GetSupportedVersions(), crypto_config_, &compressed_certs_cache_,
1331 helper()->GetClock(), helper()->GetRandomGenerator(),
1332 current_packet_->length(), current_client_address_,
1333 current_self_address_));
1334 ChloValidator validator(session_helper_.get(), current_client_address_,
1335 current_peer_address_, current_self_address_,
1336 rejector.get());
1337 if (!ChloExtractor::Extract(*current_packet_, GetSupportedVersions(),
1338 config_->create_session_tag_indicators(),
1339 &validator, connection_id.length())) {
fayang1de67892019-04-19 05:59:45 -07001340 ProcessUnauthenticatedHeaderFate(kFateBuffer, connection_id, form,
1341 version_flag, version);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001342 return;
1343 }
1344 current_alpn_ = validator.ConsumeAlpn();
1345
1346 if (!validator.can_accept()) {
1347 // This CHLO is prohibited by policy.
1348 QUIC_CODE_COUNT(quic_reject_cant_accept_chlo);
fayangf7c569c2019-05-07 11:56:51 -07001349 StatelessConnectionTerminator terminator(connection_id, version, helper(),
QUICHE teama6ef0a62019-03-07 20:34:33 -05001350 time_wait_list_manager_.get());
1351 terminator.CloseConnection(QUIC_HANDSHAKE_FAILED, validator.error_details(),
1352 form != GOOGLE_QUIC_PACKET);
wub2b5942f2019-04-11 13:22:50 -07001353 QuicSession::RecordConnectionCloseAtServer(
1354 QUIC_HANDSHAKE_FAILED, ConnectionCloseSource::FROM_SELF);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001355 ProcessUnauthenticatedHeaderFate(kFateTimeWait, connection_id, form,
fayang1de67892019-04-19 05:59:45 -07001356 version_flag, version);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001357 return;
1358 }
1359
1360 // If we were able to make a decision about this CHLO based purely on the
1361 // information available in OnChlo, just invoke the done callback immediately.
1362 if (rejector->state() != StatelessRejector::UNKNOWN) {
fayangf7c569c2019-05-07 11:56:51 -07001363 ProcessStatelessRejectorState(std::move(rejector), version, form,
1364 version_flag);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001365 return;
1366 }
1367
1368 // Insert into set of connection IDs to buffer
1369 const bool ok =
1370 temporarily_buffered_connections_.insert(connection_id).second;
1371 QUIC_BUG_IF(!ok)
1372 << "Processing multiple stateless rejections for connection ID "
1373 << connection_id;
1374
1375 // Continue stateless rejector processing
1376 std::unique_ptr<StatelessRejectorProcessDoneCallback> cb(
fayang1de67892019-04-19 05:59:45 -07001377 new StatelessRejectorProcessDoneCallback(this, version, form,
1378 version_flag));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001379 StatelessRejector::Process(std::move(rejector), std::move(cb));
1380}
1381
1382void QuicDispatcher::OnStatelessRejectorProcessDone(
1383 std::unique_ptr<StatelessRejector> rejector,
1384 const QuicSocketAddress& current_client_address,
1385 const QuicSocketAddress& current_peer_address,
1386 const QuicSocketAddress& current_self_address,
1387 std::unique_ptr<QuicReceivedPacket> current_packet,
1388 ParsedQuicVersion first_version,
fayang1de67892019-04-19 05:59:45 -07001389 PacketHeaderFormat current_packet_format,
1390 bool current_version_flag) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001391 // Reset current_* to correspond to the packet which initiated the stateless
1392 // reject logic.
1393 current_client_address_ = current_client_address;
1394 current_peer_address_ = current_peer_address;
1395 current_self_address_ = current_self_address;
1396 current_packet_ = current_packet.get();
1397 current_connection_id_ = rejector->connection_id();
fayangccbab732019-05-13 10:11:25 -07001398 if (!no_framer_) {
1399 framer_.set_version(first_version);
1400 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001401
1402 // Stop buffering packets on this connection
1403 const auto num_erased =
1404 temporarily_buffered_connections_.erase(rejector->connection_id());
1405 QUIC_BUG_IF(num_erased != 1) << "Completing stateless rejection logic for "
1406 "non-buffered connection ID "
1407 << rejector->connection_id();
1408
1409 // If this connection has gone into time-wait during the async processing,
1410 // don't proceed.
1411 if (time_wait_list_manager_->IsConnectionIdInTimeWait(
1412 rejector->connection_id())) {
1413 time_wait_list_manager_->ProcessPacket(
1414 current_self_address, current_peer_address, rejector->connection_id(),
1415 current_packet_format, GetPerPacketContext());
1416 return;
1417 }
1418
fayangf7c569c2019-05-07 11:56:51 -07001419 ProcessStatelessRejectorState(std::move(rejector), first_version,
fayang1de67892019-04-19 05:59:45 -07001420 current_packet_format, current_version_flag);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001421}
1422
1423void QuicDispatcher::ProcessStatelessRejectorState(
1424 std::unique_ptr<StatelessRejector> rejector,
fayangf7c569c2019-05-07 11:56:51 -07001425 ParsedQuicVersion first_version,
fayang1de67892019-04-19 05:59:45 -07001426 PacketHeaderFormat form,
1427 bool version_flag) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001428 QuicPacketFate fate;
1429 switch (rejector->state()) {
1430 case StatelessRejector::FAILED: {
1431 // There was an error processing the client hello.
1432 QUIC_CODE_COUNT(quic_reject_error_processing_chlo);
1433 StatelessConnectionTerminator terminator(rejector->connection_id(),
fayangf7c569c2019-05-07 11:56:51 -07001434 first_version, helper(),
QUICHE teama6ef0a62019-03-07 20:34:33 -05001435 time_wait_list_manager_.get());
1436 terminator.CloseConnection(rejector->error(), rejector->error_details(),
1437 form != GOOGLE_QUIC_PACKET);
1438 fate = kFateTimeWait;
1439 break;
1440 }
1441
1442 case StatelessRejector::UNSUPPORTED:
1443 // Cheap stateless rejects are not supported so process the packet.
1444 fate = kFateProcess;
1445 break;
1446
1447 case StatelessRejector::ACCEPTED:
1448 // Contains a valid CHLO, so process the packet and create a connection.
1449 fate = kFateProcess;
1450 break;
1451
1452 case StatelessRejector::REJECTED: {
fayangccbab732019-05-13 10:11:25 -07001453 QUIC_BUG_IF(!no_framer_ && first_version != framer_.version())
fayangf7c569c2019-05-07 11:56:51 -07001454 << "SREJ: Client's version: "
1455 << QuicVersionToString(first_version.transport_version)
QUICHE teama6ef0a62019-03-07 20:34:33 -05001456 << " is different from current dispatcher framer's version: "
1457 << QuicVersionToString(framer_.transport_version());
1458 StatelessConnectionTerminator terminator(rejector->connection_id(),
fayangf7c569c2019-05-07 11:56:51 -07001459 first_version, helper(),
QUICHE teama6ef0a62019-03-07 20:34:33 -05001460 time_wait_list_manager_.get());
1461 terminator.RejectConnection(
1462 rejector->reply().GetSerialized().AsStringPiece(),
1463 form != GOOGLE_QUIC_PACKET);
wub2b5942f2019-04-11 13:22:50 -07001464 QuicSession::RecordConnectionCloseAtServer(
1465 QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT,
1466 ConnectionCloseSource::FROM_SELF);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001467 OnConnectionRejectedStatelessly();
1468 fate = kFateTimeWait;
1469 break;
1470 }
1471
1472 default:
1473 QUIC_BUG << "Rejector has invalid state " << rejector->state();
1474 fate = kFateDrop;
1475 break;
1476 }
1477 ProcessUnauthenticatedHeaderFate(fate, rejector->connection_id(), form,
fayang1de67892019-04-19 05:59:45 -07001478 version_flag, rejector->version());
QUICHE teama6ef0a62019-03-07 20:34:33 -05001479}
1480
1481const QuicTransportVersionVector&
1482QuicDispatcher::GetSupportedTransportVersions() {
1483 return version_manager_->GetSupportedTransportVersions();
1484}
1485
1486const ParsedQuicVersionVector& QuicDispatcher::GetSupportedVersions() {
1487 return version_manager_->GetSupportedVersions();
1488}
1489
1490void QuicDispatcher::DeliverPacketsToSession(
1491 const std::list<BufferedPacket>& packets,
1492 QuicSession* session) {
1493 for (const BufferedPacket& packet : packets) {
1494 session->ProcessUdpPacket(packet.self_address, packet.peer_address,
1495 *(packet.packet));
1496 }
1497}
1498
1499void QuicDispatcher::DisableFlagValidation() {
fayangccbab732019-05-13 10:11:25 -07001500 if (!no_framer_) {
1501 framer_.set_validate_flags(false);
1502 }
1503}
1504
1505bool QuicDispatcher::IsSupportedVersion(const ParsedQuicVersion version) {
1506 if (!no_framer_) {
1507 return framer_.IsSupportedVersion(version);
1508 }
1509 for (const ParsedQuicVersion& supported_version :
1510 version_manager_->GetSupportedVersions()) {
1511 if (version == supported_version) {
1512 return true;
1513 }
1514 }
1515 return false;
QUICHE teama6ef0a62019-03-07 20:34:33 -05001516}
1517
1518} // namespace quic