blob: 8a91711062d508447db869e85c3166a0361b0741 [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"
QUICHE teama6ef0a62019-03-07 20:34:33 -050017#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
18#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
19#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
20#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
21#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
22#include "net/third_party/quiche/src/quic/platform/api/quic_stack_trace.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050023#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
dschinazi965ce092019-05-23 06:29:01 -070024#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050025
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,
fkastenholz85f18902019-05-28 12:47:00 -070075 const std::string& error_details) override {}
QUICHE teama6ef0a62019-03-07 20:34:33 -050076
77 void SaveStatelessRejectFrameData(QuicStringPiece reject) {
78 struct iovec iovec;
79 iovec.iov_base = const_cast<char*>(reject.data());
80 iovec.iov_len = reject.length();
81 send_buffer_.SaveStreamData(&iovec, 1, 0, iovec.iov_len);
82 }
83
84 // QuicStreamFrameDataProducer
85 WriteStreamDataResult WriteStreamData(QuicStreamId id,
86 QuicStreamOffset offset,
87 QuicByteCount data_length,
88 QuicDataWriter* writer) override {
89 if (send_buffer_.WriteStreamData(offset, data_length, writer)) {
90 return WRITE_SUCCESS;
91 }
92 return WRITE_FAILED;
93 }
94 bool WriteCryptoData(EncryptionLevel level,
95 QuicStreamOffset offset,
96 QuicByteCount data_length,
97 QuicDataWriter* writer) override {
98 return send_buffer_.WriteStreamData(offset, data_length, writer);
99 }
100
101 std::vector<std::unique_ptr<QuicEncryptedPacket>>* packets() {
102 return &packets_;
103 }
104
105 private:
106 std::vector<std::unique_ptr<QuicEncryptedPacket>> packets_;
107 // This is only needed until the packets are encrypted. Once packets are
108 // encrypted, the stream data is no longer required.
109 QuicStreamSendBuffer send_buffer_;
110};
111
112// Helper for statelessly closing connections by generating the
113// correct termination packets and adding the connection to the time wait
114// list manager.
115class StatelessConnectionTerminator {
116 public:
dschinazi7b9278c2019-05-20 07:36:21 -0700117 StatelessConnectionTerminator(QuicConnectionId server_connection_id,
fayangf7c569c2019-05-07 11:56:51 -0700118 const ParsedQuicVersion version,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500119 QuicConnectionHelperInterface* helper,
120 QuicTimeWaitListManager* time_wait_list_manager)
dschinazi7b9278c2019-05-20 07:36:21 -0700121 : server_connection_id_(server_connection_id),
fayangf7c569c2019-05-07 11:56:51 -0700122 framer_(ParsedQuicVersionVector{version},
123 /*unused*/ QuicTime::Zero(),
124 Perspective::IS_SERVER,
125 /*unused*/ kQuicDefaultConnectionIdLength),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500126 collector_(helper->GetStreamSendBufferAllocator()),
dschinazi7b9278c2019-05-20 07:36:21 -0700127 creator_(server_connection_id, &framer_, &collector_),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500128 time_wait_list_manager_(time_wait_list_manager) {
fayangf7c569c2019-05-07 11:56:51 -0700129 framer_.set_data_producer(&collector_);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500130 }
131
132 ~StatelessConnectionTerminator() {
133 // Clear framer's producer.
fayangf7c569c2019-05-07 11:56:51 -0700134 framer_.set_data_producer(nullptr);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500135 }
136
137 // Generates a packet containing a CONNECTION_CLOSE frame specifying
138 // |error_code| and |error_details| and add the connection to time wait.
139 void CloseConnection(QuicErrorCode error_code,
vasilvvc48c8712019-03-11 13:38:16 -0700140 const std::string& error_details,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500141 bool ietf_quic) {
fkastenholze9d71a82019-04-09 05:12:13 -0700142 QuicConnectionCloseFrame* frame =
143 new QuicConnectionCloseFrame(error_code, error_details);
fayangf7c569c2019-05-07 11:56:51 -0700144 if (framer_.transport_version() == QUIC_VERSION_99) {
fkastenholz72f509b2019-04-10 09:17:49 -0700145 frame->close_type = IETF_QUIC_TRANSPORT_CONNECTION_CLOSE;
146 }
147
QUICHE teama6ef0a62019-03-07 20:34:33 -0500148 if (!creator_.AddSavedFrame(QuicFrame(frame), NOT_RETRANSMISSION)) {
149 QUIC_BUG << "Unable to add frame to an empty packet";
150 delete frame;
151 return;
152 }
153 creator_.Flush();
154 DCHECK_EQ(1u, collector_.packets()->size());
155 time_wait_list_manager_->AddConnectionIdToTimeWait(
dschinazi7b9278c2019-05-20 07:36:21 -0700156 server_connection_id_, ietf_quic,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500157 QuicTimeWaitListManager::SEND_TERMINATION_PACKETS,
QUICHE team6987b4a2019-03-15 16:23:04 -0700158 quic::ENCRYPTION_INITIAL, collector_.packets());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500159 }
160
161 // Generates a series of termination packets containing the crypto handshake
162 // message |reject|. Adds the connection to time wait list with the
163 // generated packets.
164 void RejectConnection(QuicStringPiece reject, bool ietf_quic) {
165 QuicStreamOffset offset = 0;
166 collector_.SaveStatelessRejectFrameData(reject);
167 while (offset < reject.length()) {
168 QuicFrame frame;
fayangf7c569c2019-05-07 11:56:51 -0700169 if (!QuicVersionUsesCryptoFrames(framer_.transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500170 if (!creator_.ConsumeData(
fayangf7c569c2019-05-07 11:56:51 -0700171 QuicUtils::GetCryptoStreamId(framer_.transport_version()),
ianswette28f0222019-04-04 13:31:22 -0700172 reject.length() - offset, offset,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500173 /*fin=*/false,
174 /*needs_full_padding=*/true, NOT_RETRANSMISSION, &frame)) {
175 QUIC_BUG << "Unable to consume data into an empty packet.";
176 return;
177 }
178 offset += frame.stream_frame.data_length;
179 } else {
nharper51961cf2019-05-13 13:23:24 -0700180 if (!creator_.ConsumeCryptoData(
181 ENCRYPTION_INITIAL, reject.length() - offset, offset,
182 /*needs_full_padding=*/true, NOT_RETRANSMISSION, &frame)) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500183 QUIC_BUG << "Unable to consume crypto data into an empty packet.";
184 return;
185 }
186 offset += frame.crypto_frame->data_length;
187 }
nharper46833c32019-05-15 21:33:05 -0700188 if (offset < reject.length() &&
189 !QuicVersionUsesCryptoFrames(framer_.transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500190 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(
dschinazi7b9278c2019-05-20 07:36:21 -0700197 server_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());
dschinazi7b9278c2019-05-20 07:36:21 -0700200 DCHECK(time_wait_list_manager_->IsConnectionIdInTimeWait(
201 server_connection_id_));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500202 }
203
204 private:
dschinazi7b9278c2019-05-20 07:36:21 -0700205 QuicConnectionId server_connection_id_;
fayangf7c569c2019-05-07 11:56:51 -0700206 QuicFramer framer_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500207 // Set as the visitor of |creator_| to collect any generated packets.
208 PacketCollector collector_;
209 QuicPacketCreator creator_;
210 QuicTimeWaitListManager* time_wait_list_manager_;
211};
212
213// Class which extracts the ALPN from a CHLO packet.
214class ChloAlpnExtractor : public ChloExtractor::Delegate {
215 public:
216 void OnChlo(QuicTransportVersion version,
dschinazi7b9278c2019-05-20 07:36:21 -0700217 QuicConnectionId server_connection_id,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500218 const CryptoHandshakeMessage& chlo) override {
219 QuicStringPiece alpn_value;
220 if (chlo.GetStringPiece(kALPN, &alpn_value)) {
vasilvvc48c8712019-03-11 13:38:16 -0700221 alpn_ = std::string(alpn_value);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500222 }
223 }
224
vasilvvc48c8712019-03-11 13:38:16 -0700225 std::string&& ConsumeAlpn() { return std::move(alpn_); }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500226
227 private:
vasilvvc48c8712019-03-11 13:38:16 -0700228 std::string alpn_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500229};
230
QUICHE teama6ef0a62019-03-07 20:34:33 -0500231} // namespace
232
233QuicDispatcher::QuicDispatcher(
234 const QuicConfig* config,
235 const QuicCryptoServerConfig* crypto_config,
236 QuicVersionManager* version_manager,
237 std::unique_ptr<QuicConnectionHelperInterface> helper,
238 std::unique_ptr<QuicCryptoServerStream::Helper> session_helper,
239 std::unique_ptr<QuicAlarmFactory> alarm_factory,
dschinazi8ff74822019-05-28 16:37:20 -0700240 uint8_t expected_server_connection_id_length)
QUICHE teama6ef0a62019-03-07 20:34:33 -0500241 : config_(config),
242 crypto_config_(crypto_config),
243 compressed_certs_cache_(
244 QuicCompressedCertsCache::kQuicCompressedCertsCacheSize),
245 helper_(std::move(helper)),
246 session_helper_(std::move(session_helper)),
247 alarm_factory_(std::move(alarm_factory)),
248 delete_sessions_alarm_(
249 alarm_factory_->CreateAlarm(new DeleteSessionsAlarm(this))),
250 buffered_packets_(this, helper_->GetClock(), alarm_factory_.get()),
251 current_packet_(nullptr),
252 version_manager_(version_manager),
253 framer_(GetSupportedVersions(),
254 /*unused*/ QuicTime::Zero(),
255 Perspective::IS_SERVER,
dschinazi8ff74822019-05-28 16:37:20 -0700256 expected_server_connection_id_length),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500257 last_error_(QUIC_NO_ERROR),
258 new_sessions_allowed_per_event_loop_(0u),
QUICHE team963d57e2019-03-21 10:58:47 -0700259 accept_new_connections_(true),
dschinazi7b9278c2019-05-20 07:36:21 -0700260 allow_short_initial_server_connection_ids_(false),
fayangccbab732019-05-13 10:11:25 -0700261 last_version_label_(0),
dschinazi8ff74822019-05-28 16:37:20 -0700262 expected_server_connection_id_length_(
263 expected_server_connection_id_length),
264 should_update_expected_server_connection_id_length_(false),
fayangccbab732019-05-13 10:11:25 -0700265 no_framer_(GetQuicRestartFlag(quic_no_framer_object_in_dispatcher)) {
266 if (!no_framer_) {
267 framer_.set_visitor(this);
268 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500269}
270
271QuicDispatcher::~QuicDispatcher() {
272 session_map_.clear();
273 closed_session_list_.clear();
274}
275
276void QuicDispatcher::InitializeWithWriter(QuicPacketWriter* writer) {
277 DCHECK(writer_ == nullptr);
278 writer_.reset(writer);
279 time_wait_list_manager_.reset(CreateQuicTimeWaitListManager());
280}
281
282void QuicDispatcher::ProcessPacket(const QuicSocketAddress& self_address,
283 const QuicSocketAddress& peer_address,
284 const QuicReceivedPacket& packet) {
dschinazi965ce092019-05-23 06:29:01 -0700285 QUIC_DVLOG(2) << "Dispatcher received encrypted " << packet.length()
286 << " bytes:" << std::endl
287 << QuicTextUtils::HexDump(
288 QuicStringPiece(packet.data(), packet.length()));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500289 current_self_address_ = self_address;
290 current_peer_address_ = peer_address;
291 // GetClientAddress must be called after current_peer_address_ is set.
292 current_client_address_ = GetClientAddress();
293 current_packet_ = &packet;
fayangccbab732019-05-13 10:11:25 -0700294 if (!no_framer_) {
295 // ProcessPacket will cause the packet to be dispatched in
296 // OnUnauthenticatedPublicHeader, or sent to the time wait list manager
297 // in OnUnauthenticatedHeader.
298 framer_.ProcessPacket(packet);
299 // TODO(rjshade): Return a status describing if/why a packet was dropped,
300 // and log somehow. Maybe expose as a varz.
301 return;
302 }
303 QUIC_RESTART_FLAG_COUNT(quic_no_framer_object_in_dispatcher);
304 QuicPacketHeader header;
fayang1f123502019-05-14 08:05:16 -0700305 std::string detailed_error;
fayangccbab732019-05-13 10:11:25 -0700306 const QuicErrorCode error = QuicFramer::ProcessPacketDispatcher(
dschinazi8ff74822019-05-28 16:37:20 -0700307 packet, expected_server_connection_id_length_, &header.form,
fayangccbab732019-05-13 10:11:25 -0700308 &header.version_flag, &last_version_label_,
dschinazib42a8c52019-05-30 09:45:01 -0700309 &header.destination_connection_id, &header.source_connection_id,
fayangccbab732019-05-13 10:11:25 -0700310 &detailed_error);
311 if (error != QUIC_NO_ERROR) {
312 // Packet has framing error.
313 SetLastError(error);
314 QUIC_DLOG(ERROR) << detailed_error;
315 return;
316 }
317 header.version = ParseQuicVersionLabel(last_version_label_);
dschinazib42a8c52019-05-30 09:45:01 -0700318 if (header.destination_connection_id.length() !=
dschinazi8ff74822019-05-28 16:37:20 -0700319 expected_server_connection_id_length_ &&
320 !should_update_expected_server_connection_id_length_ &&
fayangccbab732019-05-13 10:11:25 -0700321 !QuicUtils::VariableLengthConnectionIdAllowedForVersion(
322 header.version.transport_version)) {
323 SetLastError(QUIC_INVALID_PACKET_HEADER);
324 QUIC_DLOG(ERROR) << "Invalid Connection Id Length";
325 return;
326 }
dschinazi8ff74822019-05-28 16:37:20 -0700327 if (should_update_expected_server_connection_id_length_) {
dschinazib42a8c52019-05-30 09:45:01 -0700328 expected_server_connection_id_length_ =
329 header.destination_connection_id.length();
fayangccbab732019-05-13 10:11:25 -0700330 }
331 // TODO(fayang): Instead of passing in QuicPacketHeader, pass format,
332 // version_flag, version and destination_connection_id. Combine
333 // OnUnauthenticatedPublicHeader and OnUnauthenticatedHeader to a single
334 // function when deprecating quic_no_framer_object_in_dispatcher.
335 if (!OnUnauthenticatedPublicHeader(header)) {
336 return;
337 }
338 OnUnauthenticatedHeader(header);
339 // TODO(wub): Consider invalidate the current_* variables so processing of
340 // the next packet does not use them incorrectly.
QUICHE teama6ef0a62019-03-07 20:34:33 -0500341}
342
dschinazi7b9278c2019-05-20 07:36:21 -0700343QuicConnectionId QuicDispatcher::MaybeReplaceServerConnectionId(
344 QuicConnectionId server_connection_id,
QUICHE teamc65d1d12019-03-19 20:58:04 -0700345 ParsedQuicVersion version) {
dschinazi8ff74822019-05-28 16:37:20 -0700346 const uint8_t expected_server_connection_id_length =
347 no_framer_ ? expected_server_connection_id_length_
348 : framer_.GetExpectedServerConnectionIdLength();
349 if (server_connection_id.length() == expected_server_connection_id_length) {
dschinazi7b9278c2019-05-20 07:36:21 -0700350 return server_connection_id;
QUICHE teamc65d1d12019-03-19 20:58:04 -0700351 }
352 DCHECK(QuicUtils::VariableLengthConnectionIdAllowedForVersion(
353 version.transport_version));
dschinazi7b9278c2019-05-20 07:36:21 -0700354 auto it = connection_id_map_.find(server_connection_id);
QUICHE teamc65d1d12019-03-19 20:58:04 -0700355 if (it != connection_id_map_.end()) {
356 return it->second;
357 }
358 QuicConnectionId new_connection_id =
359 session_helper_->GenerateConnectionIdForReject(version.transport_version,
dschinazi7b9278c2019-05-20 07:36:21 -0700360 server_connection_id);
dschinazi8ff74822019-05-28 16:37:20 -0700361 DCHECK_EQ(expected_server_connection_id_length, new_connection_id.length());
dschinazi7b9278c2019-05-20 07:36:21 -0700362 connection_id_map_.insert(
363 std::make_pair(server_connection_id, new_connection_id));
364 QUIC_DLOG(INFO) << "Replacing incoming connection ID " << server_connection_id
QUICHE teamc65d1d12019-03-19 20:58:04 -0700365 << " with " << new_connection_id;
366 return new_connection_id;
367}
368
QUICHE teama6ef0a62019-03-07 20:34:33 -0500369bool QuicDispatcher::OnUnauthenticatedPublicHeader(
370 const QuicPacketHeader& header) {
dschinazi7b9278c2019-05-20 07:36:21 -0700371 current_server_connection_id_ = header.destination_connection_id;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500372
373 // Port zero is only allowed for unidirectional UDP, so is disallowed by QUIC.
374 // Given that we can't even send a reply rejecting the packet, just drop the
375 // packet.
376 if (current_peer_address_.port() == 0) {
377 return false;
378 }
379
380 // The dispatcher requires the connection ID to be present in order to
381 // look up the matching QuicConnection, so we error out if it is absent.
382 if (header.destination_connection_id_included != CONNECTION_ID_PRESENT) {
383 return false;
384 }
dschinazi7b9278c2019-05-20 07:36:21 -0700385 QuicConnectionId server_connection_id = header.destination_connection_id;
QUICHE team8e2e4532019-03-14 14:37:56 -0700386
QUICHE team963d57e2019-03-21 10:58:47 -0700387 // The IETF spec requires the client to generate an initial server
388 // connection ID that is at least 64 bits long. After that initial
389 // connection ID, the dispatcher picks a new one of its expected length.
390 // Therefore we should never receive a connection ID that is smaller
391 // than 64 bits and smaller than what we expect.
dschinazi8ff74822019-05-28 16:37:20 -0700392 const uint8_t expected_server_connection_id_length =
393 no_framer_ ? expected_server_connection_id_length_
394 : framer_.GetExpectedServerConnectionIdLength();
dschinazi7b9278c2019-05-20 07:36:21 -0700395 if (server_connection_id.length() < kQuicMinimumInitialConnectionIdLength &&
dschinazi8ff74822019-05-28 16:37:20 -0700396 server_connection_id.length() < expected_server_connection_id_length &&
dschinazi7b9278c2019-05-20 07:36:21 -0700397 !allow_short_initial_server_connection_ids_) {
QUICHE team963d57e2019-03-21 10:58:47 -0700398 DCHECK(header.version_flag);
399 DCHECK(QuicUtils::VariableLengthConnectionIdAllowedForVersion(
400 header.version.transport_version));
401 QUIC_DLOG(INFO) << "Packet with short destination connection ID "
dschinazi7b9278c2019-05-20 07:36:21 -0700402 << server_connection_id << " expected "
dschinazi8ff74822019-05-28 16:37:20 -0700403 << static_cast<int>(expected_server_connection_id_length);
dschinazi7b9278c2019-05-20 07:36:21 -0700404 ProcessUnauthenticatedHeaderFate(kFateTimeWait, server_connection_id,
405 header.form, header.version_flag,
406 header.version);
QUICHE team963d57e2019-03-21 10:58:47 -0700407 return false;
408 }
409
QUICHE teama6ef0a62019-03-07 20:34:33 -0500410 // Packets with connection IDs for active connections are processed
411 // immediately.
dschinazi7b9278c2019-05-20 07:36:21 -0700412 auto it = session_map_.find(server_connection_id);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500413 if (it != session_map_.end()) {
dschinazi7b9278c2019-05-20 07:36:21 -0700414 DCHECK(!buffered_packets_.HasBufferedPackets(server_connection_id));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500415 it->second->ProcessUdpPacket(current_self_address_, current_peer_address_,
416 *current_packet_);
417 return false;
418 }
419
dschinazi7b9278c2019-05-20 07:36:21 -0700420 if (buffered_packets_.HasChloForConnection(server_connection_id)) {
421 BufferEarlyPacket(server_connection_id, header.form != GOOGLE_QUIC_PACKET,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500422 header.version);
423 return false;
424 }
425
426 // Check if we are buffering packets for this connection ID
dschinazi7b9278c2019-05-20 07:36:21 -0700427 if (temporarily_buffered_connections_.find(server_connection_id) !=
QUICHE teama6ef0a62019-03-07 20:34:33 -0500428 temporarily_buffered_connections_.end()) {
429 // This packet was received while the a CHLO for the same connection ID was
430 // being processed. Buffer it.
dschinazi7b9278c2019-05-20 07:36:21 -0700431 BufferEarlyPacket(server_connection_id, header.form != GOOGLE_QUIC_PACKET,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500432 header.version);
433 return false;
434 }
435
436 if (!OnUnauthenticatedUnknownPublicHeader(header)) {
437 return false;
438 }
439
440 // If the packet is a public reset for a connection ID that is not active,
441 // there is nothing we must do or can do.
442 if (header.reset_flag) {
443 return false;
444 }
445
dschinazi7b9278c2019-05-20 07:36:21 -0700446 if (time_wait_list_manager_->IsConnectionIdInTimeWait(server_connection_id)) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500447 // This connection ID is already in time-wait state.
448 time_wait_list_manager_->ProcessPacket(
449 current_self_address_, current_peer_address_,
450 header.destination_connection_id, header.form, GetPerPacketContext());
451 return false;
452 }
453
454 // The packet has an unknown connection ID.
455
456 // Unless the packet provides a version, assume that we can continue
457 // processing using our preferred version.
458 ParsedQuicVersion version = GetSupportedVersions().front();
459 if (header.version_flag) {
460 ParsedQuicVersion packet_version = header.version;
fayangccbab732019-05-13 10:11:25 -0700461 if (!no_framer_ && framer_.supported_versions() != GetSupportedVersions()) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500462 // Reset framer's version if version flags change in flight.
463 framer_.SetSupportedVersions(GetSupportedVersions());
464 }
fayangccbab732019-05-13 10:11:25 -0700465 if (!IsSupportedVersion(packet_version)) {
466 if (ShouldCreateSessionForUnknownVersion(
467 no_framer_ ? last_version_label_
468 : framer_.last_version_label())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500469 return true;
470 }
471 if (!crypto_config()->validate_chlo_size() ||
472 current_packet_->length() >= kMinPacketSizeForVersionNegotiation) {
473 // Since the version is not supported, send a version negotiation
474 // packet and stop processing the current packet.
dschinazi346b7ce2019-06-05 01:38:18 -0700475 QuicConnectionId client_connection_id = header.source_connection_id;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500476 time_wait_list_manager()->SendVersionNegotiationPacket(
dschinazi346b7ce2019-06-05 01:38:18 -0700477 server_connection_id, client_connection_id,
dschinazib417d602019-05-29 13:08:45 -0700478 header.form != GOOGLE_QUIC_PACKET, GetSupportedVersions(),
479 current_self_address_, current_peer_address_,
480 GetPerPacketContext());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500481 }
482 return false;
483 }
484 version = packet_version;
485 }
fayangccbab732019-05-13 10:11:25 -0700486 if (!no_framer_) {
487 // Set the framer's version and continue processing.
488 framer_.set_version(version);
489 }
nharper55fa6132019-05-07 19:37:21 -0700490
491 if (version.HasHeaderProtection()) {
492 ProcessHeader(header);
493 return false;
494 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500495 return true;
496}
497
498bool QuicDispatcher::OnUnauthenticatedHeader(const QuicPacketHeader& header) {
nharper55fa6132019-05-07 19:37:21 -0700499 ProcessHeader(header);
500 return false;
501}
502
503void QuicDispatcher::ProcessHeader(const QuicPacketHeader& header) {
dschinazi7b9278c2019-05-20 07:36:21 -0700504 QuicConnectionId server_connection_id = header.destination_connection_id;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500505 // Packet's connection ID is unknown. Apply the validity checks.
506 QuicPacketFate fate = ValidityChecks(header);
507 if (fate == kFateProcess) {
wub0a4b9c52019-05-28 13:18:58 -0700508 ProcessOrBufferPacket(server_connection_id, header.form,
509 header.version_flag, header.version);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500510 } else {
511 // If the fate is already known, process it without executing stateless
512 // rejection logic.
dschinazi7b9278c2019-05-20 07:36:21 -0700513 ProcessUnauthenticatedHeaderFate(fate, server_connection_id, header.form,
fayang1de67892019-04-19 05:59:45 -0700514 header.version_flag, header.version);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500515 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500516}
517
518void QuicDispatcher::ProcessUnauthenticatedHeaderFate(
519 QuicPacketFate fate,
dschinazi7b9278c2019-05-20 07:36:21 -0700520 QuicConnectionId server_connection_id,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500521 PacketHeaderFormat form,
fayang1de67892019-04-19 05:59:45 -0700522 bool version_flag,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500523 ParsedQuicVersion version) {
524 switch (fate) {
525 case kFateProcess: {
526 ProcessChlo(form, version);
527 break;
528 }
529 case kFateTimeWait:
wub0a4b9c52019-05-28 13:18:58 -0700530 // Add this connection_id to the time-wait state, to safely reject
531 // future packets.
532 QUIC_DLOG(INFO) << "Adding connection ID " << server_connection_id
533 << " to time-wait list.";
534 QUIC_CODE_COUNT(quic_reject_fate_time_wait);
535 StatelesslyTerminateConnection(
536 server_connection_id, form, version_flag, version,
537 QUIC_HANDSHAKE_FAILED, "Reject connection",
538 quic::QuicTimeWaitListManager::SEND_STATELESS_RESET);
539
dschinazi7b9278c2019-05-20 07:36:21 -0700540 DCHECK(time_wait_list_manager_->IsConnectionIdInTimeWait(
541 server_connection_id));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500542 time_wait_list_manager_->ProcessPacket(
dschinazi7b9278c2019-05-20 07:36:21 -0700543 current_self_address_, current_peer_address_, server_connection_id,
544 form, GetPerPacketContext());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500545
546 // Any packets which were buffered while the stateless rejector logic was
547 // running should be discarded. Do not inform the time wait list manager,
548 // which should already have a made a decision about sending a reject
549 // based on the CHLO alone.
dschinazi7b9278c2019-05-20 07:36:21 -0700550 buffered_packets_.DiscardPackets(server_connection_id);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500551 break;
552 case kFateBuffer:
553 // This packet is a non-CHLO packet which has arrived before the
554 // corresponding CHLO, *or* this packet was received while the
555 // corresponding CHLO was being processed. Buffer it.
dschinazi7b9278c2019-05-20 07:36:21 -0700556 BufferEarlyPacket(server_connection_id, form != GOOGLE_QUIC_PACKET,
557 version);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500558 break;
559 case kFateDrop:
560 // Do nothing with the packet.
561 break;
562 }
563}
564
565QuicDispatcher::QuicPacketFate QuicDispatcher::ValidityChecks(
566 const QuicPacketHeader& header) {
567 // To have all the checks work properly without tears, insert any new check
568 // into the framework of this method in the section for checks that return the
569 // check's fate value. The sections for checks must be ordered with the
570 // highest priority fate first.
571
572 // Checks that return kFateDrop.
573
574 // Checks that return kFateTimeWait.
575
576 // All packets within a connection sent by a client before receiving a
577 // response from the server are required to have the version negotiation flag
578 // set. Since this may be a client continuing a connection we lost track of
579 // via server restart, send a rejection to fast-fail the connection.
580 if (!header.version_flag) {
581 QUIC_DLOG(INFO)
582 << "Packet without version arrived for unknown connection ID "
583 << header.destination_connection_id;
584 return kFateTimeWait;
585 }
586
fayangccbab732019-05-13 10:11:25 -0700587 if (no_framer_) {
588 // Let the connection parse and validate packet number.
589 return kFateProcess;
590 }
591
QUICHE teama6ef0a62019-03-07 20:34:33 -0500592 // initial packet number of 0 is always invalid.
nharper55fa6132019-05-07 19:37:21 -0700593 if (!framer_.version().HasHeaderProtection()) {
594 if (!header.packet_number.IsInitialized()) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500595 return kFateTimeWait;
596 }
nharper55fa6132019-05-07 19:37:21 -0700597 if (GetQuicRestartFlag(quic_enable_accept_random_ipn)) {
598 QUIC_RESTART_FLAG_COUNT_N(quic_enable_accept_random_ipn, 1, 2);
599 // Accepting Initial Packet Numbers in 1...((2^31)-1) range... check
600 // maximum accordingly.
601 if (header.packet_number > MaxRandomInitialPacketNumber()) {
602 return kFateTimeWait;
603 }
604 } else {
605 // Count those that would have been accepted if FLAGS..random_ipn
606 // were true -- to detect/diagnose potential issues prior to
607 // enabling the flag.
608 if ((header.packet_number >
609 QuicPacketNumber(kMaxReasonableInitialPacketNumber)) &&
610 (header.packet_number <= MaxRandomInitialPacketNumber())) {
611 QUIC_CODE_COUNT_N(had_possibly_random_ipn, 1, 2);
612 }
613 // Check that the sequence number is within the range that the client is
614 // expected to send before receiving a response from the server.
615 if (header.packet_number >
616 QuicPacketNumber(kMaxReasonableInitialPacketNumber)) {
617 return kFateTimeWait;
618 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500619 }
620 }
621 return kFateProcess;
622}
623
624void QuicDispatcher::CleanUpSession(SessionMap::iterator it,
625 QuicConnection* connection,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500626 ConnectionCloseSource source) {
627 write_blocked_list_.erase(connection);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500628 QuicTimeWaitListManager::TimeWaitAction action =
629 QuicTimeWaitListManager::SEND_STATELESS_RESET;
630 if (connection->termination_packets() != nullptr &&
631 !connection->termination_packets()->empty()) {
632 action = QuicTimeWaitListManager::SEND_TERMINATION_PACKETS;
fayangd4291e42019-05-30 10:31:21 -0700633 } else if (VersionHasIetfInvariantHeader(connection->transport_version()) ||
fayang1de67892019-04-19 05:59:45 -0700634 GetQuicReloadableFlag(quic_terminate_gquic_connection_as_ietf)) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500635 if (!connection->IsHandshakeConfirmed()) {
fayangd4291e42019-05-30 10:31:21 -0700636 if (!VersionHasIetfInvariantHeader(connection->transport_version())) {
fayang1de67892019-04-19 05:59:45 -0700637 QUIC_CODE_COUNT(gquic_add_to_time_wait_list_with_handshake_failed);
638 } else {
639 QUIC_CODE_COUNT(quic_v44_add_to_time_wait_list_with_handshake_failed);
640 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500641 action = QuicTimeWaitListManager::SEND_TERMINATION_PACKETS;
642 // This serializes a connection close termination packet with error code
643 // QUIC_HANDSHAKE_FAILED and adds the connection to the time wait list.
644 StatelesslyTerminateConnection(
fayang1de67892019-04-19 05:59:45 -0700645 connection->connection_id(),
fayangd4291e42019-05-30 10:31:21 -0700646 VersionHasIetfInvariantHeader(connection->transport_version())
fayang1de67892019-04-19 05:59:45 -0700647 ? IETF_QUIC_LONG_HEADER_PACKET
648 : GOOGLE_QUIC_PACKET,
649 /*version_flag=*/true, connection->version(), QUIC_HANDSHAKE_FAILED,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500650 "Connection is closed by server before handshake confirmed",
651 // Although it is our intention to send termination packets, the
652 // |action| argument is not used by this call to
653 // StatelesslyTerminateConnection().
654 action);
655 session_map_.erase(it);
656 return;
657 }
658 QUIC_CODE_COUNT(quic_v44_add_to_time_wait_list_with_stateless_reset);
659 }
660 time_wait_list_manager_->AddConnectionIdToTimeWait(
fayangd4291e42019-05-30 10:31:21 -0700661 it->first, VersionHasIetfInvariantHeader(connection->transport_version()),
662 action, connection->encryption_level(),
663 connection->termination_packets());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500664 session_map_.erase(it);
665}
666
667void QuicDispatcher::StopAcceptingNewConnections() {
668 accept_new_connections_ = false;
669}
670
671std::unique_ptr<QuicPerPacketContext> QuicDispatcher::GetPerPacketContext()
672 const {
673 return nullptr;
674}
675
676void QuicDispatcher::DeleteSessions() {
QUICHE teamaa1d6a82019-03-13 09:14:13 -0700677 if (!write_blocked_list_.empty()) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500678 for (const std::unique_ptr<QuicSession>& session : closed_session_list_) {
679 if (write_blocked_list_.erase(session->connection()) != 0) {
680 QUIC_BUG << "QuicConnection was in WriteBlockedList before destruction";
681 }
682 }
683 }
684 closed_session_list_.clear();
685}
686
687void QuicDispatcher::OnCanWrite() {
688 // The socket is now writable.
689 writer_->SetWritable();
690
691 // Move every blocked writer in |write_blocked_list_| to a temporary list.
692 const size_t num_blocked_writers_before = write_blocked_list_.size();
693 WriteBlockedList temp_list;
694 temp_list.swap(write_blocked_list_);
695 DCHECK(write_blocked_list_.empty());
696
697 // Give each blocked writer a chance to write what they indended to write.
698 // If they are blocked again, they will call |OnWriteBlocked| to add
699 // themselves back into |write_blocked_list_|.
700 while (!temp_list.empty()) {
701 QuicBlockedWriterInterface* blocked_writer = temp_list.begin()->first;
702 temp_list.erase(temp_list.begin());
703 blocked_writer->OnBlockedWriterCanWrite();
704 }
705 const size_t num_blocked_writers_after = write_blocked_list_.size();
706 if (num_blocked_writers_after != 0) {
707 if (num_blocked_writers_before == num_blocked_writers_after) {
708 QUIC_CODE_COUNT(quic_zero_progress_on_can_write);
709 } else {
710 QUIC_CODE_COUNT(quic_blocked_again_on_can_write);
711 }
712 }
713}
714
715bool QuicDispatcher::HasPendingWrites() const {
716 return !write_blocked_list_.empty();
717}
718
719void QuicDispatcher::Shutdown() {
720 while (!session_map_.empty()) {
721 QuicSession* session = session_map_.begin()->second.get();
722 session->connection()->CloseConnection(
723 QUIC_PEER_GOING_AWAY, "Server shutdown imminent",
724 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
725 // Validate that the session removes itself from the session map on close.
726 DCHECK(session_map_.empty() ||
727 session_map_.begin()->second.get() != session);
728 }
729 DeleteSessions();
730}
731
dschinazi7b9278c2019-05-20 07:36:21 -0700732void QuicDispatcher::OnConnectionClosed(QuicConnectionId server_connection_id,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500733 QuicErrorCode error,
vasilvvc48c8712019-03-11 13:38:16 -0700734 const std::string& error_details,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500735 ConnectionCloseSource source) {
dschinazi7b9278c2019-05-20 07:36:21 -0700736 auto it = session_map_.find(server_connection_id);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500737 if (it == session_map_.end()) {
dschinazi7b9278c2019-05-20 07:36:21 -0700738 QUIC_BUG << "ConnectionId " << server_connection_id
QUICHE teama6ef0a62019-03-07 20:34:33 -0500739 << " does not exist in the session map. Error: "
740 << QuicErrorCodeToString(error);
741 QUIC_BUG << QuicStackTrace();
742 return;
743 }
744
745 QUIC_DLOG_IF(INFO, error != QUIC_NO_ERROR)
dschinazi7b9278c2019-05-20 07:36:21 -0700746 << "Closing connection (" << server_connection_id
QUICHE teama6ef0a62019-03-07 20:34:33 -0500747 << ") due to error: " << QuicErrorCodeToString(error)
748 << ", with details: " << error_details;
749
750 QuicConnection* connection = it->second->connection();
751 if (ShouldDestroySessionAsynchronously()) {
752 // Set up alarm to fire immediately to bring destruction of this session
753 // out of current call stack.
754 if (closed_session_list_.empty()) {
755 delete_sessions_alarm_->Update(helper()->GetClock()->ApproximateNow(),
756 QuicTime::Delta::Zero());
757 }
758 closed_session_list_.push_back(std::move(it->second));
759 }
wub5f64ec42019-06-06 07:31:19 -0700760 CleanUpSession(it, connection, source);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500761}
762
763void QuicDispatcher::OnWriteBlocked(
764 QuicBlockedWriterInterface* blocked_writer) {
765 if (!blocked_writer->IsWriterBlocked()) {
766 // It is a programming error if this ever happens. When we are sure it is
767 // not happening, replace it with a DCHECK.
768 QUIC_BUG
769 << "Tried to add writer into blocked list when it shouldn't be added";
770 // Return without adding the connection to the blocked list, to avoid
771 // infinite loops in OnCanWrite.
772 return;
773 }
774
775 write_blocked_list_.insert(std::make_pair(blocked_writer, true));
776}
777
778void QuicDispatcher::OnRstStreamReceived(const QuicRstStreamFrame& frame) {}
779
780void QuicDispatcher::OnStopSendingReceived(const QuicStopSendingFrame& frame) {}
781
782void QuicDispatcher::OnConnectionAddedToTimeWaitList(
dschinazi7b9278c2019-05-20 07:36:21 -0700783 QuicConnectionId server_connection_id) {
784 QUIC_DLOG(INFO) << "Connection " << server_connection_id
QUICHE teama6ef0a62019-03-07 20:34:33 -0500785 << " added to time wait list.";
786}
787
788void QuicDispatcher::StatelesslyTerminateConnection(
dschinazi7b9278c2019-05-20 07:36:21 -0700789 QuicConnectionId server_connection_id,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500790 PacketHeaderFormat format,
fayang1de67892019-04-19 05:59:45 -0700791 bool version_flag,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500792 ParsedQuicVersion version,
793 QuicErrorCode error_code,
vasilvvc48c8712019-03-11 13:38:16 -0700794 const std::string& error_details,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500795 QuicTimeWaitListManager::TimeWaitAction action) {
fayang1de67892019-04-19 05:59:45 -0700796 if (format != IETF_QUIC_LONG_HEADER_PACKET &&
797 (!GetQuicReloadableFlag(quic_terminate_gquic_connection_as_ietf) ||
798 !version_flag)) {
dschinazi7b9278c2019-05-20 07:36:21 -0700799 QUIC_DVLOG(1) << "Statelessly terminating " << server_connection_id
QUICHE teama6ef0a62019-03-07 20:34:33 -0500800 << " based on a non-ietf-long packet, action:" << action
801 << ", error_code:" << error_code
802 << ", error_details:" << error_details;
803 time_wait_list_manager_->AddConnectionIdToTimeWait(
dschinazi7b9278c2019-05-20 07:36:21 -0700804 server_connection_id, format != GOOGLE_QUIC_PACKET, action,
805 ENCRYPTION_INITIAL, nullptr);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500806 return;
807 }
808
809 // If the version is known and supported by framer, send a connection close.
fayangccbab732019-05-13 10:11:25 -0700810 if (IsSupportedVersion(version)) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500811 QUIC_DVLOG(1)
dschinazi7b9278c2019-05-20 07:36:21 -0700812 << "Statelessly terminating " << server_connection_id
QUICHE teama6ef0a62019-03-07 20:34:33 -0500813 << " based on an ietf-long packet, which has a supported version:"
814 << version << ", error_code:" << error_code
815 << ", error_details:" << error_details;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500816
dschinazi7b9278c2019-05-20 07:36:21 -0700817 StatelessConnectionTerminator terminator(server_connection_id, version,
818 helper_.get(),
819 time_wait_list_manager_.get());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500820 // This also adds the connection to time wait list.
fayang1de67892019-04-19 05:59:45 -0700821 if (format == GOOGLE_QUIC_PACKET) {
822 QUIC_RELOADABLE_FLAG_COUNT_N(quic_terminate_gquic_connection_as_ietf, 1,
823 2);
824 }
825 terminator.CloseConnection(error_code, error_details,
826 format != GOOGLE_QUIC_PACKET);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500827 return;
828 }
829
830 QUIC_DVLOG(1)
dschinazi7b9278c2019-05-20 07:36:21 -0700831 << "Statelessly terminating " << server_connection_id
QUICHE teama6ef0a62019-03-07 20:34:33 -0500832 << " based on an ietf-long packet, which has an unsupported version:"
833 << version << ", error_code:" << error_code
834 << ", error_details:" << error_details;
835 // Version is unknown or unsupported by framer, send a version negotiation
836 // with an empty version list, which can be understood by the client.
837 std::vector<std::unique_ptr<QuicEncryptedPacket>> termination_packets;
838 termination_packets.push_back(QuicFramer::BuildVersionNegotiationPacket(
dschinazib417d602019-05-29 13:08:45 -0700839 server_connection_id, EmptyQuicConnectionId(),
840 /*ietf_quic=*/format != GOOGLE_QUIC_PACKET,
nharper4fd11052019-06-04 14:23:22 -0700841 ParsedQuicVersionVector{QuicVersionReservedForNegotiation()}));
fayang1de67892019-04-19 05:59:45 -0700842 if (format == GOOGLE_QUIC_PACKET) {
843 QUIC_RELOADABLE_FLAG_COUNT_N(quic_terminate_gquic_connection_as_ietf, 2, 2);
844 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500845 time_wait_list_manager()->AddConnectionIdToTimeWait(
dschinazi7b9278c2019-05-20 07:36:21 -0700846 server_connection_id, /*ietf_quic=*/format != GOOGLE_QUIC_PACKET,
QUICHE team6987b4a2019-03-15 16:23:04 -0700847 QuicTimeWaitListManager::SEND_TERMINATION_PACKETS, ENCRYPTION_INITIAL,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500848 &termination_packets);
849}
850
851void QuicDispatcher::OnPacket() {}
852
853void QuicDispatcher::OnError(QuicFramer* framer) {
854 QuicErrorCode error = framer->error();
855 SetLastError(error);
856 QUIC_DLOG(INFO) << QuicErrorCodeToString(error);
857}
858
859bool QuicDispatcher::ShouldCreateSessionForUnknownVersion(
860 QuicVersionLabel /*version_label*/) {
861 return false;
862}
863
864bool QuicDispatcher::OnProtocolVersionMismatch(
865 ParsedQuicVersion /*received_version*/,
866 PacketHeaderFormat /*form*/) {
fayangccbab732019-05-13 10:11:25 -0700867 DCHECK(!no_framer_);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500868 QUIC_BUG_IF(
869 !time_wait_list_manager_->IsConnectionIdInTimeWait(
dschinazi7b9278c2019-05-20 07:36:21 -0700870 current_server_connection_id_) &&
QUICHE teama6ef0a62019-03-07 20:34:33 -0500871 !ShouldCreateSessionForUnknownVersion(framer_.last_version_label()))
872 << "Unexpected version mismatch: "
873 << QuicVersionLabelToString(framer_.last_version_label());
874
875 // Keep processing after protocol mismatch - this will be dealt with by the
876 // time wait list or connection that we will create.
877 return true;
878}
879
880void QuicDispatcher::OnPublicResetPacket(
881 const QuicPublicResetPacket& /*packet*/) {
882 DCHECK(false);
883}
884
885void QuicDispatcher::OnVersionNegotiationPacket(
886 const QuicVersionNegotiationPacket& /*packet*/) {
887 DCHECK(false);
888}
889
dschinazi244f6dc2019-05-06 15:45:16 -0700890void QuicDispatcher::OnRetryPacket(QuicConnectionId /*original_connection_id*/,
891 QuicConnectionId /*new_connection_id*/,
892 QuicStringPiece /*retry_token*/) {
893 DCHECK(false);
894}
895
QUICHE teama6ef0a62019-03-07 20:34:33 -0500896void QuicDispatcher::OnDecryptedPacket(EncryptionLevel level) {
897 DCHECK(false);
898}
899
900bool QuicDispatcher::OnPacketHeader(const QuicPacketHeader& /*header*/) {
901 DCHECK(false);
902 return false;
903}
904
905void QuicDispatcher::OnCoalescedPacket(const QuicEncryptedPacket& /*packet*/) {
906 DCHECK(false);
907}
908
909bool QuicDispatcher::OnStreamFrame(const QuicStreamFrame& /*frame*/) {
910 DCHECK(false);
911 return false;
912}
913
914bool QuicDispatcher::OnCryptoFrame(const QuicCryptoFrame& /*frame*/) {
915 DCHECK(false);
916 return false;
917}
918
919bool QuicDispatcher::OnAckFrameStart(QuicPacketNumber /*largest_acked*/,
920 QuicTime::Delta /*ack_delay_time*/) {
921 DCHECK(false);
922 return false;
923}
924
925bool QuicDispatcher::OnAckRange(QuicPacketNumber /*start*/,
926 QuicPacketNumber /*end*/) {
927 DCHECK(false);
928 return false;
929}
930
931bool QuicDispatcher::OnAckTimestamp(QuicPacketNumber /*packet_number*/,
932 QuicTime /*timestamp*/) {
933 DCHECK(false);
934 return false;
935}
936
937bool QuicDispatcher::OnAckFrameEnd(QuicPacketNumber /*start*/) {
938 DCHECK(false);
939 return false;
940}
941
942bool QuicDispatcher::OnStopWaitingFrame(const QuicStopWaitingFrame& /*frame*/) {
943 DCHECK(false);
944 return false;
945}
946
947bool QuicDispatcher::OnPaddingFrame(const QuicPaddingFrame& /*frame*/) {
948 DCHECK(false);
949 return false;
950}
951
952bool QuicDispatcher::OnPingFrame(const QuicPingFrame& /*frame*/) {
953 DCHECK(false);
954 return false;
955}
956
957bool QuicDispatcher::OnRstStreamFrame(const QuicRstStreamFrame& /*frame*/) {
958 DCHECK(false);
959 return false;
960}
961
962bool QuicDispatcher::OnConnectionCloseFrame(
963 const QuicConnectionCloseFrame& /*frame*/) {
964 DCHECK(false);
965 return false;
966}
967
fkastenholz3c4eabf2019-04-22 07:49:59 -0700968bool QuicDispatcher::OnMaxStreamsFrame(const QuicMaxStreamsFrame& frame) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500969 return true;
970}
971
fkastenholz3c4eabf2019-04-22 07:49:59 -0700972bool QuicDispatcher::OnStreamsBlockedFrame(
973 const QuicStreamsBlockedFrame& frame) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500974 return true;
975}
976
977bool QuicDispatcher::OnStopSendingFrame(const QuicStopSendingFrame& /*frame*/) {
978 DCHECK(false);
979 return false;
980}
981
982bool QuicDispatcher::OnPathChallengeFrame(
983 const QuicPathChallengeFrame& /*frame*/) {
984 DCHECK(false);
985 return false;
986}
987
988bool QuicDispatcher::OnPathResponseFrame(
989 const QuicPathResponseFrame& /*frame*/) {
990 DCHECK(false);
991 return false;
992}
993
994bool QuicDispatcher::OnGoAwayFrame(const QuicGoAwayFrame& /*frame*/) {
995 DCHECK(false);
996 return false;
997}
998
999bool QuicDispatcher::OnWindowUpdateFrame(
1000 const QuicWindowUpdateFrame& /*frame*/) {
1001 DCHECK(false);
1002 return false;
1003}
1004
1005bool QuicDispatcher::OnBlockedFrame(const QuicBlockedFrame& frame) {
1006 DCHECK(false);
1007 return false;
1008}
1009
1010bool QuicDispatcher::OnNewConnectionIdFrame(
1011 const QuicNewConnectionIdFrame& frame) {
1012 DCHECK(false);
1013 return false;
1014}
1015
1016bool QuicDispatcher::OnRetireConnectionIdFrame(
1017 const QuicRetireConnectionIdFrame& frame) {
1018 DCHECK(false);
1019 return false;
1020}
1021
1022bool QuicDispatcher::OnNewTokenFrame(const QuicNewTokenFrame& frame) {
1023 DCHECK(false);
1024 return false;
1025}
1026
1027bool QuicDispatcher::OnMessageFrame(const QuicMessageFrame& frame) {
1028 DCHECK(false);
1029 return false;
1030}
1031
1032void QuicDispatcher::OnPacketComplete() {
1033 DCHECK(false);
1034}
1035
1036bool QuicDispatcher::IsValidStatelessResetToken(QuicUint128 token) const {
1037 DCHECK(false);
1038 return false;
1039}
1040
1041void QuicDispatcher::OnAuthenticatedIetfStatelessResetPacket(
1042 const QuicIetfStatelessResetPacket& packet) {
1043 DCHECK(false);
1044}
1045
1046void QuicDispatcher::OnExpiredPackets(
dschinazi7b9278c2019-05-20 07:36:21 -07001047 QuicConnectionId server_connection_id,
QUICHE teama6ef0a62019-03-07 20:34:33 -05001048 BufferedPacketList early_arrived_packets) {
1049 QUIC_CODE_COUNT(quic_reject_buffered_packets_expired);
1050 StatelesslyTerminateConnection(
dschinazi7b9278c2019-05-20 07:36:21 -07001051 server_connection_id,
QUICHE teama6ef0a62019-03-07 20:34:33 -05001052 early_arrived_packets.ietf_quic ? IETF_QUIC_LONG_HEADER_PACKET
1053 : GOOGLE_QUIC_PACKET,
fayang1de67892019-04-19 05:59:45 -07001054 /*version_flag=*/true, early_arrived_packets.version,
1055 QUIC_HANDSHAKE_FAILED, "Packets buffered for too long",
QUICHE teama6ef0a62019-03-07 20:34:33 -05001056 quic::QuicTimeWaitListManager::SEND_STATELESS_RESET);
1057}
1058
1059void QuicDispatcher::ProcessBufferedChlos(size_t max_connections_to_create) {
1060 // Reset the counter before starting creating connections.
1061 new_sessions_allowed_per_event_loop_ = max_connections_to_create;
1062 for (; new_sessions_allowed_per_event_loop_ > 0;
1063 --new_sessions_allowed_per_event_loop_) {
dschinazi7b9278c2019-05-20 07:36:21 -07001064 QuicConnectionId server_connection_id;
QUICHE teama6ef0a62019-03-07 20:34:33 -05001065 BufferedPacketList packet_list =
dschinazi7b9278c2019-05-20 07:36:21 -07001066 buffered_packets_.DeliverPacketsForNextConnection(
1067 &server_connection_id);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001068 const std::list<BufferedPacket>& packets = packet_list.buffered_packets;
1069 if (packets.empty()) {
1070 return;
1071 }
dschinazi7b9278c2019-05-20 07:36:21 -07001072 QuicConnectionId original_connection_id = server_connection_id;
1073 server_connection_id = MaybeReplaceServerConnectionId(server_connection_id,
1074 packet_list.version);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001075 QuicSession* session =
dschinazi7b9278c2019-05-20 07:36:21 -07001076 CreateQuicSession(server_connection_id, packets.front().peer_address,
QUICHE teama6ef0a62019-03-07 20:34:33 -05001077 packet_list.alpn, packet_list.version);
dschinazi7b9278c2019-05-20 07:36:21 -07001078 if (original_connection_id != server_connection_id) {
QUICHE teamc65d1d12019-03-19 20:58:04 -07001079 session->connection()->AddIncomingConnectionId(original_connection_id);
1080 }
dschinazi7b9278c2019-05-20 07:36:21 -07001081 QUIC_DLOG(INFO) << "Created new session for " << server_connection_id;
1082 session_map_.insert(
1083 std::make_pair(server_connection_id, QuicWrapUnique(session)));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001084 DeliverPacketsToSession(packets, session);
1085 }
1086}
1087
1088bool QuicDispatcher::HasChlosBuffered() const {
1089 return buffered_packets_.HasChlosBuffered();
1090}
1091
1092bool QuicDispatcher::ShouldCreateOrBufferPacketForConnection(
dschinazi7b9278c2019-05-20 07:36:21 -07001093 QuicConnectionId server_connection_id,
QUICHE teama6ef0a62019-03-07 20:34:33 -05001094 bool ietf_quic) {
dschinazi7b9278c2019-05-20 07:36:21 -07001095 QUIC_VLOG(1) << "Received packet from new connection "
1096 << server_connection_id;
QUICHE teama6ef0a62019-03-07 20:34:33 -05001097 return true;
1098}
1099
1100// Return true if there is any packet buffered in the store.
dschinazi7b9278c2019-05-20 07:36:21 -07001101bool QuicDispatcher::HasBufferedPackets(QuicConnectionId server_connection_id) {
1102 return buffered_packets_.HasBufferedPackets(server_connection_id);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001103}
1104
dschinazi7b9278c2019-05-20 07:36:21 -07001105void QuicDispatcher::OnBufferPacketFailure(
1106 EnqueuePacketResult result,
1107 QuicConnectionId server_connection_id) {
1108 QUIC_DLOG(INFO) << "Fail to buffer packet on connection "
1109 << server_connection_id << " because of " << result;
QUICHE teama6ef0a62019-03-07 20:34:33 -05001110}
1111
QUICHE teama6ef0a62019-03-07 20:34:33 -05001112QuicTimeWaitListManager* QuicDispatcher::CreateQuicTimeWaitListManager() {
1113 return new QuicTimeWaitListManager(writer_.get(), this, helper_->GetClock(),
1114 alarm_factory_.get());
1115}
1116
dschinazi7b9278c2019-05-20 07:36:21 -07001117void QuicDispatcher::BufferEarlyPacket(QuicConnectionId server_connection_id,
QUICHE teama6ef0a62019-03-07 20:34:33 -05001118 bool ietf_quic,
1119 ParsedQuicVersion version) {
dschinazi7b9278c2019-05-20 07:36:21 -07001120 bool is_new_connection =
1121 !buffered_packets_.HasBufferedPackets(server_connection_id);
1122 if (is_new_connection && !ShouldCreateOrBufferPacketForConnection(
1123 server_connection_id, ietf_quic)) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001124 return;
1125 }
1126
1127 EnqueuePacketResult rs = buffered_packets_.EnqueuePacket(
dschinazi7b9278c2019-05-20 07:36:21 -07001128 server_connection_id, ietf_quic, *current_packet_, current_self_address_,
QUICHE teama6ef0a62019-03-07 20:34:33 -05001129 current_peer_address_, /*is_chlo=*/false,
1130 /*alpn=*/"", version);
1131 if (rs != EnqueuePacketResult::SUCCESS) {
dschinazi7b9278c2019-05-20 07:36:21 -07001132 OnBufferPacketFailure(rs, server_connection_id);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001133 }
1134}
1135
1136void QuicDispatcher::ProcessChlo(PacketHeaderFormat form,
1137 ParsedQuicVersion version) {
1138 if (!accept_new_connections_) {
1139 // Don't any create new connection.
1140 QUIC_CODE_COUNT(quic_reject_stop_accepting_new_connections);
1141 StatelesslyTerminateConnection(
dschinazi7b9278c2019-05-20 07:36:21 -07001142 current_server_connection_id(), form, /*version_flag=*/true, version,
fayang1de67892019-04-19 05:59:45 -07001143 QUIC_HANDSHAKE_FAILED, "Stop accepting new connections",
QUICHE teama6ef0a62019-03-07 20:34:33 -05001144 quic::QuicTimeWaitListManager::SEND_STATELESS_RESET);
1145 // Time wait list will reject the packet correspondingly.
1146 time_wait_list_manager()->ProcessPacket(
dschinazi7b9278c2019-05-20 07:36:21 -07001147 current_self_address(), current_peer_address(),
1148 current_server_connection_id(), form, GetPerPacketContext());
QUICHE teama6ef0a62019-03-07 20:34:33 -05001149 return;
1150 }
dschinazi7b9278c2019-05-20 07:36:21 -07001151 if (!buffered_packets_.HasBufferedPackets(current_server_connection_id_) &&
1152 !ShouldCreateOrBufferPacketForConnection(current_server_connection_id_,
QUICHE teama6ef0a62019-03-07 20:34:33 -05001153 form != GOOGLE_QUIC_PACKET)) {
1154 return;
1155 }
QUICHE teamf356d9e2019-06-12 15:34:32 -07001156 if (FLAGS_quic_allow_chlo_buffering &&
QUICHE teama6ef0a62019-03-07 20:34:33 -05001157 new_sessions_allowed_per_event_loop_ <= 0) {
1158 // Can't create new session any more. Wait till next event loop.
dschinazi7b9278c2019-05-20 07:36:21 -07001159 QUIC_BUG_IF(
1160 buffered_packets_.HasChloForConnection(current_server_connection_id_));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001161 EnqueuePacketResult rs = buffered_packets_.EnqueuePacket(
dschinazi7b9278c2019-05-20 07:36:21 -07001162 current_server_connection_id_, form != GOOGLE_QUIC_PACKET,
1163 *current_packet_, current_self_address_, current_peer_address_,
fayangccbab732019-05-13 10:11:25 -07001164 /*is_chlo=*/true, current_alpn_, version);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001165 if (rs != EnqueuePacketResult::SUCCESS) {
dschinazi7b9278c2019-05-20 07:36:21 -07001166 OnBufferPacketFailure(rs, current_server_connection_id_);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001167 }
1168 return;
1169 }
QUICHE teamc65d1d12019-03-19 20:58:04 -07001170
dschinazi7b9278c2019-05-20 07:36:21 -07001171 QuicConnectionId original_connection_id = current_server_connection_id_;
1172 current_server_connection_id_ =
1173 MaybeReplaceServerConnectionId(current_server_connection_id_, version);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001174 // Creates a new session and process all buffered packets for this connection.
dschinazi7b9278c2019-05-20 07:36:21 -07001175 QuicSession* session =
1176 CreateQuicSession(current_server_connection_id_, current_peer_address_,
1177 current_alpn_, version);
1178 if (original_connection_id != current_server_connection_id_) {
QUICHE teamc65d1d12019-03-19 20:58:04 -07001179 session->connection()->AddIncomingConnectionId(original_connection_id);
1180 }
dschinazi7b9278c2019-05-20 07:36:21 -07001181 QUIC_DLOG(INFO) << "Created new session for "
1182 << current_server_connection_id_;
QUICHE teama6ef0a62019-03-07 20:34:33 -05001183 session_map_.insert(
dschinazi7b9278c2019-05-20 07:36:21 -07001184 std::make_pair(current_server_connection_id_, QuicWrapUnique(session)));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001185 std::list<BufferedPacket> packets =
dschinazi7b9278c2019-05-20 07:36:21 -07001186 buffered_packets_.DeliverPackets(current_server_connection_id_)
1187 .buffered_packets;
QUICHE teama6ef0a62019-03-07 20:34:33 -05001188 // Process CHLO at first.
1189 session->ProcessUdpPacket(current_self_address_, current_peer_address_,
1190 *current_packet_);
1191 // Deliver queued-up packets in the same order as they arrived.
1192 // Do this even when flag is off because there might be still some packets
1193 // buffered in the store before flag is turned off.
1194 DeliverPacketsToSession(packets, session);
1195 --new_sessions_allowed_per_event_loop_;
1196}
1197
1198const QuicSocketAddress QuicDispatcher::GetClientAddress() const {
1199 return current_peer_address_;
1200}
1201
1202bool QuicDispatcher::ShouldDestroySessionAsynchronously() {
1203 return true;
1204}
1205
1206void QuicDispatcher::SetLastError(QuicErrorCode error) {
1207 last_error_ = error;
1208}
1209
1210bool QuicDispatcher::OnUnauthenticatedUnknownPublicHeader(
1211 const QuicPacketHeader& header) {
1212 return true;
1213}
1214
wub0a4b9c52019-05-28 13:18:58 -07001215void QuicDispatcher::ProcessOrBufferPacket(
dschinazi7b9278c2019-05-20 07:36:21 -07001216 QuicConnectionId server_connection_id,
1217 PacketHeaderFormat form,
1218 bool version_flag,
1219 ParsedQuicVersion version) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001220 if (version.handshake_protocol == PROTOCOL_TLS1_3) {
dschinazi7b9278c2019-05-20 07:36:21 -07001221 ProcessUnauthenticatedHeaderFate(kFateProcess, server_connection_id, form,
fayang1de67892019-04-19 05:59:45 -07001222 version_flag, version);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001223 return;
1224 // TODO(nharper): Support buffering non-ClientHello packets when using TLS.
1225 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001226
wub0a4b9c52019-05-28 13:18:58 -07001227 ChloAlpnExtractor alpn_extractor;
QUICHE teamf356d9e2019-06-12 15:34:32 -07001228 if (FLAGS_quic_allow_chlo_buffering &&
wub0a4b9c52019-05-28 13:18:58 -07001229 !ChloExtractor::Extract(*current_packet_, GetSupportedVersions(),
QUICHE teama6ef0a62019-03-07 20:34:33 -05001230 config_->create_session_tag_indicators(),
wub0a4b9c52019-05-28 13:18:58 -07001231 &alpn_extractor, server_connection_id.length())) {
1232 // Buffer non-CHLO packets.
dschinazi7b9278c2019-05-20 07:36:21 -07001233 ProcessUnauthenticatedHeaderFate(kFateBuffer, server_connection_id, form,
fayang1de67892019-04-19 05:59:45 -07001234 version_flag, version);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001235 return;
1236 }
wub0a4b9c52019-05-28 13:18:58 -07001237 current_alpn_ = alpn_extractor.ConsumeAlpn();
1238 ProcessUnauthenticatedHeaderFate(kFateProcess, server_connection_id, form,
1239 version_flag, version);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001240}
1241
1242const QuicTransportVersionVector&
1243QuicDispatcher::GetSupportedTransportVersions() {
1244 return version_manager_->GetSupportedTransportVersions();
1245}
1246
1247const ParsedQuicVersionVector& QuicDispatcher::GetSupportedVersions() {
1248 return version_manager_->GetSupportedVersions();
1249}
1250
1251void QuicDispatcher::DeliverPacketsToSession(
1252 const std::list<BufferedPacket>& packets,
1253 QuicSession* session) {
1254 for (const BufferedPacket& packet : packets) {
1255 session->ProcessUdpPacket(packet.self_address, packet.peer_address,
1256 *(packet.packet));
1257 }
1258}
1259
1260void QuicDispatcher::DisableFlagValidation() {
fayangccbab732019-05-13 10:11:25 -07001261 if (!no_framer_) {
1262 framer_.set_validate_flags(false);
1263 }
1264}
1265
1266bool QuicDispatcher::IsSupportedVersion(const ParsedQuicVersion version) {
1267 if (!no_framer_) {
1268 return framer_.IsSupportedVersion(version);
1269 }
1270 for (const ParsedQuicVersion& supported_version :
1271 version_manager_->GetSupportedVersions()) {
1272 if (version == supported_version) {
1273 return true;
1274 }
1275 }
1276 return false;
QUICHE teama6ef0a62019-03-07 20:34:33 -05001277}
1278
1279} // namespace quic