blob: f7973e0754e256078bbfa830bfa71faf96e4648b [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
dschinazi17d42422019-06-18 16:35:07 -070074 void OnUnrecoverableError(QuicErrorCode /*error*/,
75 const std::string& /*error_details*/) override {}
QUICHE teama6ef0a62019-03-07 20:34:33 -050076
QUICHE teama6ef0a62019-03-07 20:34:33 -050077 // QuicStreamFrameDataProducer
dschinazi17d42422019-06-18 16:35:07 -070078 WriteStreamDataResult WriteStreamData(QuicStreamId /*id*/,
QUICHE teama6ef0a62019-03-07 20:34:33 -050079 QuicStreamOffset offset,
80 QuicByteCount data_length,
81 QuicDataWriter* writer) override {
82 if (send_buffer_.WriteStreamData(offset, data_length, writer)) {
83 return WRITE_SUCCESS;
84 }
85 return WRITE_FAILED;
86 }
dschinazi17d42422019-06-18 16:35:07 -070087 bool WriteCryptoData(EncryptionLevel /*level*/,
QUICHE teama6ef0a62019-03-07 20:34:33 -050088 QuicStreamOffset offset,
89 QuicByteCount data_length,
90 QuicDataWriter* writer) override {
91 return send_buffer_.WriteStreamData(offset, data_length, writer);
92 }
93
94 std::vector<std::unique_ptr<QuicEncryptedPacket>>* packets() {
95 return &packets_;
96 }
97
98 private:
99 std::vector<std::unique_ptr<QuicEncryptedPacket>> packets_;
100 // This is only needed until the packets are encrypted. Once packets are
101 // encrypted, the stream data is no longer required.
102 QuicStreamSendBuffer send_buffer_;
103};
104
105// Helper for statelessly closing connections by generating the
106// correct termination packets and adding the connection to the time wait
107// list manager.
108class StatelessConnectionTerminator {
109 public:
dschinazi7b9278c2019-05-20 07:36:21 -0700110 StatelessConnectionTerminator(QuicConnectionId server_connection_id,
fayangf7c569c2019-05-07 11:56:51 -0700111 const ParsedQuicVersion version,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500112 QuicConnectionHelperInterface* helper,
113 QuicTimeWaitListManager* time_wait_list_manager)
dschinazi7b9278c2019-05-20 07:36:21 -0700114 : server_connection_id_(server_connection_id),
fayangf7c569c2019-05-07 11:56:51 -0700115 framer_(ParsedQuicVersionVector{version},
116 /*unused*/ QuicTime::Zero(),
117 Perspective::IS_SERVER,
118 /*unused*/ kQuicDefaultConnectionIdLength),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500119 collector_(helper->GetStreamSendBufferAllocator()),
dschinazi7b9278c2019-05-20 07:36:21 -0700120 creator_(server_connection_id, &framer_, &collector_),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500121 time_wait_list_manager_(time_wait_list_manager) {
fayangf7c569c2019-05-07 11:56:51 -0700122 framer_.set_data_producer(&collector_);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500123 }
124
125 ~StatelessConnectionTerminator() {
126 // Clear framer's producer.
fayangf7c569c2019-05-07 11:56:51 -0700127 framer_.set_data_producer(nullptr);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500128 }
129
130 // Generates a packet containing a CONNECTION_CLOSE frame specifying
131 // |error_code| and |error_details| and add the connection to time wait.
132 void CloseConnection(QuicErrorCode error_code,
vasilvvc48c8712019-03-11 13:38:16 -0700133 const std::string& error_details,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500134 bool ietf_quic) {
fkastenholze9d71a82019-04-09 05:12:13 -0700135 QuicConnectionCloseFrame* frame =
136 new QuicConnectionCloseFrame(error_code, error_details);
fkastenholz305e1732019-06-18 05:01:22 -0700137 if (VersionHasIetfQuicFrames(framer_.transport_version())) {
fkastenholz72f509b2019-04-10 09:17:49 -0700138 frame->close_type = IETF_QUIC_TRANSPORT_CONNECTION_CLOSE;
139 }
140
QUICHE teama6ef0a62019-03-07 20:34:33 -0500141 if (!creator_.AddSavedFrame(QuicFrame(frame), NOT_RETRANSMISSION)) {
142 QUIC_BUG << "Unable to add frame to an empty packet";
143 delete frame;
144 return;
145 }
146 creator_.Flush();
147 DCHECK_EQ(1u, collector_.packets()->size());
148 time_wait_list_manager_->AddConnectionIdToTimeWait(
dschinazi7b9278c2019-05-20 07:36:21 -0700149 server_connection_id_, ietf_quic,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500150 QuicTimeWaitListManager::SEND_TERMINATION_PACKETS,
QUICHE team6987b4a2019-03-15 16:23:04 -0700151 quic::ENCRYPTION_INITIAL, collector_.packets());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500152 }
153
QUICHE teama6ef0a62019-03-07 20:34:33 -0500154 private:
dschinazi7b9278c2019-05-20 07:36:21 -0700155 QuicConnectionId server_connection_id_;
fayangf7c569c2019-05-07 11:56:51 -0700156 QuicFramer framer_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500157 // Set as the visitor of |creator_| to collect any generated packets.
158 PacketCollector collector_;
159 QuicPacketCreator creator_;
160 QuicTimeWaitListManager* time_wait_list_manager_;
161};
162
163// Class which extracts the ALPN from a CHLO packet.
164class ChloAlpnExtractor : public ChloExtractor::Delegate {
165 public:
dschinazi17d42422019-06-18 16:35:07 -0700166 void OnChlo(QuicTransportVersion /*version*/,
167 QuicConnectionId /*server_connection_id*/,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500168 const CryptoHandshakeMessage& chlo) override {
169 QuicStringPiece alpn_value;
170 if (chlo.GetStringPiece(kALPN, &alpn_value)) {
vasilvvc48c8712019-03-11 13:38:16 -0700171 alpn_ = std::string(alpn_value);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500172 }
173 }
174
vasilvvc48c8712019-03-11 13:38:16 -0700175 std::string&& ConsumeAlpn() { return std::move(alpn_); }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500176
177 private:
vasilvvc48c8712019-03-11 13:38:16 -0700178 std::string alpn_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500179};
180
QUICHE teama6ef0a62019-03-07 20:34:33 -0500181} // namespace
182
183QuicDispatcher::QuicDispatcher(
184 const QuicConfig* config,
185 const QuicCryptoServerConfig* crypto_config,
186 QuicVersionManager* version_manager,
187 std::unique_ptr<QuicConnectionHelperInterface> helper,
188 std::unique_ptr<QuicCryptoServerStream::Helper> session_helper,
189 std::unique_ptr<QuicAlarmFactory> alarm_factory,
dschinazi8ff74822019-05-28 16:37:20 -0700190 uint8_t expected_server_connection_id_length)
QUICHE teama6ef0a62019-03-07 20:34:33 -0500191 : config_(config),
192 crypto_config_(crypto_config),
193 compressed_certs_cache_(
194 QuicCompressedCertsCache::kQuicCompressedCertsCacheSize),
195 helper_(std::move(helper)),
196 session_helper_(std::move(session_helper)),
197 alarm_factory_(std::move(alarm_factory)),
198 delete_sessions_alarm_(
199 alarm_factory_->CreateAlarm(new DeleteSessionsAlarm(this))),
200 buffered_packets_(this, helper_->GetClock(), alarm_factory_.get()),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500201 version_manager_(version_manager),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500202 last_error_(QUIC_NO_ERROR),
203 new_sessions_allowed_per_event_loop_(0u),
QUICHE team963d57e2019-03-21 10:58:47 -0700204 accept_new_connections_(true),
dschinazi7b9278c2019-05-20 07:36:21 -0700205 allow_short_initial_server_connection_ids_(false),
dschinazi8ff74822019-05-28 16:37:20 -0700206 expected_server_connection_id_length_(
207 expected_server_connection_id_length),
fayang91475c42019-06-19 08:04:26 -0700208 should_update_expected_server_connection_id_length_(false) {}
QUICHE teama6ef0a62019-03-07 20:34:33 -0500209
210QuicDispatcher::~QuicDispatcher() {
211 session_map_.clear();
212 closed_session_list_.clear();
213}
214
215void QuicDispatcher::InitializeWithWriter(QuicPacketWriter* writer) {
216 DCHECK(writer_ == nullptr);
217 writer_.reset(writer);
218 time_wait_list_manager_.reset(CreateQuicTimeWaitListManager());
219}
220
221void QuicDispatcher::ProcessPacket(const QuicSocketAddress& self_address,
222 const QuicSocketAddress& peer_address,
223 const QuicReceivedPacket& packet) {
dschinazi965ce092019-05-23 06:29:01 -0700224 QUIC_DVLOG(2) << "Dispatcher received encrypted " << packet.length()
225 << " bytes:" << std::endl
226 << QuicTextUtils::HexDump(
227 QuicStringPiece(packet.data(), packet.length()));
fayang1ed1f762019-06-24 11:40:04 -0700228 ReceivedPacketInfo packet_info(self_address, peer_address, packet);
fayang1f123502019-05-14 08:05:16 -0700229 std::string detailed_error;
fayangccbab732019-05-13 10:11:25 -0700230 const QuicErrorCode error = QuicFramer::ProcessPacketDispatcher(
fayang1ed1f762019-06-24 11:40:04 -0700231 packet, expected_server_connection_id_length_, &packet_info.form,
232 &packet_info.version_flag, &packet_info.version_label,
233 &packet_info.destination_connection_id, &packet_info.source_connection_id,
fayangccbab732019-05-13 10:11:25 -0700234 &detailed_error);
235 if (error != QUIC_NO_ERROR) {
236 // Packet has framing error.
237 SetLastError(error);
238 QUIC_DLOG(ERROR) << detailed_error;
239 return;
240 }
fayang1ed1f762019-06-24 11:40:04 -0700241 packet_info.version = ParseQuicVersionLabel(packet_info.version_label);
242 if (packet_info.destination_connection_id.length() !=
dschinazi8ff74822019-05-28 16:37:20 -0700243 expected_server_connection_id_length_ &&
244 !should_update_expected_server_connection_id_length_ &&
fayangccbab732019-05-13 10:11:25 -0700245 !QuicUtils::VariableLengthConnectionIdAllowedForVersion(
fayang1ed1f762019-06-24 11:40:04 -0700246 packet_info.version.transport_version)) {
fayangccbab732019-05-13 10:11:25 -0700247 SetLastError(QUIC_INVALID_PACKET_HEADER);
248 QUIC_DLOG(ERROR) << "Invalid Connection Id Length";
249 return;
250 }
dschinazi8ff74822019-05-28 16:37:20 -0700251 if (should_update_expected_server_connection_id_length_) {
fayang1ed1f762019-06-24 11:40:04 -0700252 expected_server_connection_id_length_ =
253 packet_info.destination_connection_id.length();
fayangccbab732019-05-13 10:11:25 -0700254 }
fayang91475c42019-06-19 08:04:26 -0700255
fayang1ed1f762019-06-24 11:40:04 -0700256 if (MaybeDispatchPacket(packet_info)) {
fayang91475c42019-06-19 08:04:26 -0700257 // Packet has been dropped or successfully dispatched, stop processing.
fayangccbab732019-05-13 10:11:25 -0700258 return;
259 }
fayang1ed1f762019-06-24 11:40:04 -0700260 ProcessHeader(&packet_info);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500261}
262
dschinazi7b9278c2019-05-20 07:36:21 -0700263QuicConnectionId QuicDispatcher::MaybeReplaceServerConnectionId(
264 QuicConnectionId server_connection_id,
QUICHE teamc65d1d12019-03-19 20:58:04 -0700265 ParsedQuicVersion version) {
fayang91475c42019-06-19 08:04:26 -0700266 if (server_connection_id.length() == expected_server_connection_id_length_) {
dschinazi7b9278c2019-05-20 07:36:21 -0700267 return server_connection_id;
QUICHE teamc65d1d12019-03-19 20:58:04 -0700268 }
269 DCHECK(QuicUtils::VariableLengthConnectionIdAllowedForVersion(
270 version.transport_version));
dschinazi7b9278c2019-05-20 07:36:21 -0700271 auto it = connection_id_map_.find(server_connection_id);
QUICHE teamc65d1d12019-03-19 20:58:04 -0700272 if (it != connection_id_map_.end()) {
273 return it->second;
274 }
275 QuicConnectionId new_connection_id =
276 session_helper_->GenerateConnectionIdForReject(version.transport_version,
dschinazi7b9278c2019-05-20 07:36:21 -0700277 server_connection_id);
fayang91475c42019-06-19 08:04:26 -0700278 DCHECK_EQ(expected_server_connection_id_length_, new_connection_id.length());
dschinazi7b9278c2019-05-20 07:36:21 -0700279 connection_id_map_.insert(
280 std::make_pair(server_connection_id, new_connection_id));
281 QUIC_DLOG(INFO) << "Replacing incoming connection ID " << server_connection_id
QUICHE teamc65d1d12019-03-19 20:58:04 -0700282 << " with " << new_connection_id;
283 return new_connection_id;
284}
285
fayang91475c42019-06-19 08:04:26 -0700286bool QuicDispatcher::MaybeDispatchPacket(
fayang1ed1f762019-06-24 11:40:04 -0700287 const ReceivedPacketInfo& packet_info) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500288 // Port zero is only allowed for unidirectional UDP, so is disallowed by QUIC.
289 // Given that we can't even send a reply rejecting the packet, just drop the
290 // packet.
fayang1ed1f762019-06-24 11:40:04 -0700291 if (packet_info.peer_address.port() == 0) {
fayang91475c42019-06-19 08:04:26 -0700292 return true;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500293 }
294
fayang1ed1f762019-06-24 11:40:04 -0700295 QuicConnectionId server_connection_id = packet_info.destination_connection_id;
QUICHE team8e2e4532019-03-14 14:37:56 -0700296
QUICHE team963d57e2019-03-21 10:58:47 -0700297 // The IETF spec requires the client to generate an initial server
298 // connection ID that is at least 64 bits long. After that initial
299 // connection ID, the dispatcher picks a new one of its expected length.
300 // Therefore we should never receive a connection ID that is smaller
301 // than 64 bits and smaller than what we expect.
dschinazi7b9278c2019-05-20 07:36:21 -0700302 if (server_connection_id.length() < kQuicMinimumInitialConnectionIdLength &&
fayang91475c42019-06-19 08:04:26 -0700303 server_connection_id.length() < expected_server_connection_id_length_ &&
dschinazi7b9278c2019-05-20 07:36:21 -0700304 !allow_short_initial_server_connection_ids_) {
fayang1ed1f762019-06-24 11:40:04 -0700305 DCHECK(packet_info.version_flag);
QUICHE team963d57e2019-03-21 10:58:47 -0700306 DCHECK(QuicUtils::VariableLengthConnectionIdAllowedForVersion(
fayang1ed1f762019-06-24 11:40:04 -0700307 packet_info.version.transport_version));
QUICHE team963d57e2019-03-21 10:58:47 -0700308 QUIC_DLOG(INFO) << "Packet with short destination connection ID "
dschinazi7b9278c2019-05-20 07:36:21 -0700309 << server_connection_id << " expected "
fayang91475c42019-06-19 08:04:26 -0700310 << static_cast<int>(expected_server_connection_id_length_);
dschinaziee07e472019-06-19 09:56:56 -0700311 if (!GetQuicReloadableFlag(quic_drop_invalid_small_initial_connection_id)) {
fayang17230ac2019-06-21 06:28:28 -0700312 // Add this connection_id to the time-wait state, to safely reject
313 // future packets.
314 QUIC_DLOG(INFO) << "Adding connection ID " << server_connection_id
315 << " to time-wait list.";
316 StatelesslyTerminateConnection(
fayang1ed1f762019-06-24 11:40:04 -0700317 server_connection_id, packet_info.form, packet_info.version_flag,
318 packet_info.version, QUIC_HANDSHAKE_FAILED, "Reject connection",
fayang17230ac2019-06-21 06:28:28 -0700319 quic::QuicTimeWaitListManager::SEND_STATELESS_RESET);
320
321 DCHECK(time_wait_list_manager_->IsConnectionIdInTimeWait(
322 server_connection_id));
323 time_wait_list_manager_->ProcessPacket(
fayang1ed1f762019-06-24 11:40:04 -0700324 packet_info.self_address, packet_info.peer_address,
325 server_connection_id, packet_info.form, GetPerPacketContext());
fayang17230ac2019-06-21 06:28:28 -0700326
327 buffered_packets_.DiscardPackets(server_connection_id);
dschinaziee07e472019-06-19 09:56:56 -0700328 } else {
329 QUIC_RELOADABLE_FLAG_COUNT(quic_drop_invalid_small_initial_connection_id);
fayang17230ac2019-06-21 06:28:28 -0700330 // Drop the packet silently.
dschinaziee07e472019-06-19 09:56:56 -0700331 }
fayang91475c42019-06-19 08:04:26 -0700332 return true;
QUICHE team963d57e2019-03-21 10:58:47 -0700333 }
334
QUICHE teama6ef0a62019-03-07 20:34:33 -0500335 // Packets with connection IDs for active connections are processed
336 // immediately.
dschinazi7b9278c2019-05-20 07:36:21 -0700337 auto it = session_map_.find(server_connection_id);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500338 if (it != session_map_.end()) {
dschinazi7b9278c2019-05-20 07:36:21 -0700339 DCHECK(!buffered_packets_.HasBufferedPackets(server_connection_id));
fayang1ed1f762019-06-24 11:40:04 -0700340 it->second->ProcessUdpPacket(packet_info.self_address,
341 packet_info.peer_address, packet_info.packet);
fayang91475c42019-06-19 08:04:26 -0700342 return true;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500343 }
344
dschinazi7b9278c2019-05-20 07:36:21 -0700345 if (buffered_packets_.HasChloForConnection(server_connection_id)) {
fayang1ed1f762019-06-24 11:40:04 -0700346 BufferEarlyPacket(packet_info);
fayang91475c42019-06-19 08:04:26 -0700347 return true;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500348 }
349
fayang1ed1f762019-06-24 11:40:04 -0700350 if (OnFailedToDispatchPacket(packet_info)) {
fayang91475c42019-06-19 08:04:26 -0700351 return true;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500352 }
353
dschinazi7b9278c2019-05-20 07:36:21 -0700354 if (time_wait_list_manager_->IsConnectionIdInTimeWait(server_connection_id)) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500355 // This connection ID is already in time-wait state.
356 time_wait_list_manager_->ProcessPacket(
fayang1ed1f762019-06-24 11:40:04 -0700357 packet_info.self_address, packet_info.peer_address,
358 packet_info.destination_connection_id, packet_info.form,
359 GetPerPacketContext());
fayang91475c42019-06-19 08:04:26 -0700360 return true;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500361 }
362
363 // The packet has an unknown connection ID.
364
365 // Unless the packet provides a version, assume that we can continue
366 // processing using our preferred version.
fayang1ed1f762019-06-24 11:40:04 -0700367 if (packet_info.version_flag) {
368 if (!IsSupportedVersion(packet_info.version)) {
369 if (ShouldCreateSessionForUnknownVersion(packet_info.version_label)) {
fayang91475c42019-06-19 08:04:26 -0700370 return false;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500371 }
372 if (!crypto_config()->validate_chlo_size() ||
fayang1ed1f762019-06-24 11:40:04 -0700373 packet_info.packet.length() >= kMinPacketSizeForVersionNegotiation) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500374 // Since the version is not supported, send a version negotiation
375 // packet and stop processing the current packet.
fayang1ed1f762019-06-24 11:40:04 -0700376 QuicConnectionId client_connection_id =
377 packet_info.source_connection_id;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500378 time_wait_list_manager()->SendVersionNegotiationPacket(
dschinazi346b7ce2019-06-05 01:38:18 -0700379 server_connection_id, client_connection_id,
fayang1ed1f762019-06-24 11:40:04 -0700380 packet_info.form != GOOGLE_QUIC_PACKET, GetSupportedVersions(),
381 packet_info.self_address, packet_info.peer_address,
dschinazib417d602019-05-29 13:08:45 -0700382 GetPerPacketContext());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500383 }
fayang91475c42019-06-19 08:04:26 -0700384 return true;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500385 }
fayangccbab732019-05-13 10:11:25 -0700386 }
nharper55fa6132019-05-07 19:37:21 -0700387
nharper55fa6132019-05-07 19:37:21 -0700388 return false;
389}
390
fayang1ed1f762019-06-24 11:40:04 -0700391void QuicDispatcher::ProcessHeader(ReceivedPacketInfo* packet_info) {
392 QuicConnectionId server_connection_id =
393 packet_info->destination_connection_id;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500394 // Packet's connection ID is unknown. Apply the validity checks.
wub2a5670f2019-06-13 13:39:16 -0700395 // TODO(wub): Determine the fate completely in ValidityChecks, then call
396 // ProcessUnauthenticatedHeaderFate in one place.
fayang1ed1f762019-06-24 11:40:04 -0700397 QuicPacketFate fate = ValidityChecks(*packet_info);
fayang17230ac2019-06-21 06:28:28 -0700398 ChloAlpnExtractor alpn_extractor;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500399 switch (fate) {
fayang17230ac2019-06-21 06:28:28 -0700400 case kFateProcess:
fayang1ed1f762019-06-24 11:40:04 -0700401 if (packet_info->version.handshake_protocol == PROTOCOL_TLS1_3) {
fayang17230ac2019-06-21 06:28:28 -0700402 // TODO(nharper): Support buffering non-ClientHello packets when using
403 // TLS.
fayang1ed1f762019-06-24 11:40:04 -0700404 ProcessChlo(/*alpn=*/"", packet_info);
fayang17230ac2019-06-21 06:28:28 -0700405 break;
406 }
407 if (GetQuicFlag(FLAGS_quic_allow_chlo_buffering) &&
fayang1ed1f762019-06-24 11:40:04 -0700408 !ChloExtractor::Extract(packet_info->packet, GetSupportedVersions(),
fayang17230ac2019-06-21 06:28:28 -0700409 config_->create_session_tag_indicators(),
410 &alpn_extractor,
411 server_connection_id.length())) {
412 // Buffer non-CHLO packets.
fayang1ed1f762019-06-24 11:40:04 -0700413 BufferEarlyPacket(*packet_info);
fayang17230ac2019-06-21 06:28:28 -0700414 break;
415 }
fayang1ed1f762019-06-24 11:40:04 -0700416 ProcessChlo(alpn_extractor.ConsumeAlpn(), packet_info);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500417 break;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500418 case kFateTimeWait:
wub0a4b9c52019-05-28 13:18:58 -0700419 // Add this connection_id to the time-wait state, to safely reject
420 // future packets.
421 QUIC_DLOG(INFO) << "Adding connection ID " << server_connection_id
422 << " to time-wait list.";
423 QUIC_CODE_COUNT(quic_reject_fate_time_wait);
424 StatelesslyTerminateConnection(
fayang1ed1f762019-06-24 11:40:04 -0700425 server_connection_id, packet_info->form, packet_info->version_flag,
426 packet_info->version, QUIC_HANDSHAKE_FAILED, "Reject connection",
wub0a4b9c52019-05-28 13:18:58 -0700427 quic::QuicTimeWaitListManager::SEND_STATELESS_RESET);
428
dschinazi7b9278c2019-05-20 07:36:21 -0700429 DCHECK(time_wait_list_manager_->IsConnectionIdInTimeWait(
430 server_connection_id));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500431 time_wait_list_manager_->ProcessPacket(
fayang1ed1f762019-06-24 11:40:04 -0700432 packet_info->self_address, packet_info->peer_address,
433 server_connection_id, packet_info->form, GetPerPacketContext());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500434
dschinazi7b9278c2019-05-20 07:36:21 -0700435 buffered_packets_.DiscardPackets(server_connection_id);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500436 break;
fayangd057e662019-07-10 13:29:41 -0700437 case kFateDrop:
438 break;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500439 }
440}
441
442QuicDispatcher::QuicPacketFate QuicDispatcher::ValidityChecks(
fayang1ed1f762019-06-24 11:40:04 -0700443 const ReceivedPacketInfo& packet_info) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500444 // To have all the checks work properly without tears, insert any new check
445 // into the framework of this method in the section for checks that return the
446 // check's fate value. The sections for checks must be ordered with the
447 // highest priority fate first.
448
QUICHE teama6ef0a62019-03-07 20:34:33 -0500449 // All packets within a connection sent by a client before receiving a
450 // response from the server are required to have the version negotiation flag
451 // set. Since this may be a client continuing a connection we lost track of
452 // via server restart, send a rejection to fast-fail the connection.
fayang1ed1f762019-06-24 11:40:04 -0700453 if (!packet_info.version_flag) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500454 QUIC_DLOG(INFO)
455 << "Packet without version arrived for unknown connection ID "
fayang1ed1f762019-06-24 11:40:04 -0700456 << packet_info.destination_connection_id;
fayangd057e662019-07-10 13:29:41 -0700457 if (GetQuicReloadableFlag(quic_reject_unprocessable_packets_statelessly)) {
458 QUIC_RELOADABLE_FLAG_COUNT(quic_reject_unprocessable_packets_statelessly);
459 MaybeResetPacketsWithNoVersion(packet_info);
460 return kFateDrop;
461 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500462 return kFateTimeWait;
463 }
464
fayang91475c42019-06-19 08:04:26 -0700465 // Let the connection parse and validate packet number.
QUICHE teama6ef0a62019-03-07 20:34:33 -0500466 return kFateProcess;
467}
468
469void QuicDispatcher::CleanUpSession(SessionMap::iterator it,
470 QuicConnection* connection,
dschinazi17d42422019-06-18 16:35:07 -0700471 ConnectionCloseSource /*source*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500472 write_blocked_list_.erase(connection);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500473 QuicTimeWaitListManager::TimeWaitAction action =
474 QuicTimeWaitListManager::SEND_STATELESS_RESET;
475 if (connection->termination_packets() != nullptr &&
476 !connection->termination_packets()->empty()) {
477 action = QuicTimeWaitListManager::SEND_TERMINATION_PACKETS;
fayang51c23732019-06-24 06:59:55 -0700478 } else {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500479 if (!connection->IsHandshakeConfirmed()) {
fayangd4291e42019-05-30 10:31:21 -0700480 if (!VersionHasIetfInvariantHeader(connection->transport_version())) {
fayang1de67892019-04-19 05:59:45 -0700481 QUIC_CODE_COUNT(gquic_add_to_time_wait_list_with_handshake_failed);
482 } else {
483 QUIC_CODE_COUNT(quic_v44_add_to_time_wait_list_with_handshake_failed);
484 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500485 action = QuicTimeWaitListManager::SEND_TERMINATION_PACKETS;
486 // This serializes a connection close termination packet with error code
487 // QUIC_HANDSHAKE_FAILED and adds the connection to the time wait list.
488 StatelesslyTerminateConnection(
fayang1de67892019-04-19 05:59:45 -0700489 connection->connection_id(),
fayangd4291e42019-05-30 10:31:21 -0700490 VersionHasIetfInvariantHeader(connection->transport_version())
fayang1de67892019-04-19 05:59:45 -0700491 ? IETF_QUIC_LONG_HEADER_PACKET
492 : GOOGLE_QUIC_PACKET,
493 /*version_flag=*/true, connection->version(), QUIC_HANDSHAKE_FAILED,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500494 "Connection is closed by server before handshake confirmed",
495 // Although it is our intention to send termination packets, the
496 // |action| argument is not used by this call to
497 // StatelesslyTerminateConnection().
498 action);
499 session_map_.erase(it);
500 return;
501 }
502 QUIC_CODE_COUNT(quic_v44_add_to_time_wait_list_with_stateless_reset);
503 }
504 time_wait_list_manager_->AddConnectionIdToTimeWait(
fayangd4291e42019-05-30 10:31:21 -0700505 it->first, VersionHasIetfInvariantHeader(connection->transport_version()),
506 action, connection->encryption_level(),
507 connection->termination_packets());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500508 session_map_.erase(it);
509}
510
511void QuicDispatcher::StopAcceptingNewConnections() {
512 accept_new_connections_ = false;
513}
514
515std::unique_ptr<QuicPerPacketContext> QuicDispatcher::GetPerPacketContext()
516 const {
517 return nullptr;
518}
519
520void QuicDispatcher::DeleteSessions() {
QUICHE teamaa1d6a82019-03-13 09:14:13 -0700521 if (!write_blocked_list_.empty()) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500522 for (const std::unique_ptr<QuicSession>& session : closed_session_list_) {
523 if (write_blocked_list_.erase(session->connection()) != 0) {
524 QUIC_BUG << "QuicConnection was in WriteBlockedList before destruction";
525 }
526 }
527 }
528 closed_session_list_.clear();
529}
530
531void QuicDispatcher::OnCanWrite() {
532 // The socket is now writable.
533 writer_->SetWritable();
534
535 // Move every blocked writer in |write_blocked_list_| to a temporary list.
536 const size_t num_blocked_writers_before = write_blocked_list_.size();
537 WriteBlockedList temp_list;
538 temp_list.swap(write_blocked_list_);
539 DCHECK(write_blocked_list_.empty());
540
541 // Give each blocked writer a chance to write what they indended to write.
542 // If they are blocked again, they will call |OnWriteBlocked| to add
543 // themselves back into |write_blocked_list_|.
544 while (!temp_list.empty()) {
545 QuicBlockedWriterInterface* blocked_writer = temp_list.begin()->first;
546 temp_list.erase(temp_list.begin());
547 blocked_writer->OnBlockedWriterCanWrite();
548 }
549 const size_t num_blocked_writers_after = write_blocked_list_.size();
550 if (num_blocked_writers_after != 0) {
551 if (num_blocked_writers_before == num_blocked_writers_after) {
552 QUIC_CODE_COUNT(quic_zero_progress_on_can_write);
553 } else {
554 QUIC_CODE_COUNT(quic_blocked_again_on_can_write);
555 }
556 }
557}
558
559bool QuicDispatcher::HasPendingWrites() const {
560 return !write_blocked_list_.empty();
561}
562
563void QuicDispatcher::Shutdown() {
564 while (!session_map_.empty()) {
565 QuicSession* session = session_map_.begin()->second.get();
566 session->connection()->CloseConnection(
567 QUIC_PEER_GOING_AWAY, "Server shutdown imminent",
568 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
569 // Validate that the session removes itself from the session map on close.
570 DCHECK(session_map_.empty() ||
571 session_map_.begin()->second.get() != session);
572 }
573 DeleteSessions();
574}
575
dschinazi7b9278c2019-05-20 07:36:21 -0700576void QuicDispatcher::OnConnectionClosed(QuicConnectionId server_connection_id,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500577 QuicErrorCode error,
vasilvvc48c8712019-03-11 13:38:16 -0700578 const std::string& error_details,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500579 ConnectionCloseSource source) {
dschinazi7b9278c2019-05-20 07:36:21 -0700580 auto it = session_map_.find(server_connection_id);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500581 if (it == session_map_.end()) {
dschinazi7b9278c2019-05-20 07:36:21 -0700582 QUIC_BUG << "ConnectionId " << server_connection_id
QUICHE teama6ef0a62019-03-07 20:34:33 -0500583 << " does not exist in the session map. Error: "
584 << QuicErrorCodeToString(error);
585 QUIC_BUG << QuicStackTrace();
586 return;
587 }
588
589 QUIC_DLOG_IF(INFO, error != QUIC_NO_ERROR)
dschinazi7b9278c2019-05-20 07:36:21 -0700590 << "Closing connection (" << server_connection_id
QUICHE teama6ef0a62019-03-07 20:34:33 -0500591 << ") due to error: " << QuicErrorCodeToString(error)
592 << ", with details: " << error_details;
593
594 QuicConnection* connection = it->second->connection();
595 if (ShouldDestroySessionAsynchronously()) {
596 // Set up alarm to fire immediately to bring destruction of this session
597 // out of current call stack.
598 if (closed_session_list_.empty()) {
599 delete_sessions_alarm_->Update(helper()->GetClock()->ApproximateNow(),
600 QuicTime::Delta::Zero());
601 }
602 closed_session_list_.push_back(std::move(it->second));
603 }
wub5f64ec42019-06-06 07:31:19 -0700604 CleanUpSession(it, connection, source);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500605}
606
607void QuicDispatcher::OnWriteBlocked(
608 QuicBlockedWriterInterface* blocked_writer) {
609 if (!blocked_writer->IsWriterBlocked()) {
610 // It is a programming error if this ever happens. When we are sure it is
611 // not happening, replace it with a DCHECK.
612 QUIC_BUG
613 << "Tried to add writer into blocked list when it shouldn't be added";
614 // Return without adding the connection to the blocked list, to avoid
615 // infinite loops in OnCanWrite.
616 return;
617 }
618
619 write_blocked_list_.insert(std::make_pair(blocked_writer, true));
620}
621
dschinazi17d42422019-06-18 16:35:07 -0700622void QuicDispatcher::OnRstStreamReceived(const QuicRstStreamFrame& /*frame*/) {}
QUICHE teama6ef0a62019-03-07 20:34:33 -0500623
dschinazi17d42422019-06-18 16:35:07 -0700624void QuicDispatcher::OnStopSendingReceived(
625 const QuicStopSendingFrame& /*frame*/) {}
QUICHE teama6ef0a62019-03-07 20:34:33 -0500626
627void QuicDispatcher::OnConnectionAddedToTimeWaitList(
dschinazi7b9278c2019-05-20 07:36:21 -0700628 QuicConnectionId server_connection_id) {
629 QUIC_DLOG(INFO) << "Connection " << server_connection_id
QUICHE teama6ef0a62019-03-07 20:34:33 -0500630 << " added to time wait list.";
631}
632
633void QuicDispatcher::StatelesslyTerminateConnection(
dschinazi7b9278c2019-05-20 07:36:21 -0700634 QuicConnectionId server_connection_id,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500635 PacketHeaderFormat format,
fayang1de67892019-04-19 05:59:45 -0700636 bool version_flag,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500637 ParsedQuicVersion version,
638 QuicErrorCode error_code,
vasilvvc48c8712019-03-11 13:38:16 -0700639 const std::string& error_details,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500640 QuicTimeWaitListManager::TimeWaitAction action) {
fayang51c23732019-06-24 06:59:55 -0700641 if (format != IETF_QUIC_LONG_HEADER_PACKET && !version_flag) {
dschinazi7b9278c2019-05-20 07:36:21 -0700642 QUIC_DVLOG(1) << "Statelessly terminating " << server_connection_id
QUICHE teama6ef0a62019-03-07 20:34:33 -0500643 << " based on a non-ietf-long packet, action:" << action
644 << ", error_code:" << error_code
645 << ", error_details:" << error_details;
646 time_wait_list_manager_->AddConnectionIdToTimeWait(
dschinazi7b9278c2019-05-20 07:36:21 -0700647 server_connection_id, format != GOOGLE_QUIC_PACKET, action,
648 ENCRYPTION_INITIAL, nullptr);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500649 return;
650 }
651
652 // If the version is known and supported by framer, send a connection close.
fayangccbab732019-05-13 10:11:25 -0700653 if (IsSupportedVersion(version)) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500654 QUIC_DVLOG(1)
dschinazi7b9278c2019-05-20 07:36:21 -0700655 << "Statelessly terminating " << server_connection_id
QUICHE teama6ef0a62019-03-07 20:34:33 -0500656 << " based on an ietf-long packet, which has a supported version:"
657 << version << ", error_code:" << error_code
658 << ", error_details:" << error_details;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500659
dschinazi7b9278c2019-05-20 07:36:21 -0700660 StatelessConnectionTerminator terminator(server_connection_id, version,
661 helper_.get(),
662 time_wait_list_manager_.get());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500663 // This also adds the connection to time wait list.
fayang1de67892019-04-19 05:59:45 -0700664 terminator.CloseConnection(error_code, error_details,
665 format != GOOGLE_QUIC_PACKET);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500666 return;
667 }
668
669 QUIC_DVLOG(1)
dschinazi7b9278c2019-05-20 07:36:21 -0700670 << "Statelessly terminating " << server_connection_id
QUICHE teama6ef0a62019-03-07 20:34:33 -0500671 << " based on an ietf-long packet, which has an unsupported version:"
672 << version << ", error_code:" << error_code
673 << ", error_details:" << error_details;
674 // Version is unknown or unsupported by framer, send a version negotiation
675 // with an empty version list, which can be understood by the client.
676 std::vector<std::unique_ptr<QuicEncryptedPacket>> termination_packets;
677 termination_packets.push_back(QuicFramer::BuildVersionNegotiationPacket(
dschinazib417d602019-05-29 13:08:45 -0700678 server_connection_id, EmptyQuicConnectionId(),
679 /*ietf_quic=*/format != GOOGLE_QUIC_PACKET,
dschinazi1ac22cc2019-06-25 11:47:50 -0700680 /*versions=*/{}));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500681 time_wait_list_manager()->AddConnectionIdToTimeWait(
dschinazi7b9278c2019-05-20 07:36:21 -0700682 server_connection_id, /*ietf_quic=*/format != GOOGLE_QUIC_PACKET,
QUICHE team6987b4a2019-03-15 16:23:04 -0700683 QuicTimeWaitListManager::SEND_TERMINATION_PACKETS, ENCRYPTION_INITIAL,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500684 &termination_packets);
685}
686
QUICHE teama6ef0a62019-03-07 20:34:33 -0500687bool QuicDispatcher::ShouldCreateSessionForUnknownVersion(
688 QuicVersionLabel /*version_label*/) {
689 return false;
690}
691
QUICHE teama6ef0a62019-03-07 20:34:33 -0500692void QuicDispatcher::OnExpiredPackets(
dschinazi7b9278c2019-05-20 07:36:21 -0700693 QuicConnectionId server_connection_id,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500694 BufferedPacketList early_arrived_packets) {
695 QUIC_CODE_COUNT(quic_reject_buffered_packets_expired);
696 StatelesslyTerminateConnection(
dschinazi7b9278c2019-05-20 07:36:21 -0700697 server_connection_id,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500698 early_arrived_packets.ietf_quic ? IETF_QUIC_LONG_HEADER_PACKET
699 : GOOGLE_QUIC_PACKET,
fayang1de67892019-04-19 05:59:45 -0700700 /*version_flag=*/true, early_arrived_packets.version,
701 QUIC_HANDSHAKE_FAILED, "Packets buffered for too long",
QUICHE teama6ef0a62019-03-07 20:34:33 -0500702 quic::QuicTimeWaitListManager::SEND_STATELESS_RESET);
703}
704
705void QuicDispatcher::ProcessBufferedChlos(size_t max_connections_to_create) {
706 // Reset the counter before starting creating connections.
707 new_sessions_allowed_per_event_loop_ = max_connections_to_create;
708 for (; new_sessions_allowed_per_event_loop_ > 0;
709 --new_sessions_allowed_per_event_loop_) {
dschinazi7b9278c2019-05-20 07:36:21 -0700710 QuicConnectionId server_connection_id;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500711 BufferedPacketList packet_list =
dschinazi7b9278c2019-05-20 07:36:21 -0700712 buffered_packets_.DeliverPacketsForNextConnection(
713 &server_connection_id);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500714 const std::list<BufferedPacket>& packets = packet_list.buffered_packets;
715 if (packets.empty()) {
716 return;
717 }
dschinazi7b9278c2019-05-20 07:36:21 -0700718 QuicConnectionId original_connection_id = server_connection_id;
719 server_connection_id = MaybeReplaceServerConnectionId(server_connection_id,
720 packet_list.version);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500721 QuicSession* session =
dschinazi7b9278c2019-05-20 07:36:21 -0700722 CreateQuicSession(server_connection_id, packets.front().peer_address,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500723 packet_list.alpn, packet_list.version);
dschinazi7b9278c2019-05-20 07:36:21 -0700724 if (original_connection_id != server_connection_id) {
QUICHE teamc65d1d12019-03-19 20:58:04 -0700725 session->connection()->AddIncomingConnectionId(original_connection_id);
726 }
dschinazi7b9278c2019-05-20 07:36:21 -0700727 QUIC_DLOG(INFO) << "Created new session for " << server_connection_id;
728 session_map_.insert(
729 std::make_pair(server_connection_id, QuicWrapUnique(session)));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500730 DeliverPacketsToSession(packets, session);
731 }
732}
733
734bool QuicDispatcher::HasChlosBuffered() const {
735 return buffered_packets_.HasChlosBuffered();
736}
737
738bool QuicDispatcher::ShouldCreateOrBufferPacketForConnection(
fayang1ed1f762019-06-24 11:40:04 -0700739 const ReceivedPacketInfo& packet_info) {
dschinazi7b9278c2019-05-20 07:36:21 -0700740 QUIC_VLOG(1) << "Received packet from new connection "
fayang1ed1f762019-06-24 11:40:04 -0700741 << packet_info.destination_connection_id;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500742 return true;
743}
744
745// Return true if there is any packet buffered in the store.
dschinazi7b9278c2019-05-20 07:36:21 -0700746bool QuicDispatcher::HasBufferedPackets(QuicConnectionId server_connection_id) {
747 return buffered_packets_.HasBufferedPackets(server_connection_id);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500748}
749
dschinazi7b9278c2019-05-20 07:36:21 -0700750void QuicDispatcher::OnBufferPacketFailure(
751 EnqueuePacketResult result,
752 QuicConnectionId server_connection_id) {
753 QUIC_DLOG(INFO) << "Fail to buffer packet on connection "
754 << server_connection_id << " because of " << result;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500755}
756
QUICHE teama6ef0a62019-03-07 20:34:33 -0500757QuicTimeWaitListManager* QuicDispatcher::CreateQuicTimeWaitListManager() {
758 return new QuicTimeWaitListManager(writer_.get(), this, helper_->GetClock(),
759 alarm_factory_.get());
760}
761
fayang1ed1f762019-06-24 11:40:04 -0700762void QuicDispatcher::BufferEarlyPacket(const ReceivedPacketInfo& packet_info) {
763 bool is_new_connection = !buffered_packets_.HasBufferedPackets(
764 packet_info.destination_connection_id);
765 if (is_new_connection &&
766 !ShouldCreateOrBufferPacketForConnection(packet_info)) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500767 return;
768 }
769
770 EnqueuePacketResult rs = buffered_packets_.EnqueuePacket(
fayang1ed1f762019-06-24 11:40:04 -0700771 packet_info.destination_connection_id,
772 packet_info.form != GOOGLE_QUIC_PACKET, packet_info.packet,
773 packet_info.self_address, packet_info.peer_address, /*is_chlo=*/false,
774 /*alpn=*/"", packet_info.version);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500775 if (rs != EnqueuePacketResult::SUCCESS) {
fayang1ed1f762019-06-24 11:40:04 -0700776 OnBufferPacketFailure(rs, packet_info.destination_connection_id);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500777 }
778}
779
fayang1ed1f762019-06-24 11:40:04 -0700780void QuicDispatcher::ProcessChlo(const std::string& alpn,
781 ReceivedPacketInfo* packet_info) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500782 if (!accept_new_connections_) {
783 // Don't any create new connection.
784 QUIC_CODE_COUNT(quic_reject_stop_accepting_new_connections);
785 StatelesslyTerminateConnection(
fayang1ed1f762019-06-24 11:40:04 -0700786 packet_info->destination_connection_id, packet_info->form,
787 /*version_flag=*/true, packet_info->version, QUIC_HANDSHAKE_FAILED,
788 "Stop accepting new connections",
QUICHE teama6ef0a62019-03-07 20:34:33 -0500789 quic::QuicTimeWaitListManager::SEND_STATELESS_RESET);
790 // Time wait list will reject the packet correspondingly.
791 time_wait_list_manager()->ProcessPacket(
fayang1ed1f762019-06-24 11:40:04 -0700792 packet_info->self_address, packet_info->peer_address,
793 packet_info->destination_connection_id, packet_info->form,
794 GetPerPacketContext());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500795 return;
796 }
fayang1ed1f762019-06-24 11:40:04 -0700797 if (!buffered_packets_.HasBufferedPackets(
798 packet_info->destination_connection_id) &&
799 !ShouldCreateOrBufferPacketForConnection(*packet_info)) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500800 return;
801 }
danzh88e3e052019-06-13 11:47:18 -0700802 if (GetQuicFlag(FLAGS_quic_allow_chlo_buffering) &&
QUICHE teama6ef0a62019-03-07 20:34:33 -0500803 new_sessions_allowed_per_event_loop_ <= 0) {
804 // Can't create new session any more. Wait till next event loop.
fayang1ed1f762019-06-24 11:40:04 -0700805 QUIC_BUG_IF(buffered_packets_.HasChloForConnection(
806 packet_info->destination_connection_id));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500807 EnqueuePacketResult rs = buffered_packets_.EnqueuePacket(
fayang1ed1f762019-06-24 11:40:04 -0700808 packet_info->destination_connection_id,
809 packet_info->form != GOOGLE_QUIC_PACKET, packet_info->packet,
810 packet_info->self_address, packet_info->peer_address,
811 /*is_chlo=*/true, alpn, packet_info->version);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500812 if (rs != EnqueuePacketResult::SUCCESS) {
fayang1ed1f762019-06-24 11:40:04 -0700813 OnBufferPacketFailure(rs, packet_info->destination_connection_id);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500814 }
815 return;
816 }
QUICHE teamc65d1d12019-03-19 20:58:04 -0700817
fayang1ed1f762019-06-24 11:40:04 -0700818 QuicConnectionId original_connection_id =
819 packet_info->destination_connection_id;
820 packet_info->destination_connection_id = MaybeReplaceServerConnectionId(
821 original_connection_id, packet_info->version);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500822 // Creates a new session and process all buffered packets for this connection.
dschinazi7b9278c2019-05-20 07:36:21 -0700823 QuicSession* session =
fayang1ed1f762019-06-24 11:40:04 -0700824 CreateQuicSession(packet_info->destination_connection_id,
825 packet_info->peer_address, alpn, packet_info->version);
826 if (original_connection_id != packet_info->destination_connection_id) {
QUICHE teamc65d1d12019-03-19 20:58:04 -0700827 session->connection()->AddIncomingConnectionId(original_connection_id);
828 }
dschinazi7b9278c2019-05-20 07:36:21 -0700829 QUIC_DLOG(INFO) << "Created new session for "
fayang1ed1f762019-06-24 11:40:04 -0700830 << packet_info->destination_connection_id;
831 session_map_.insert(std::make_pair(packet_info->destination_connection_id,
832 QuicWrapUnique(session)));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500833 std::list<BufferedPacket> packets =
fayang1ed1f762019-06-24 11:40:04 -0700834 buffered_packets_.DeliverPackets(packet_info->destination_connection_id)
dschinazi7b9278c2019-05-20 07:36:21 -0700835 .buffered_packets;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500836 // Process CHLO at first.
fayang1ed1f762019-06-24 11:40:04 -0700837 session->ProcessUdpPacket(packet_info->self_address,
838 packet_info->peer_address, packet_info->packet);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500839 // Deliver queued-up packets in the same order as they arrived.
840 // Do this even when flag is off because there might be still some packets
841 // buffered in the store before flag is turned off.
842 DeliverPacketsToSession(packets, session);
843 --new_sessions_allowed_per_event_loop_;
844}
845
QUICHE teama6ef0a62019-03-07 20:34:33 -0500846bool QuicDispatcher::ShouldDestroySessionAsynchronously() {
847 return true;
848}
849
850void QuicDispatcher::SetLastError(QuicErrorCode error) {
851 last_error_ = error;
852}
853
fayang91475c42019-06-19 08:04:26 -0700854bool QuicDispatcher::OnFailedToDispatchPacket(
fayang1ed1f762019-06-24 11:40:04 -0700855 const ReceivedPacketInfo& /*packet_info*/) {
fayang91475c42019-06-19 08:04:26 -0700856 return false;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500857}
858
QUICHE teama6ef0a62019-03-07 20:34:33 -0500859const QuicTransportVersionVector&
860QuicDispatcher::GetSupportedTransportVersions() {
861 return version_manager_->GetSupportedTransportVersions();
862}
863
864const ParsedQuicVersionVector& QuicDispatcher::GetSupportedVersions() {
865 return version_manager_->GetSupportedVersions();
866}
867
868void QuicDispatcher::DeliverPacketsToSession(
869 const std::list<BufferedPacket>& packets,
870 QuicSession* session) {
871 for (const BufferedPacket& packet : packets) {
872 session->ProcessUdpPacket(packet.self_address, packet.peer_address,
873 *(packet.packet));
874 }
875}
876
fayangccbab732019-05-13 10:11:25 -0700877bool QuicDispatcher::IsSupportedVersion(const ParsedQuicVersion version) {
fayangccbab732019-05-13 10:11:25 -0700878 for (const ParsedQuicVersion& supported_version :
879 version_manager_->GetSupportedVersions()) {
880 if (version == supported_version) {
881 return true;
882 }
883 }
884 return false;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500885}
886
fayangd057e662019-07-10 13:29:41 -0700887void QuicDispatcher::MaybeResetPacketsWithNoVersion(
888 const ReceivedPacketInfo& packet_info) {
889 DCHECK(!packet_info.version_flag);
890 const size_t MinValidPacketLength =
891 kPacketHeaderTypeSize + expected_server_connection_id_length_ +
892 PACKET_1BYTE_PACKET_NUMBER + /*payload size=*/1 + /*tag size=*/12;
893 if (packet_info.packet.length() < MinValidPacketLength) {
894 // The packet size is too small.
895 QUIC_CODE_COUNT(drop_too_small_packets);
896 return;
897 }
898 // TODO(fayang): Consider rate limiting reset packets if reset packet size >
899 // packet_length.
900
901 time_wait_list_manager()->SendPublicReset(
902 packet_info.self_address, packet_info.peer_address,
903 packet_info.destination_connection_id,
904 packet_info.form != GOOGLE_QUIC_PACKET, GetPerPacketContext());
905}
906
QUICHE teama6ef0a62019-03-07 20:34:33 -0500907} // namespace quic