blob: 049a63fc28fbb5ec5947bbb43968265cd0940653 [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:
dschinazi7b9278c2019-05-20 07:36:21 -0700118 StatelessConnectionTerminator(QuicConnectionId server_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)
dschinazi7b9278c2019-05-20 07:36:21 -0700122 : server_connection_id_(server_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()),
dschinazi7b9278c2019-05-20 07:36:21 -0700128 creator_(server_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(
dschinazi7b9278c2019-05-20 07:36:21 -0700157 server_connection_id_, ietf_quic,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500158 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 }
nharper46833c32019-05-15 21:33:05 -0700189 if (offset < reject.length() &&
190 !QuicVersionUsesCryptoFrames(framer_.transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500191 DCHECK(!creator_.HasRoomForStreamFrame(
fayangf7c569c2019-05-07 11:56:51 -0700192 QuicUtils::GetCryptoStreamId(framer_.transport_version()), offset,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500193 frame.stream_frame.data_length));
194 }
195 creator_.Flush();
196 }
197 time_wait_list_manager_->AddConnectionIdToTimeWait(
dschinazi7b9278c2019-05-20 07:36:21 -0700198 server_connection_id_, ietf_quic,
QUICHE team6987b4a2019-03-15 16:23:04 -0700199 QuicTimeWaitListManager::SEND_TERMINATION_PACKETS, ENCRYPTION_INITIAL,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500200 collector_.packets());
dschinazi7b9278c2019-05-20 07:36:21 -0700201 DCHECK(time_wait_list_manager_->IsConnectionIdInTimeWait(
202 server_connection_id_));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500203 }
204
205 private:
dschinazi7b9278c2019-05-20 07:36:21 -0700206 QuicConnectionId server_connection_id_;
fayangf7c569c2019-05-07 11:56:51 -0700207 QuicFramer framer_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500208 // Set as the visitor of |creator_| to collect any generated packets.
209 PacketCollector collector_;
210 QuicPacketCreator creator_;
211 QuicTimeWaitListManager* time_wait_list_manager_;
212};
213
214// Class which extracts the ALPN from a CHLO packet.
215class ChloAlpnExtractor : public ChloExtractor::Delegate {
216 public:
217 void OnChlo(QuicTransportVersion version,
dschinazi7b9278c2019-05-20 07:36:21 -0700218 QuicConnectionId server_connection_id,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500219 const CryptoHandshakeMessage& chlo) override {
220 QuicStringPiece alpn_value;
221 if (chlo.GetStringPiece(kALPN, &alpn_value)) {
vasilvvc48c8712019-03-11 13:38:16 -0700222 alpn_ = std::string(alpn_value);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500223 }
224 }
225
vasilvvc48c8712019-03-11 13:38:16 -0700226 std::string&& ConsumeAlpn() { return std::move(alpn_); }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500227
228 private:
vasilvvc48c8712019-03-11 13:38:16 -0700229 std::string alpn_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500230};
231
232// Class which sits between the ChloExtractor and the StatelessRejector
233// to give the QuicDispatcher a chance to apply policy checks to the CHLO.
234class ChloValidator : public ChloAlpnExtractor {
235 public:
236 ChloValidator(QuicCryptoServerStream::Helper* helper,
237 const QuicSocketAddress& client_address,
238 const QuicSocketAddress& peer_address,
239 const QuicSocketAddress& self_address,
240 StatelessRejector* rejector)
241 : helper_(helper),
242 client_address_(client_address),
243 peer_address_(peer_address),
244 self_address_(self_address),
245 rejector_(rejector),
246 can_accept_(false),
247 error_details_("CHLO not processed") {}
248
249 // ChloExtractor::Delegate implementation.
250 void OnChlo(QuicTransportVersion version,
dschinazi7b9278c2019-05-20 07:36:21 -0700251 QuicConnectionId server_connection_id,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500252 const CryptoHandshakeMessage& chlo) override {
253 // Extract the ALPN
dschinazi7b9278c2019-05-20 07:36:21 -0700254 ChloAlpnExtractor::OnChlo(version, server_connection_id, chlo);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500255 if (helper_->CanAcceptClientHello(chlo, client_address_, peer_address_,
256 self_address_, &error_details_)) {
257 can_accept_ = true;
258 rejector_->OnChlo(
dschinazi7b9278c2019-05-20 07:36:21 -0700259 version, server_connection_id,
260 helper_->GenerateConnectionIdForReject(version, server_connection_id),
261 chlo);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500262 }
263 }
264
265 bool can_accept() const { return can_accept_; }
266
vasilvvc48c8712019-03-11 13:38:16 -0700267 const std::string& error_details() const { return error_details_; }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500268
269 private:
270 QuicCryptoServerStream::Helper* helper_; // Unowned.
271 // client_address_ and peer_address_ could be different values for proxy
272 // connections.
273 QuicSocketAddress client_address_;
274 QuicSocketAddress peer_address_;
275 QuicSocketAddress self_address_;
276 StatelessRejector* rejector_; // Unowned.
277 bool can_accept_;
vasilvvc48c8712019-03-11 13:38:16 -0700278 std::string error_details_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500279};
280
281} // namespace
282
283QuicDispatcher::QuicDispatcher(
284 const QuicConfig* config,
285 const QuicCryptoServerConfig* crypto_config,
286 QuicVersionManager* version_manager,
287 std::unique_ptr<QuicConnectionHelperInterface> helper,
288 std::unique_ptr<QuicCryptoServerStream::Helper> session_helper,
289 std::unique_ptr<QuicAlarmFactory> alarm_factory,
290 uint8_t expected_connection_id_length)
291 : config_(config),
292 crypto_config_(crypto_config),
293 compressed_certs_cache_(
294 QuicCompressedCertsCache::kQuicCompressedCertsCacheSize),
295 helper_(std::move(helper)),
296 session_helper_(std::move(session_helper)),
297 alarm_factory_(std::move(alarm_factory)),
298 delete_sessions_alarm_(
299 alarm_factory_->CreateAlarm(new DeleteSessionsAlarm(this))),
300 buffered_packets_(this, helper_->GetClock(), alarm_factory_.get()),
301 current_packet_(nullptr),
302 version_manager_(version_manager),
303 framer_(GetSupportedVersions(),
304 /*unused*/ QuicTime::Zero(),
305 Perspective::IS_SERVER,
306 expected_connection_id_length),
307 last_error_(QUIC_NO_ERROR),
308 new_sessions_allowed_per_event_loop_(0u),
QUICHE team963d57e2019-03-21 10:58:47 -0700309 accept_new_connections_(true),
dschinazi7b9278c2019-05-20 07:36:21 -0700310 allow_short_initial_server_connection_ids_(false),
fayangccbab732019-05-13 10:11:25 -0700311 last_version_label_(0),
312 expected_connection_id_length_(expected_connection_id_length),
313 should_update_expected_connection_id_length_(false),
314 no_framer_(GetQuicRestartFlag(quic_no_framer_object_in_dispatcher)) {
315 if (!no_framer_) {
316 framer_.set_visitor(this);
317 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500318}
319
320QuicDispatcher::~QuicDispatcher() {
321 session_map_.clear();
322 closed_session_list_.clear();
323}
324
325void QuicDispatcher::InitializeWithWriter(QuicPacketWriter* writer) {
326 DCHECK(writer_ == nullptr);
327 writer_.reset(writer);
328 time_wait_list_manager_.reset(CreateQuicTimeWaitListManager());
329}
330
331void QuicDispatcher::ProcessPacket(const QuicSocketAddress& self_address,
332 const QuicSocketAddress& peer_address,
333 const QuicReceivedPacket& packet) {
334 current_self_address_ = self_address;
335 current_peer_address_ = peer_address;
336 // GetClientAddress must be called after current_peer_address_ is set.
337 current_client_address_ = GetClientAddress();
338 current_packet_ = &packet;
fayangccbab732019-05-13 10:11:25 -0700339 if (!no_framer_) {
340 // ProcessPacket will cause the packet to be dispatched in
341 // OnUnauthenticatedPublicHeader, or sent to the time wait list manager
342 // in OnUnauthenticatedHeader.
343 framer_.ProcessPacket(packet);
344 // TODO(rjshade): Return a status describing if/why a packet was dropped,
345 // and log somehow. Maybe expose as a varz.
346 return;
347 }
348 QUIC_RESTART_FLAG_COUNT(quic_no_framer_object_in_dispatcher);
349 QuicPacketHeader header;
350 uint8_t destination_connection_id_length;
fayang1f123502019-05-14 08:05:16 -0700351 std::string detailed_error;
fayangccbab732019-05-13 10:11:25 -0700352 const QuicErrorCode error = QuicFramer::ProcessPacketDispatcher(
353 packet, expected_connection_id_length_, &header.form,
354 &header.version_flag, &last_version_label_,
355 &destination_connection_id_length, &header.destination_connection_id,
356 &detailed_error);
357 if (error != QUIC_NO_ERROR) {
358 // Packet has framing error.
359 SetLastError(error);
360 QUIC_DLOG(ERROR) << detailed_error;
361 return;
362 }
363 header.version = ParseQuicVersionLabel(last_version_label_);
364 if (destination_connection_id_length != expected_connection_id_length_ &&
365 !should_update_expected_connection_id_length_ &&
366 !QuicUtils::VariableLengthConnectionIdAllowedForVersion(
367 header.version.transport_version)) {
368 SetLastError(QUIC_INVALID_PACKET_HEADER);
369 QUIC_DLOG(ERROR) << "Invalid Connection Id Length";
370 return;
371 }
372 if (should_update_expected_connection_id_length_) {
373 expected_connection_id_length_ = destination_connection_id_length;
374 }
375 // TODO(fayang): Instead of passing in QuicPacketHeader, pass format,
376 // version_flag, version and destination_connection_id. Combine
377 // OnUnauthenticatedPublicHeader and OnUnauthenticatedHeader to a single
378 // function when deprecating quic_no_framer_object_in_dispatcher.
379 if (!OnUnauthenticatedPublicHeader(header)) {
380 return;
381 }
382 OnUnauthenticatedHeader(header);
383 // TODO(wub): Consider invalidate the current_* variables so processing of
384 // the next packet does not use them incorrectly.
QUICHE teama6ef0a62019-03-07 20:34:33 -0500385}
386
dschinazi7b9278c2019-05-20 07:36:21 -0700387QuicConnectionId QuicDispatcher::MaybeReplaceServerConnectionId(
388 QuicConnectionId server_connection_id,
QUICHE teamc65d1d12019-03-19 20:58:04 -0700389 ParsedQuicVersion version) {
390 const uint8_t expected_connection_id_length =
fayangccbab732019-05-13 10:11:25 -0700391 no_framer_ ? expected_connection_id_length_
392 : framer_.GetExpectedConnectionIdLength();
dschinazi7b9278c2019-05-20 07:36:21 -0700393 if (server_connection_id.length() == expected_connection_id_length) {
394 return server_connection_id;
QUICHE teamc65d1d12019-03-19 20:58:04 -0700395 }
396 DCHECK(QuicUtils::VariableLengthConnectionIdAllowedForVersion(
397 version.transport_version));
dschinazi7b9278c2019-05-20 07:36:21 -0700398 auto it = connection_id_map_.find(server_connection_id);
QUICHE teamc65d1d12019-03-19 20:58:04 -0700399 if (it != connection_id_map_.end()) {
400 return it->second;
401 }
402 QuicConnectionId new_connection_id =
403 session_helper_->GenerateConnectionIdForReject(version.transport_version,
dschinazi7b9278c2019-05-20 07:36:21 -0700404 server_connection_id);
QUICHE teamc65d1d12019-03-19 20:58:04 -0700405 DCHECK_EQ(expected_connection_id_length, new_connection_id.length());
dschinazi7b9278c2019-05-20 07:36:21 -0700406 connection_id_map_.insert(
407 std::make_pair(server_connection_id, new_connection_id));
408 QUIC_DLOG(INFO) << "Replacing incoming connection ID " << server_connection_id
QUICHE teamc65d1d12019-03-19 20:58:04 -0700409 << " with " << new_connection_id;
410 return new_connection_id;
411}
412
QUICHE teama6ef0a62019-03-07 20:34:33 -0500413bool QuicDispatcher::OnUnauthenticatedPublicHeader(
414 const QuicPacketHeader& header) {
dschinazi7b9278c2019-05-20 07:36:21 -0700415 current_server_connection_id_ = header.destination_connection_id;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500416
417 // Port zero is only allowed for unidirectional UDP, so is disallowed by QUIC.
418 // Given that we can't even send a reply rejecting the packet, just drop the
419 // packet.
420 if (current_peer_address_.port() == 0) {
421 return false;
422 }
423
424 // The dispatcher requires the connection ID to be present in order to
425 // look up the matching QuicConnection, so we error out if it is absent.
426 if (header.destination_connection_id_included != CONNECTION_ID_PRESENT) {
427 return false;
428 }
dschinazi7b9278c2019-05-20 07:36:21 -0700429 QuicConnectionId server_connection_id = header.destination_connection_id;
QUICHE team8e2e4532019-03-14 14:37:56 -0700430
QUICHE team963d57e2019-03-21 10:58:47 -0700431 // The IETF spec requires the client to generate an initial server
432 // connection ID that is at least 64 bits long. After that initial
433 // connection ID, the dispatcher picks a new one of its expected length.
434 // Therefore we should never receive a connection ID that is smaller
435 // than 64 bits and smaller than what we expect.
fayangccbab732019-05-13 10:11:25 -0700436 const uint8_t expected_connection_id_length =
437 no_framer_ ? expected_connection_id_length_
438 : framer_.GetExpectedConnectionIdLength();
dschinazi7b9278c2019-05-20 07:36:21 -0700439 if (server_connection_id.length() < kQuicMinimumInitialConnectionIdLength &&
440 server_connection_id.length() < expected_connection_id_length &&
441 !allow_short_initial_server_connection_ids_) {
QUICHE team963d57e2019-03-21 10:58:47 -0700442 DCHECK(header.version_flag);
443 DCHECK(QuicUtils::VariableLengthConnectionIdAllowedForVersion(
444 header.version.transport_version));
445 QUIC_DLOG(INFO) << "Packet with short destination connection ID "
dschinazi7b9278c2019-05-20 07:36:21 -0700446 << server_connection_id << " expected "
fayangccbab732019-05-13 10:11:25 -0700447 << static_cast<int>(expected_connection_id_length);
dschinazi7b9278c2019-05-20 07:36:21 -0700448 ProcessUnauthenticatedHeaderFate(kFateTimeWait, server_connection_id,
449 header.form, header.version_flag,
450 header.version);
QUICHE team963d57e2019-03-21 10:58:47 -0700451 return false;
452 }
453
QUICHE teama6ef0a62019-03-07 20:34:33 -0500454 // Packets with connection IDs for active connections are processed
455 // immediately.
dschinazi7b9278c2019-05-20 07:36:21 -0700456 auto it = session_map_.find(server_connection_id);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500457 if (it != session_map_.end()) {
dschinazi7b9278c2019-05-20 07:36:21 -0700458 DCHECK(!buffered_packets_.HasBufferedPackets(server_connection_id));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500459 it->second->ProcessUdpPacket(current_self_address_, current_peer_address_,
460 *current_packet_);
461 return false;
462 }
463
dschinazi7b9278c2019-05-20 07:36:21 -0700464 if (buffered_packets_.HasChloForConnection(server_connection_id)) {
465 BufferEarlyPacket(server_connection_id, header.form != GOOGLE_QUIC_PACKET,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500466 header.version);
467 return false;
468 }
469
470 // Check if we are buffering packets for this connection ID
dschinazi7b9278c2019-05-20 07:36:21 -0700471 if (temporarily_buffered_connections_.find(server_connection_id) !=
QUICHE teama6ef0a62019-03-07 20:34:33 -0500472 temporarily_buffered_connections_.end()) {
473 // This packet was received while the a CHLO for the same connection ID was
474 // being processed. Buffer it.
dschinazi7b9278c2019-05-20 07:36:21 -0700475 BufferEarlyPacket(server_connection_id, header.form != GOOGLE_QUIC_PACKET,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500476 header.version);
477 return false;
478 }
479
480 if (!OnUnauthenticatedUnknownPublicHeader(header)) {
481 return false;
482 }
483
484 // If the packet is a public reset for a connection ID that is not active,
485 // there is nothing we must do or can do.
486 if (header.reset_flag) {
487 return false;
488 }
489
dschinazi7b9278c2019-05-20 07:36:21 -0700490 if (time_wait_list_manager_->IsConnectionIdInTimeWait(server_connection_id)) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500491 // This connection ID is already in time-wait state.
492 time_wait_list_manager_->ProcessPacket(
493 current_self_address_, current_peer_address_,
494 header.destination_connection_id, header.form, GetPerPacketContext());
495 return false;
496 }
497
498 // The packet has an unknown connection ID.
499
500 // Unless the packet provides a version, assume that we can continue
501 // processing using our preferred version.
502 ParsedQuicVersion version = GetSupportedVersions().front();
503 if (header.version_flag) {
504 ParsedQuicVersion packet_version = header.version;
fayangccbab732019-05-13 10:11:25 -0700505 if (!no_framer_ && framer_.supported_versions() != GetSupportedVersions()) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500506 // Reset framer's version if version flags change in flight.
507 framer_.SetSupportedVersions(GetSupportedVersions());
508 }
fayangccbab732019-05-13 10:11:25 -0700509 if (!IsSupportedVersion(packet_version)) {
510 if (ShouldCreateSessionForUnknownVersion(
511 no_framer_ ? last_version_label_
512 : framer_.last_version_label())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500513 return true;
514 }
515 if (!crypto_config()->validate_chlo_size() ||
516 current_packet_->length() >= kMinPacketSizeForVersionNegotiation) {
517 // Since the version is not supported, send a version negotiation
518 // packet and stop processing the current packet.
519 time_wait_list_manager()->SendVersionNegotiationPacket(
dschinazi7b9278c2019-05-20 07:36:21 -0700520 server_connection_id, header.form != GOOGLE_QUIC_PACKET,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500521 GetSupportedVersions(), current_self_address_,
522 current_peer_address_, GetPerPacketContext());
523 }
524 return false;
525 }
526 version = packet_version;
527 }
fayangccbab732019-05-13 10:11:25 -0700528 if (!no_framer_) {
529 // Set the framer's version and continue processing.
530 framer_.set_version(version);
531 }
nharper55fa6132019-05-07 19:37:21 -0700532
533 if (version.HasHeaderProtection()) {
534 ProcessHeader(header);
535 return false;
536 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500537 return true;
538}
539
540bool QuicDispatcher::OnUnauthenticatedHeader(const QuicPacketHeader& header) {
nharper55fa6132019-05-07 19:37:21 -0700541 ProcessHeader(header);
542 return false;
543}
544
545void QuicDispatcher::ProcessHeader(const QuicPacketHeader& header) {
dschinazi7b9278c2019-05-20 07:36:21 -0700546 QuicConnectionId server_connection_id = header.destination_connection_id;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500547 // Packet's connection ID is unknown. Apply the validity checks.
548 QuicPacketFate fate = ValidityChecks(header);
549 if (fate == kFateProcess) {
550 // Execute stateless rejection logic to determine the packet fate, then
551 // invoke ProcessUnauthenticatedHeaderFate.
dschinazi7b9278c2019-05-20 07:36:21 -0700552 MaybeRejectStatelessly(server_connection_id, header.form,
553 header.version_flag, header.version);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500554 } else {
555 // If the fate is already known, process it without executing stateless
556 // rejection logic.
dschinazi7b9278c2019-05-20 07:36:21 -0700557 ProcessUnauthenticatedHeaderFate(fate, server_connection_id, header.form,
fayang1de67892019-04-19 05:59:45 -0700558 header.version_flag, header.version);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500559 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500560}
561
562void QuicDispatcher::ProcessUnauthenticatedHeaderFate(
563 QuicPacketFate fate,
dschinazi7b9278c2019-05-20 07:36:21 -0700564 QuicConnectionId server_connection_id,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500565 PacketHeaderFormat form,
fayang1de67892019-04-19 05:59:45 -0700566 bool version_flag,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500567 ParsedQuicVersion version) {
568 switch (fate) {
569 case kFateProcess: {
570 ProcessChlo(form, version);
571 break;
572 }
573 case kFateTimeWait:
574 // MaybeRejectStatelessly or OnExpiredPackets might have already added the
575 // connection to time wait, in which case it should not be added again.
576 if (!GetQuicReloadableFlag(quic_use_cheap_stateless_rejects) ||
dschinazi7b9278c2019-05-20 07:36:21 -0700577 !time_wait_list_manager_->IsConnectionIdInTimeWait(
578 server_connection_id)) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500579 // Add this connection_id to the time-wait state, to safely reject
580 // future packets.
dschinazi7b9278c2019-05-20 07:36:21 -0700581 QUIC_DLOG(INFO) << "Adding connection ID " << server_connection_id
QUICHE team8e2e4532019-03-14 14:37:56 -0700582 << " to time-wait list.";
QUICHE teama6ef0a62019-03-07 20:34:33 -0500583 QUIC_CODE_COUNT(quic_reject_fate_time_wait);
584 StatelesslyTerminateConnection(
dschinazi7b9278c2019-05-20 07:36:21 -0700585 server_connection_id, form, version_flag, version,
586 QUIC_HANDSHAKE_FAILED, "Reject connection",
QUICHE teama6ef0a62019-03-07 20:34:33 -0500587 quic::QuicTimeWaitListManager::SEND_STATELESS_RESET);
588 }
dschinazi7b9278c2019-05-20 07:36:21 -0700589 DCHECK(time_wait_list_manager_->IsConnectionIdInTimeWait(
590 server_connection_id));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500591 time_wait_list_manager_->ProcessPacket(
dschinazi7b9278c2019-05-20 07:36:21 -0700592 current_self_address_, current_peer_address_, server_connection_id,
593 form, GetPerPacketContext());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500594
595 // Any packets which were buffered while the stateless rejector logic was
596 // running should be discarded. Do not inform the time wait list manager,
597 // which should already have a made a decision about sending a reject
598 // based on the CHLO alone.
dschinazi7b9278c2019-05-20 07:36:21 -0700599 buffered_packets_.DiscardPackets(server_connection_id);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500600 break;
601 case kFateBuffer:
602 // This packet is a non-CHLO packet which has arrived before the
603 // corresponding CHLO, *or* this packet was received while the
604 // corresponding CHLO was being processed. Buffer it.
dschinazi7b9278c2019-05-20 07:36:21 -0700605 BufferEarlyPacket(server_connection_id, form != GOOGLE_QUIC_PACKET,
606 version);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500607 break;
608 case kFateDrop:
609 // Do nothing with the packet.
610 break;
611 }
612}
613
614QuicDispatcher::QuicPacketFate QuicDispatcher::ValidityChecks(
615 const QuicPacketHeader& header) {
616 // To have all the checks work properly without tears, insert any new check
617 // into the framework of this method in the section for checks that return the
618 // check's fate value. The sections for checks must be ordered with the
619 // highest priority fate first.
620
621 // Checks that return kFateDrop.
622
623 // Checks that return kFateTimeWait.
624
625 // All packets within a connection sent by a client before receiving a
626 // response from the server are required to have the version negotiation flag
627 // set. Since this may be a client continuing a connection we lost track of
628 // via server restart, send a rejection to fast-fail the connection.
629 if (!header.version_flag) {
630 QUIC_DLOG(INFO)
631 << "Packet without version arrived for unknown connection ID "
632 << header.destination_connection_id;
633 return kFateTimeWait;
634 }
635
fayangccbab732019-05-13 10:11:25 -0700636 if (no_framer_) {
637 // Let the connection parse and validate packet number.
638 return kFateProcess;
639 }
640
QUICHE teama6ef0a62019-03-07 20:34:33 -0500641 // initial packet number of 0 is always invalid.
nharper55fa6132019-05-07 19:37:21 -0700642 if (!framer_.version().HasHeaderProtection()) {
643 if (!header.packet_number.IsInitialized()) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500644 return kFateTimeWait;
645 }
nharper55fa6132019-05-07 19:37:21 -0700646 if (GetQuicRestartFlag(quic_enable_accept_random_ipn)) {
647 QUIC_RESTART_FLAG_COUNT_N(quic_enable_accept_random_ipn, 1, 2);
648 // Accepting Initial Packet Numbers in 1...((2^31)-1) range... check
649 // maximum accordingly.
650 if (header.packet_number > MaxRandomInitialPacketNumber()) {
651 return kFateTimeWait;
652 }
653 } else {
654 // Count those that would have been accepted if FLAGS..random_ipn
655 // were true -- to detect/diagnose potential issues prior to
656 // enabling the flag.
657 if ((header.packet_number >
658 QuicPacketNumber(kMaxReasonableInitialPacketNumber)) &&
659 (header.packet_number <= MaxRandomInitialPacketNumber())) {
660 QUIC_CODE_COUNT_N(had_possibly_random_ipn, 1, 2);
661 }
662 // Check that the sequence number is within the range that the client is
663 // expected to send before receiving a response from the server.
664 if (header.packet_number >
665 QuicPacketNumber(kMaxReasonableInitialPacketNumber)) {
666 return kFateTimeWait;
667 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500668 }
669 }
670 return kFateProcess;
671}
672
673void QuicDispatcher::CleanUpSession(SessionMap::iterator it,
674 QuicConnection* connection,
675 bool should_close_statelessly,
676 ConnectionCloseSource source) {
677 write_blocked_list_.erase(connection);
678 if (should_close_statelessly) {
679 DCHECK(connection->termination_packets() != nullptr &&
680 !connection->termination_packets()->empty());
681 }
682 QuicTimeWaitListManager::TimeWaitAction action =
683 QuicTimeWaitListManager::SEND_STATELESS_RESET;
684 if (connection->termination_packets() != nullptr &&
685 !connection->termination_packets()->empty()) {
686 action = QuicTimeWaitListManager::SEND_TERMINATION_PACKETS;
fayang1de67892019-04-19 05:59:45 -0700687 } else if (connection->transport_version() > QUIC_VERSION_43 ||
688 GetQuicReloadableFlag(quic_terminate_gquic_connection_as_ietf)) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500689 if (!connection->IsHandshakeConfirmed()) {
fayang1de67892019-04-19 05:59:45 -0700690 if (connection->transport_version() <= QUIC_VERSION_43) {
691 QUIC_CODE_COUNT(gquic_add_to_time_wait_list_with_handshake_failed);
692 } else {
693 QUIC_CODE_COUNT(quic_v44_add_to_time_wait_list_with_handshake_failed);
694 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500695 action = QuicTimeWaitListManager::SEND_TERMINATION_PACKETS;
696 // This serializes a connection close termination packet with error code
697 // QUIC_HANDSHAKE_FAILED and adds the connection to the time wait list.
698 StatelesslyTerminateConnection(
fayang1de67892019-04-19 05:59:45 -0700699 connection->connection_id(),
700 connection->transport_version() > QUIC_VERSION_43
701 ? IETF_QUIC_LONG_HEADER_PACKET
702 : GOOGLE_QUIC_PACKET,
703 /*version_flag=*/true, connection->version(), QUIC_HANDSHAKE_FAILED,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500704 "Connection is closed by server before handshake confirmed",
705 // Although it is our intention to send termination packets, the
706 // |action| argument is not used by this call to
707 // StatelesslyTerminateConnection().
708 action);
709 session_map_.erase(it);
710 return;
711 }
712 QUIC_CODE_COUNT(quic_v44_add_to_time_wait_list_with_stateless_reset);
713 }
714 time_wait_list_manager_->AddConnectionIdToTimeWait(
715 it->first, connection->transport_version() > QUIC_VERSION_43, action,
716 connection->encryption_level(), connection->termination_packets());
717 session_map_.erase(it);
718}
719
720void QuicDispatcher::StopAcceptingNewConnections() {
721 accept_new_connections_ = false;
722}
723
724std::unique_ptr<QuicPerPacketContext> QuicDispatcher::GetPerPacketContext()
725 const {
726 return nullptr;
727}
728
729void QuicDispatcher::DeleteSessions() {
QUICHE teamaa1d6a82019-03-13 09:14:13 -0700730 if (!write_blocked_list_.empty()) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500731 for (const std::unique_ptr<QuicSession>& session : closed_session_list_) {
732 if (write_blocked_list_.erase(session->connection()) != 0) {
733 QUIC_BUG << "QuicConnection was in WriteBlockedList before destruction";
734 }
735 }
736 }
737 closed_session_list_.clear();
738}
739
740void QuicDispatcher::OnCanWrite() {
741 // The socket is now writable.
742 writer_->SetWritable();
743
744 // Move every blocked writer in |write_blocked_list_| to a temporary list.
745 const size_t num_blocked_writers_before = write_blocked_list_.size();
746 WriteBlockedList temp_list;
747 temp_list.swap(write_blocked_list_);
748 DCHECK(write_blocked_list_.empty());
749
750 // Give each blocked writer a chance to write what they indended to write.
751 // If they are blocked again, they will call |OnWriteBlocked| to add
752 // themselves back into |write_blocked_list_|.
753 while (!temp_list.empty()) {
754 QuicBlockedWriterInterface* blocked_writer = temp_list.begin()->first;
755 temp_list.erase(temp_list.begin());
756 blocked_writer->OnBlockedWriterCanWrite();
757 }
758 const size_t num_blocked_writers_after = write_blocked_list_.size();
759 if (num_blocked_writers_after != 0) {
760 if (num_blocked_writers_before == num_blocked_writers_after) {
761 QUIC_CODE_COUNT(quic_zero_progress_on_can_write);
762 } else {
763 QUIC_CODE_COUNT(quic_blocked_again_on_can_write);
764 }
765 }
766}
767
768bool QuicDispatcher::HasPendingWrites() const {
769 return !write_blocked_list_.empty();
770}
771
772void QuicDispatcher::Shutdown() {
773 while (!session_map_.empty()) {
774 QuicSession* session = session_map_.begin()->second.get();
775 session->connection()->CloseConnection(
776 QUIC_PEER_GOING_AWAY, "Server shutdown imminent",
777 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
778 // Validate that the session removes itself from the session map on close.
779 DCHECK(session_map_.empty() ||
780 session_map_.begin()->second.get() != session);
781 }
782 DeleteSessions();
783}
784
dschinazi7b9278c2019-05-20 07:36:21 -0700785void QuicDispatcher::OnConnectionClosed(QuicConnectionId server_connection_id,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500786 QuicErrorCode error,
vasilvvc48c8712019-03-11 13:38:16 -0700787 const std::string& error_details,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500788 ConnectionCloseSource source) {
dschinazi7b9278c2019-05-20 07:36:21 -0700789 auto it = session_map_.find(server_connection_id);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500790 if (it == session_map_.end()) {
dschinazi7b9278c2019-05-20 07:36:21 -0700791 QUIC_BUG << "ConnectionId " << server_connection_id
QUICHE teama6ef0a62019-03-07 20:34:33 -0500792 << " does not exist in the session map. Error: "
793 << QuicErrorCodeToString(error);
794 QUIC_BUG << QuicStackTrace();
795 return;
796 }
797
798 QUIC_DLOG_IF(INFO, error != QUIC_NO_ERROR)
dschinazi7b9278c2019-05-20 07:36:21 -0700799 << "Closing connection (" << server_connection_id
QUICHE teama6ef0a62019-03-07 20:34:33 -0500800 << ") due to error: " << QuicErrorCodeToString(error)
801 << ", with details: " << error_details;
802
803 QuicConnection* connection = it->second->connection();
804 if (ShouldDestroySessionAsynchronously()) {
805 // Set up alarm to fire immediately to bring destruction of this session
806 // out of current call stack.
807 if (closed_session_list_.empty()) {
808 delete_sessions_alarm_->Update(helper()->GetClock()->ApproximateNow(),
809 QuicTime::Delta::Zero());
810 }
811 closed_session_list_.push_back(std::move(it->second));
812 }
813 const bool should_close_statelessly =
814 (error == QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT);
815 CleanUpSession(it, connection, should_close_statelessly, source);
816}
817
818void QuicDispatcher::OnWriteBlocked(
819 QuicBlockedWriterInterface* blocked_writer) {
820 if (!blocked_writer->IsWriterBlocked()) {
821 // It is a programming error if this ever happens. When we are sure it is
822 // not happening, replace it with a DCHECK.
823 QUIC_BUG
824 << "Tried to add writer into blocked list when it shouldn't be added";
825 // Return without adding the connection to the blocked list, to avoid
826 // infinite loops in OnCanWrite.
827 return;
828 }
829
830 write_blocked_list_.insert(std::make_pair(blocked_writer, true));
831}
832
833void QuicDispatcher::OnRstStreamReceived(const QuicRstStreamFrame& frame) {}
834
835void QuicDispatcher::OnStopSendingReceived(const QuicStopSendingFrame& frame) {}
836
837void QuicDispatcher::OnConnectionAddedToTimeWaitList(
dschinazi7b9278c2019-05-20 07:36:21 -0700838 QuicConnectionId server_connection_id) {
839 QUIC_DLOG(INFO) << "Connection " << server_connection_id
QUICHE teama6ef0a62019-03-07 20:34:33 -0500840 << " added to time wait list.";
841}
842
843void QuicDispatcher::StatelesslyTerminateConnection(
dschinazi7b9278c2019-05-20 07:36:21 -0700844 QuicConnectionId server_connection_id,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500845 PacketHeaderFormat format,
fayang1de67892019-04-19 05:59:45 -0700846 bool version_flag,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500847 ParsedQuicVersion version,
848 QuicErrorCode error_code,
vasilvvc48c8712019-03-11 13:38:16 -0700849 const std::string& error_details,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500850 QuicTimeWaitListManager::TimeWaitAction action) {
fayang1de67892019-04-19 05:59:45 -0700851 if (format != IETF_QUIC_LONG_HEADER_PACKET &&
852 (!GetQuicReloadableFlag(quic_terminate_gquic_connection_as_ietf) ||
853 !version_flag)) {
dschinazi7b9278c2019-05-20 07:36:21 -0700854 QUIC_DVLOG(1) << "Statelessly terminating " << server_connection_id
QUICHE teama6ef0a62019-03-07 20:34:33 -0500855 << " based on a non-ietf-long packet, action:" << action
856 << ", error_code:" << error_code
857 << ", error_details:" << error_details;
858 time_wait_list_manager_->AddConnectionIdToTimeWait(
dschinazi7b9278c2019-05-20 07:36:21 -0700859 server_connection_id, format != GOOGLE_QUIC_PACKET, action,
860 ENCRYPTION_INITIAL, nullptr);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500861 return;
862 }
863
864 // If the version is known and supported by framer, send a connection close.
fayangccbab732019-05-13 10:11:25 -0700865 if (IsSupportedVersion(version)) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500866 QUIC_DVLOG(1)
dschinazi7b9278c2019-05-20 07:36:21 -0700867 << "Statelessly terminating " << server_connection_id
QUICHE teama6ef0a62019-03-07 20:34:33 -0500868 << " based on an ietf-long packet, which has a supported version:"
869 << version << ", error_code:" << error_code
870 << ", error_details:" << error_details;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500871
dschinazi7b9278c2019-05-20 07:36:21 -0700872 StatelessConnectionTerminator terminator(server_connection_id, version,
873 helper_.get(),
874 time_wait_list_manager_.get());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500875 // This also adds the connection to time wait list.
fayang1de67892019-04-19 05:59:45 -0700876 if (format == GOOGLE_QUIC_PACKET) {
877 QUIC_RELOADABLE_FLAG_COUNT_N(quic_terminate_gquic_connection_as_ietf, 1,
878 2);
879 }
880 terminator.CloseConnection(error_code, error_details,
881 format != GOOGLE_QUIC_PACKET);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500882 return;
883 }
884
885 QUIC_DVLOG(1)
dschinazi7b9278c2019-05-20 07:36:21 -0700886 << "Statelessly terminating " << server_connection_id
QUICHE teama6ef0a62019-03-07 20:34:33 -0500887 << " based on an ietf-long packet, which has an unsupported version:"
888 << version << ", error_code:" << error_code
889 << ", error_details:" << error_details;
890 // Version is unknown or unsupported by framer, send a version negotiation
891 // with an empty version list, which can be understood by the client.
892 std::vector<std::unique_ptr<QuicEncryptedPacket>> termination_packets;
893 termination_packets.push_back(QuicFramer::BuildVersionNegotiationPacket(
dschinazi7b9278c2019-05-20 07:36:21 -0700894 server_connection_id, /*ietf_quic=*/format != GOOGLE_QUIC_PACKET,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500895 ParsedQuicVersionVector{UnsupportedQuicVersion()}));
fayang1de67892019-04-19 05:59:45 -0700896 if (format == GOOGLE_QUIC_PACKET) {
897 QUIC_RELOADABLE_FLAG_COUNT_N(quic_terminate_gquic_connection_as_ietf, 2, 2);
898 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500899 time_wait_list_manager()->AddConnectionIdToTimeWait(
dschinazi7b9278c2019-05-20 07:36:21 -0700900 server_connection_id, /*ietf_quic=*/format != GOOGLE_QUIC_PACKET,
QUICHE team6987b4a2019-03-15 16:23:04 -0700901 QuicTimeWaitListManager::SEND_TERMINATION_PACKETS, ENCRYPTION_INITIAL,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500902 &termination_packets);
903}
904
905void QuicDispatcher::OnPacket() {}
906
907void QuicDispatcher::OnError(QuicFramer* framer) {
908 QuicErrorCode error = framer->error();
909 SetLastError(error);
910 QUIC_DLOG(INFO) << QuicErrorCodeToString(error);
911}
912
913bool QuicDispatcher::ShouldCreateSessionForUnknownVersion(
914 QuicVersionLabel /*version_label*/) {
915 return false;
916}
917
918bool QuicDispatcher::OnProtocolVersionMismatch(
919 ParsedQuicVersion /*received_version*/,
920 PacketHeaderFormat /*form*/) {
fayangccbab732019-05-13 10:11:25 -0700921 DCHECK(!no_framer_);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500922 QUIC_BUG_IF(
923 !time_wait_list_manager_->IsConnectionIdInTimeWait(
dschinazi7b9278c2019-05-20 07:36:21 -0700924 current_server_connection_id_) &&
QUICHE teama6ef0a62019-03-07 20:34:33 -0500925 !ShouldCreateSessionForUnknownVersion(framer_.last_version_label()))
926 << "Unexpected version mismatch: "
927 << QuicVersionLabelToString(framer_.last_version_label());
928
929 // Keep processing after protocol mismatch - this will be dealt with by the
930 // time wait list or connection that we will create.
931 return true;
932}
933
934void QuicDispatcher::OnPublicResetPacket(
935 const QuicPublicResetPacket& /*packet*/) {
936 DCHECK(false);
937}
938
939void QuicDispatcher::OnVersionNegotiationPacket(
940 const QuicVersionNegotiationPacket& /*packet*/) {
941 DCHECK(false);
942}
943
dschinazi244f6dc2019-05-06 15:45:16 -0700944void QuicDispatcher::OnRetryPacket(QuicConnectionId /*original_connection_id*/,
945 QuicConnectionId /*new_connection_id*/,
946 QuicStringPiece /*retry_token*/) {
947 DCHECK(false);
948}
949
QUICHE teama6ef0a62019-03-07 20:34:33 -0500950void QuicDispatcher::OnDecryptedPacket(EncryptionLevel level) {
951 DCHECK(false);
952}
953
954bool QuicDispatcher::OnPacketHeader(const QuicPacketHeader& /*header*/) {
955 DCHECK(false);
956 return false;
957}
958
959void QuicDispatcher::OnCoalescedPacket(const QuicEncryptedPacket& /*packet*/) {
960 DCHECK(false);
961}
962
963bool QuicDispatcher::OnStreamFrame(const QuicStreamFrame& /*frame*/) {
964 DCHECK(false);
965 return false;
966}
967
968bool QuicDispatcher::OnCryptoFrame(const QuicCryptoFrame& /*frame*/) {
969 DCHECK(false);
970 return false;
971}
972
973bool QuicDispatcher::OnAckFrameStart(QuicPacketNumber /*largest_acked*/,
974 QuicTime::Delta /*ack_delay_time*/) {
975 DCHECK(false);
976 return false;
977}
978
979bool QuicDispatcher::OnAckRange(QuicPacketNumber /*start*/,
980 QuicPacketNumber /*end*/) {
981 DCHECK(false);
982 return false;
983}
984
985bool QuicDispatcher::OnAckTimestamp(QuicPacketNumber /*packet_number*/,
986 QuicTime /*timestamp*/) {
987 DCHECK(false);
988 return false;
989}
990
991bool QuicDispatcher::OnAckFrameEnd(QuicPacketNumber /*start*/) {
992 DCHECK(false);
993 return false;
994}
995
996bool QuicDispatcher::OnStopWaitingFrame(const QuicStopWaitingFrame& /*frame*/) {
997 DCHECK(false);
998 return false;
999}
1000
1001bool QuicDispatcher::OnPaddingFrame(const QuicPaddingFrame& /*frame*/) {
1002 DCHECK(false);
1003 return false;
1004}
1005
1006bool QuicDispatcher::OnPingFrame(const QuicPingFrame& /*frame*/) {
1007 DCHECK(false);
1008 return false;
1009}
1010
1011bool QuicDispatcher::OnRstStreamFrame(const QuicRstStreamFrame& /*frame*/) {
1012 DCHECK(false);
1013 return false;
1014}
1015
1016bool QuicDispatcher::OnConnectionCloseFrame(
1017 const QuicConnectionCloseFrame& /*frame*/) {
1018 DCHECK(false);
1019 return false;
1020}
1021
fkastenholz3c4eabf2019-04-22 07:49:59 -07001022bool QuicDispatcher::OnMaxStreamsFrame(const QuicMaxStreamsFrame& frame) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001023 return true;
1024}
1025
fkastenholz3c4eabf2019-04-22 07:49:59 -07001026bool QuicDispatcher::OnStreamsBlockedFrame(
1027 const QuicStreamsBlockedFrame& frame) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001028 return true;
1029}
1030
1031bool QuicDispatcher::OnStopSendingFrame(const QuicStopSendingFrame& /*frame*/) {
1032 DCHECK(false);
1033 return false;
1034}
1035
1036bool QuicDispatcher::OnPathChallengeFrame(
1037 const QuicPathChallengeFrame& /*frame*/) {
1038 DCHECK(false);
1039 return false;
1040}
1041
1042bool QuicDispatcher::OnPathResponseFrame(
1043 const QuicPathResponseFrame& /*frame*/) {
1044 DCHECK(false);
1045 return false;
1046}
1047
1048bool QuicDispatcher::OnGoAwayFrame(const QuicGoAwayFrame& /*frame*/) {
1049 DCHECK(false);
1050 return false;
1051}
1052
1053bool QuicDispatcher::OnWindowUpdateFrame(
1054 const QuicWindowUpdateFrame& /*frame*/) {
1055 DCHECK(false);
1056 return false;
1057}
1058
1059bool QuicDispatcher::OnBlockedFrame(const QuicBlockedFrame& frame) {
1060 DCHECK(false);
1061 return false;
1062}
1063
1064bool QuicDispatcher::OnNewConnectionIdFrame(
1065 const QuicNewConnectionIdFrame& frame) {
1066 DCHECK(false);
1067 return false;
1068}
1069
1070bool QuicDispatcher::OnRetireConnectionIdFrame(
1071 const QuicRetireConnectionIdFrame& frame) {
1072 DCHECK(false);
1073 return false;
1074}
1075
1076bool QuicDispatcher::OnNewTokenFrame(const QuicNewTokenFrame& frame) {
1077 DCHECK(false);
1078 return false;
1079}
1080
1081bool QuicDispatcher::OnMessageFrame(const QuicMessageFrame& frame) {
1082 DCHECK(false);
1083 return false;
1084}
1085
1086void QuicDispatcher::OnPacketComplete() {
1087 DCHECK(false);
1088}
1089
1090bool QuicDispatcher::IsValidStatelessResetToken(QuicUint128 token) const {
1091 DCHECK(false);
1092 return false;
1093}
1094
1095void QuicDispatcher::OnAuthenticatedIetfStatelessResetPacket(
1096 const QuicIetfStatelessResetPacket& packet) {
1097 DCHECK(false);
1098}
1099
1100void QuicDispatcher::OnExpiredPackets(
dschinazi7b9278c2019-05-20 07:36:21 -07001101 QuicConnectionId server_connection_id,
QUICHE teama6ef0a62019-03-07 20:34:33 -05001102 BufferedPacketList early_arrived_packets) {
1103 QUIC_CODE_COUNT(quic_reject_buffered_packets_expired);
1104 StatelesslyTerminateConnection(
dschinazi7b9278c2019-05-20 07:36:21 -07001105 server_connection_id,
QUICHE teama6ef0a62019-03-07 20:34:33 -05001106 early_arrived_packets.ietf_quic ? IETF_QUIC_LONG_HEADER_PACKET
1107 : GOOGLE_QUIC_PACKET,
fayang1de67892019-04-19 05:59:45 -07001108 /*version_flag=*/true, early_arrived_packets.version,
1109 QUIC_HANDSHAKE_FAILED, "Packets buffered for too long",
QUICHE teama6ef0a62019-03-07 20:34:33 -05001110 quic::QuicTimeWaitListManager::SEND_STATELESS_RESET);
1111}
1112
1113void QuicDispatcher::ProcessBufferedChlos(size_t max_connections_to_create) {
1114 // Reset the counter before starting creating connections.
1115 new_sessions_allowed_per_event_loop_ = max_connections_to_create;
1116 for (; new_sessions_allowed_per_event_loop_ > 0;
1117 --new_sessions_allowed_per_event_loop_) {
dschinazi7b9278c2019-05-20 07:36:21 -07001118 QuicConnectionId server_connection_id;
QUICHE teama6ef0a62019-03-07 20:34:33 -05001119 BufferedPacketList packet_list =
dschinazi7b9278c2019-05-20 07:36:21 -07001120 buffered_packets_.DeliverPacketsForNextConnection(
1121 &server_connection_id);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001122 const std::list<BufferedPacket>& packets = packet_list.buffered_packets;
1123 if (packets.empty()) {
1124 return;
1125 }
dschinazi7b9278c2019-05-20 07:36:21 -07001126 QuicConnectionId original_connection_id = server_connection_id;
1127 server_connection_id = MaybeReplaceServerConnectionId(server_connection_id,
1128 packet_list.version);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001129 QuicSession* session =
dschinazi7b9278c2019-05-20 07:36:21 -07001130 CreateQuicSession(server_connection_id, packets.front().peer_address,
QUICHE teama6ef0a62019-03-07 20:34:33 -05001131 packet_list.alpn, packet_list.version);
dschinazi7b9278c2019-05-20 07:36:21 -07001132 if (original_connection_id != server_connection_id) {
QUICHE teamc65d1d12019-03-19 20:58:04 -07001133 session->connection()->AddIncomingConnectionId(original_connection_id);
1134 }
dschinazi7b9278c2019-05-20 07:36:21 -07001135 QUIC_DLOG(INFO) << "Created new session for " << server_connection_id;
1136 session_map_.insert(
1137 std::make_pair(server_connection_id, QuicWrapUnique(session)));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001138 DeliverPacketsToSession(packets, session);
1139 }
1140}
1141
1142bool QuicDispatcher::HasChlosBuffered() const {
1143 return buffered_packets_.HasChlosBuffered();
1144}
1145
1146bool QuicDispatcher::ShouldCreateOrBufferPacketForConnection(
dschinazi7b9278c2019-05-20 07:36:21 -07001147 QuicConnectionId server_connection_id,
QUICHE teama6ef0a62019-03-07 20:34:33 -05001148 bool ietf_quic) {
dschinazi7b9278c2019-05-20 07:36:21 -07001149 QUIC_VLOG(1) << "Received packet from new connection "
1150 << server_connection_id;
QUICHE teama6ef0a62019-03-07 20:34:33 -05001151 return true;
1152}
1153
1154// Return true if there is any packet buffered in the store.
dschinazi7b9278c2019-05-20 07:36:21 -07001155bool QuicDispatcher::HasBufferedPackets(QuicConnectionId server_connection_id) {
1156 return buffered_packets_.HasBufferedPackets(server_connection_id);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001157}
1158
dschinazi7b9278c2019-05-20 07:36:21 -07001159void QuicDispatcher::OnBufferPacketFailure(
1160 EnqueuePacketResult result,
1161 QuicConnectionId server_connection_id) {
1162 QUIC_DLOG(INFO) << "Fail to buffer packet on connection "
1163 << server_connection_id << " because of " << result;
QUICHE teama6ef0a62019-03-07 20:34:33 -05001164}
1165
QUICHE teama6ef0a62019-03-07 20:34:33 -05001166bool QuicDispatcher::ShouldAttemptCheapStatelessRejection() {
1167 return true;
1168}
1169
1170QuicTimeWaitListManager* QuicDispatcher::CreateQuicTimeWaitListManager() {
1171 return new QuicTimeWaitListManager(writer_.get(), this, helper_->GetClock(),
1172 alarm_factory_.get());
1173}
1174
dschinazi7b9278c2019-05-20 07:36:21 -07001175void QuicDispatcher::BufferEarlyPacket(QuicConnectionId server_connection_id,
QUICHE teama6ef0a62019-03-07 20:34:33 -05001176 bool ietf_quic,
1177 ParsedQuicVersion version) {
dschinazi7b9278c2019-05-20 07:36:21 -07001178 bool is_new_connection =
1179 !buffered_packets_.HasBufferedPackets(server_connection_id);
1180 if (is_new_connection && !ShouldCreateOrBufferPacketForConnection(
1181 server_connection_id, ietf_quic)) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001182 return;
1183 }
1184
1185 EnqueuePacketResult rs = buffered_packets_.EnqueuePacket(
dschinazi7b9278c2019-05-20 07:36:21 -07001186 server_connection_id, ietf_quic, *current_packet_, current_self_address_,
QUICHE teama6ef0a62019-03-07 20:34:33 -05001187 current_peer_address_, /*is_chlo=*/false,
1188 /*alpn=*/"", version);
1189 if (rs != EnqueuePacketResult::SUCCESS) {
dschinazi7b9278c2019-05-20 07:36:21 -07001190 OnBufferPacketFailure(rs, server_connection_id);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001191 }
1192}
1193
1194void QuicDispatcher::ProcessChlo(PacketHeaderFormat form,
1195 ParsedQuicVersion version) {
1196 if (!accept_new_connections_) {
1197 // Don't any create new connection.
1198 QUIC_CODE_COUNT(quic_reject_stop_accepting_new_connections);
1199 StatelesslyTerminateConnection(
dschinazi7b9278c2019-05-20 07:36:21 -07001200 current_server_connection_id(), form, /*version_flag=*/true, version,
fayang1de67892019-04-19 05:59:45 -07001201 QUIC_HANDSHAKE_FAILED, "Stop accepting new connections",
QUICHE teama6ef0a62019-03-07 20:34:33 -05001202 quic::QuicTimeWaitListManager::SEND_STATELESS_RESET);
1203 // Time wait list will reject the packet correspondingly.
1204 time_wait_list_manager()->ProcessPacket(
dschinazi7b9278c2019-05-20 07:36:21 -07001205 current_self_address(), current_peer_address(),
1206 current_server_connection_id(), form, GetPerPacketContext());
QUICHE teama6ef0a62019-03-07 20:34:33 -05001207 return;
1208 }
dschinazi7b9278c2019-05-20 07:36:21 -07001209 if (!buffered_packets_.HasBufferedPackets(current_server_connection_id_) &&
1210 !ShouldCreateOrBufferPacketForConnection(current_server_connection_id_,
QUICHE teama6ef0a62019-03-07 20:34:33 -05001211 form != GOOGLE_QUIC_PACKET)) {
1212 return;
1213 }
1214 if (FLAGS_quic_allow_chlo_buffering &&
1215 new_sessions_allowed_per_event_loop_ <= 0) {
1216 // Can't create new session any more. Wait till next event loop.
dschinazi7b9278c2019-05-20 07:36:21 -07001217 QUIC_BUG_IF(
1218 buffered_packets_.HasChloForConnection(current_server_connection_id_));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001219 EnqueuePacketResult rs = buffered_packets_.EnqueuePacket(
dschinazi7b9278c2019-05-20 07:36:21 -07001220 current_server_connection_id_, form != GOOGLE_QUIC_PACKET,
1221 *current_packet_, current_self_address_, current_peer_address_,
fayangccbab732019-05-13 10:11:25 -07001222 /*is_chlo=*/true, current_alpn_, version);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001223 if (rs != EnqueuePacketResult::SUCCESS) {
dschinazi7b9278c2019-05-20 07:36:21 -07001224 OnBufferPacketFailure(rs, current_server_connection_id_);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001225 }
1226 return;
1227 }
QUICHE teamc65d1d12019-03-19 20:58:04 -07001228
dschinazi7b9278c2019-05-20 07:36:21 -07001229 QuicConnectionId original_connection_id = current_server_connection_id_;
1230 current_server_connection_id_ =
1231 MaybeReplaceServerConnectionId(current_server_connection_id_, version);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001232 // Creates a new session and process all buffered packets for this connection.
dschinazi7b9278c2019-05-20 07:36:21 -07001233 QuicSession* session =
1234 CreateQuicSession(current_server_connection_id_, current_peer_address_,
1235 current_alpn_, version);
1236 if (original_connection_id != current_server_connection_id_) {
QUICHE teamc65d1d12019-03-19 20:58:04 -07001237 session->connection()->AddIncomingConnectionId(original_connection_id);
1238 }
dschinazi7b9278c2019-05-20 07:36:21 -07001239 QUIC_DLOG(INFO) << "Created new session for "
1240 << current_server_connection_id_;
QUICHE teama6ef0a62019-03-07 20:34:33 -05001241 session_map_.insert(
dschinazi7b9278c2019-05-20 07:36:21 -07001242 std::make_pair(current_server_connection_id_, QuicWrapUnique(session)));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001243 std::list<BufferedPacket> packets =
dschinazi7b9278c2019-05-20 07:36:21 -07001244 buffered_packets_.DeliverPackets(current_server_connection_id_)
1245 .buffered_packets;
QUICHE teama6ef0a62019-03-07 20:34:33 -05001246 // Process CHLO at first.
1247 session->ProcessUdpPacket(current_self_address_, current_peer_address_,
1248 *current_packet_);
1249 // Deliver queued-up packets in the same order as they arrived.
1250 // Do this even when flag is off because there might be still some packets
1251 // buffered in the store before flag is turned off.
1252 DeliverPacketsToSession(packets, session);
1253 --new_sessions_allowed_per_event_loop_;
1254}
1255
1256const QuicSocketAddress QuicDispatcher::GetClientAddress() const {
1257 return current_peer_address_;
1258}
1259
1260bool QuicDispatcher::ShouldDestroySessionAsynchronously() {
1261 return true;
1262}
1263
1264void QuicDispatcher::SetLastError(QuicErrorCode error) {
1265 last_error_ = error;
1266}
1267
1268bool QuicDispatcher::OnUnauthenticatedUnknownPublicHeader(
1269 const QuicPacketHeader& header) {
1270 return true;
1271}
1272
1273class StatelessRejectorProcessDoneCallback
1274 : public StatelessRejector::ProcessDoneCallback {
1275 public:
1276 StatelessRejectorProcessDoneCallback(QuicDispatcher* dispatcher,
1277 ParsedQuicVersion first_version,
fayang1de67892019-04-19 05:59:45 -07001278 PacketHeaderFormat form,
1279 bool version_flag)
QUICHE teama6ef0a62019-03-07 20:34:33 -05001280 : dispatcher_(dispatcher),
1281 current_client_address_(dispatcher->current_client_address_),
1282 current_peer_address_(dispatcher->current_peer_address_),
1283 current_self_address_(dispatcher->current_self_address_),
1284 additional_context_(dispatcher->GetPerPacketContext()),
1285 current_packet_(
1286 dispatcher->current_packet_->Clone()), // Note: copies the packet
1287 first_version_(first_version),
fayang1de67892019-04-19 05:59:45 -07001288 current_packet_format_(form),
1289 current_version_flag_(version_flag) {}
QUICHE teama6ef0a62019-03-07 20:34:33 -05001290
1291 void Run(std::unique_ptr<StatelessRejector> rejector) override {
1292 if (additional_context_ != nullptr) {
1293 dispatcher_->RestorePerPacketContext(std::move(additional_context_));
1294 }
1295 dispatcher_->OnStatelessRejectorProcessDone(
1296 std::move(rejector), current_client_address_, current_peer_address_,
1297 current_self_address_, std::move(current_packet_), first_version_,
fayang1de67892019-04-19 05:59:45 -07001298 current_packet_format_, current_version_flag_);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001299 }
1300
1301 private:
1302 QuicDispatcher* dispatcher_;
1303 QuicSocketAddress current_client_address_;
1304 QuicSocketAddress current_peer_address_;
1305 QuicSocketAddress current_self_address_;
1306 // TODO(wub): Wrap all current_* variables into PerPacketContext. And rename
1307 // |additional_context_| to |context_|.
1308 std::unique_ptr<QuicPerPacketContext> additional_context_;
1309 std::unique_ptr<QuicReceivedPacket> current_packet_;
1310 ParsedQuicVersion first_version_;
1311 const PacketHeaderFormat current_packet_format_;
fayang1de67892019-04-19 05:59:45 -07001312 bool current_version_flag_;
QUICHE teama6ef0a62019-03-07 20:34:33 -05001313};
1314
dschinazi7b9278c2019-05-20 07:36:21 -07001315void QuicDispatcher::MaybeRejectStatelessly(
1316 QuicConnectionId server_connection_id,
1317 PacketHeaderFormat form,
1318 bool version_flag,
1319 ParsedQuicVersion version) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001320 if (version.handshake_protocol == PROTOCOL_TLS1_3) {
dschinazi7b9278c2019-05-20 07:36:21 -07001321 ProcessUnauthenticatedHeaderFate(kFateProcess, server_connection_id, form,
fayang1de67892019-04-19 05:59:45 -07001322 version_flag, version);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001323 return;
1324 // TODO(nharper): Support buffering non-ClientHello packets when using TLS.
1325 }
1326 // TODO(rch): This logic should probably live completely inside the rejector.
1327 if (!FLAGS_quic_allow_chlo_buffering ||
1328 !GetQuicReloadableFlag(quic_use_cheap_stateless_rejects) ||
1329 !GetQuicReloadableFlag(enable_quic_stateless_reject_support) ||
1330 !ShouldAttemptCheapStatelessRejection()) {
1331 // Not use cheap stateless reject.
1332 ChloAlpnExtractor alpn_extractor;
1333 if (FLAGS_quic_allow_chlo_buffering &&
1334 !ChloExtractor::Extract(*current_packet_, GetSupportedVersions(),
1335 config_->create_session_tag_indicators(),
dschinazi7b9278c2019-05-20 07:36:21 -07001336 &alpn_extractor,
1337 server_connection_id.length())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001338 // Buffer non-CHLO packets.
dschinazi7b9278c2019-05-20 07:36:21 -07001339 ProcessUnauthenticatedHeaderFate(kFateBuffer, server_connection_id, form,
fayang1de67892019-04-19 05:59:45 -07001340 version_flag, version);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001341 return;
1342 }
1343 current_alpn_ = alpn_extractor.ConsumeAlpn();
dschinazi7b9278c2019-05-20 07:36:21 -07001344 ProcessUnauthenticatedHeaderFate(kFateProcess, server_connection_id, form,
fayang1de67892019-04-19 05:59:45 -07001345 version_flag, version);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001346 return;
1347 }
1348
1349 std::unique_ptr<StatelessRejector> rejector(new StatelessRejector(
1350 version, GetSupportedVersions(), crypto_config_, &compressed_certs_cache_,
1351 helper()->GetClock(), helper()->GetRandomGenerator(),
1352 current_packet_->length(), current_client_address_,
1353 current_self_address_));
1354 ChloValidator validator(session_helper_.get(), current_client_address_,
1355 current_peer_address_, current_self_address_,
1356 rejector.get());
1357 if (!ChloExtractor::Extract(*current_packet_, GetSupportedVersions(),
1358 config_->create_session_tag_indicators(),
dschinazi7b9278c2019-05-20 07:36:21 -07001359 &validator, server_connection_id.length())) {
1360 ProcessUnauthenticatedHeaderFate(kFateBuffer, server_connection_id, form,
fayang1de67892019-04-19 05:59:45 -07001361 version_flag, version);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001362 return;
1363 }
1364 current_alpn_ = validator.ConsumeAlpn();
1365
1366 if (!validator.can_accept()) {
1367 // This CHLO is prohibited by policy.
1368 QUIC_CODE_COUNT(quic_reject_cant_accept_chlo);
dschinazi7b9278c2019-05-20 07:36:21 -07001369 StatelessConnectionTerminator terminator(
1370 server_connection_id, version, helper(), time_wait_list_manager_.get());
QUICHE teama6ef0a62019-03-07 20:34:33 -05001371 terminator.CloseConnection(QUIC_HANDSHAKE_FAILED, validator.error_details(),
1372 form != GOOGLE_QUIC_PACKET);
wub2b5942f2019-04-11 13:22:50 -07001373 QuicSession::RecordConnectionCloseAtServer(
1374 QUIC_HANDSHAKE_FAILED, ConnectionCloseSource::FROM_SELF);
dschinazi7b9278c2019-05-20 07:36:21 -07001375 ProcessUnauthenticatedHeaderFate(kFateTimeWait, server_connection_id, form,
fayang1de67892019-04-19 05:59:45 -07001376 version_flag, version);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001377 return;
1378 }
1379
1380 // If we were able to make a decision about this CHLO based purely on the
1381 // information available in OnChlo, just invoke the done callback immediately.
1382 if (rejector->state() != StatelessRejector::UNKNOWN) {
fayangf7c569c2019-05-07 11:56:51 -07001383 ProcessStatelessRejectorState(std::move(rejector), version, form,
1384 version_flag);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001385 return;
1386 }
1387
1388 // Insert into set of connection IDs to buffer
1389 const bool ok =
dschinazi7b9278c2019-05-20 07:36:21 -07001390 temporarily_buffered_connections_.insert(server_connection_id).second;
QUICHE teama6ef0a62019-03-07 20:34:33 -05001391 QUIC_BUG_IF(!ok)
1392 << "Processing multiple stateless rejections for connection ID "
dschinazi7b9278c2019-05-20 07:36:21 -07001393 << server_connection_id;
QUICHE teama6ef0a62019-03-07 20:34:33 -05001394
1395 // Continue stateless rejector processing
1396 std::unique_ptr<StatelessRejectorProcessDoneCallback> cb(
fayang1de67892019-04-19 05:59:45 -07001397 new StatelessRejectorProcessDoneCallback(this, version, form,
1398 version_flag));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001399 StatelessRejector::Process(std::move(rejector), std::move(cb));
1400}
1401
1402void QuicDispatcher::OnStatelessRejectorProcessDone(
1403 std::unique_ptr<StatelessRejector> rejector,
1404 const QuicSocketAddress& current_client_address,
1405 const QuicSocketAddress& current_peer_address,
1406 const QuicSocketAddress& current_self_address,
1407 std::unique_ptr<QuicReceivedPacket> current_packet,
1408 ParsedQuicVersion first_version,
fayang1de67892019-04-19 05:59:45 -07001409 PacketHeaderFormat current_packet_format,
1410 bool current_version_flag) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001411 // Reset current_* to correspond to the packet which initiated the stateless
1412 // reject logic.
1413 current_client_address_ = current_client_address;
1414 current_peer_address_ = current_peer_address;
1415 current_self_address_ = current_self_address;
1416 current_packet_ = current_packet.get();
dschinazi7b9278c2019-05-20 07:36:21 -07001417 current_server_connection_id_ = rejector->connection_id();
fayangccbab732019-05-13 10:11:25 -07001418 if (!no_framer_) {
1419 framer_.set_version(first_version);
1420 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001421
1422 // Stop buffering packets on this connection
1423 const auto num_erased =
1424 temporarily_buffered_connections_.erase(rejector->connection_id());
1425 QUIC_BUG_IF(num_erased != 1) << "Completing stateless rejection logic for "
1426 "non-buffered connection ID "
1427 << rejector->connection_id();
1428
1429 // If this connection has gone into time-wait during the async processing,
1430 // don't proceed.
1431 if (time_wait_list_manager_->IsConnectionIdInTimeWait(
1432 rejector->connection_id())) {
1433 time_wait_list_manager_->ProcessPacket(
1434 current_self_address, current_peer_address, rejector->connection_id(),
1435 current_packet_format, GetPerPacketContext());
1436 return;
1437 }
1438
fayangf7c569c2019-05-07 11:56:51 -07001439 ProcessStatelessRejectorState(std::move(rejector), first_version,
fayang1de67892019-04-19 05:59:45 -07001440 current_packet_format, current_version_flag);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001441}
1442
1443void QuicDispatcher::ProcessStatelessRejectorState(
1444 std::unique_ptr<StatelessRejector> rejector,
fayangf7c569c2019-05-07 11:56:51 -07001445 ParsedQuicVersion first_version,
fayang1de67892019-04-19 05:59:45 -07001446 PacketHeaderFormat form,
1447 bool version_flag) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001448 QuicPacketFate fate;
1449 switch (rejector->state()) {
1450 case StatelessRejector::FAILED: {
1451 // There was an error processing the client hello.
1452 QUIC_CODE_COUNT(quic_reject_error_processing_chlo);
1453 StatelessConnectionTerminator terminator(rejector->connection_id(),
fayangf7c569c2019-05-07 11:56:51 -07001454 first_version, helper(),
QUICHE teama6ef0a62019-03-07 20:34:33 -05001455 time_wait_list_manager_.get());
1456 terminator.CloseConnection(rejector->error(), rejector->error_details(),
1457 form != GOOGLE_QUIC_PACKET);
1458 fate = kFateTimeWait;
1459 break;
1460 }
1461
1462 case StatelessRejector::UNSUPPORTED:
1463 // Cheap stateless rejects are not supported so process the packet.
1464 fate = kFateProcess;
1465 break;
1466
1467 case StatelessRejector::ACCEPTED:
1468 // Contains a valid CHLO, so process the packet and create a connection.
1469 fate = kFateProcess;
1470 break;
1471
1472 case StatelessRejector::REJECTED: {
fayangccbab732019-05-13 10:11:25 -07001473 QUIC_BUG_IF(!no_framer_ && first_version != framer_.version())
fayangf7c569c2019-05-07 11:56:51 -07001474 << "SREJ: Client's version: "
1475 << QuicVersionToString(first_version.transport_version)
QUICHE teama6ef0a62019-03-07 20:34:33 -05001476 << " is different from current dispatcher framer's version: "
1477 << QuicVersionToString(framer_.transport_version());
1478 StatelessConnectionTerminator terminator(rejector->connection_id(),
fayangf7c569c2019-05-07 11:56:51 -07001479 first_version, helper(),
QUICHE teama6ef0a62019-03-07 20:34:33 -05001480 time_wait_list_manager_.get());
1481 terminator.RejectConnection(
1482 rejector->reply().GetSerialized().AsStringPiece(),
1483 form != GOOGLE_QUIC_PACKET);
wub2b5942f2019-04-11 13:22:50 -07001484 QuicSession::RecordConnectionCloseAtServer(
1485 QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT,
1486 ConnectionCloseSource::FROM_SELF);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001487 OnConnectionRejectedStatelessly();
1488 fate = kFateTimeWait;
1489 break;
1490 }
1491
1492 default:
1493 QUIC_BUG << "Rejector has invalid state " << rejector->state();
1494 fate = kFateDrop;
1495 break;
1496 }
1497 ProcessUnauthenticatedHeaderFate(fate, rejector->connection_id(), form,
fayang1de67892019-04-19 05:59:45 -07001498 version_flag, rejector->version());
QUICHE teama6ef0a62019-03-07 20:34:33 -05001499}
1500
1501const QuicTransportVersionVector&
1502QuicDispatcher::GetSupportedTransportVersions() {
1503 return version_manager_->GetSupportedTransportVersions();
1504}
1505
1506const ParsedQuicVersionVector& QuicDispatcher::GetSupportedVersions() {
1507 return version_manager_->GetSupportedVersions();
1508}
1509
1510void QuicDispatcher::DeliverPacketsToSession(
1511 const std::list<BufferedPacket>& packets,
1512 QuicSession* session) {
1513 for (const BufferedPacket& packet : packets) {
1514 session->ProcessUdpPacket(packet.self_address, packet.peer_address,
1515 *(packet.packet));
1516 }
1517}
1518
1519void QuicDispatcher::DisableFlagValidation() {
fayangccbab732019-05-13 10:11:25 -07001520 if (!no_framer_) {
1521 framer_.set_validate_flags(false);
1522 }
1523}
1524
1525bool QuicDispatcher::IsSupportedVersion(const ParsedQuicVersion version) {
1526 if (!no_framer_) {
1527 return framer_.IsSupportedVersion(version);
1528 }
1529 for (const ParsedQuicVersion& supported_version :
1530 version_manager_->GetSupportedVersions()) {
1531 if (version == supported_version) {
1532 return true;
1533 }
1534 }
1535 return false;
QUICHE teama6ef0a62019-03-07 20:34:33 -05001536}
1537
1538} // namespace quic