Refactors gesture conversion functions to ui/events/blink
[chromium-blink-merge.git] / net / quic / quic_dispatcher.cc
blob663092f86163c57bde9c4261364d1e1587cbb80e
1 // Copyright 2014 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.
5 #include "net/quic/quic_dispatcher.h"
7 #include <errno.h>
9 #include "base/debug/stack_trace.h"
10 #include "base/logging.h"
11 #include "base/stl_util.h"
12 #include "net/quic/quic_blocked_writer_interface.h"
13 #include "net/quic/quic_connection_helper.h"
14 #include "net/quic/quic_flags.h"
15 #include "net/quic/quic_per_connection_packet_writer.h"
16 #include "net/quic/quic_utils.h"
18 namespace net {
20 using base::StringPiece;
21 using std::make_pair;
22 using std::find;
23 using tools::QuicServerSession;
24 using tools::QuicTimeWaitListManager;
26 class DeleteSessionsAlarm : public QuicAlarm::Delegate {
27 public:
28 explicit DeleteSessionsAlarm(QuicDispatcher* dispatcher)
29 : dispatcher_(dispatcher) {
32 QuicTime OnAlarm() override {
33 dispatcher_->DeleteSessions();
34 return QuicTime::Zero();
37 private:
38 QuicDispatcher* dispatcher_;
41 class QuicDispatcher::QuicFramerVisitor : public QuicFramerVisitorInterface {
42 public:
43 explicit QuicFramerVisitor(QuicDispatcher* dispatcher)
44 : dispatcher_(dispatcher),
45 connection_id_(0) {}
47 // QuicFramerVisitorInterface implementation
48 void OnPacket() override {}
49 bool OnUnauthenticatedPublicHeader(
50 const QuicPacketPublicHeader& header) override {
51 connection_id_ = header.connection_id;
52 return dispatcher_->OnUnauthenticatedPublicHeader(header);
54 bool OnUnauthenticatedHeader(const QuicPacketHeader& header) override {
55 dispatcher_->OnUnauthenticatedHeader(header);
56 return false;
58 void OnError(QuicFramer* framer) override {
59 DVLOG(1) << QuicUtils::ErrorToString(framer->error());
62 bool OnProtocolVersionMismatch(QuicVersion /*received_version*/) override {
63 if (dispatcher_->time_wait_list_manager()->IsConnectionIdInTimeWait(
64 connection_id_)) {
65 // Keep processing after protocol mismatch - this will be dealt with by
66 // the TimeWaitListManager.
67 return true;
68 } else {
69 DLOG(DFATAL) << "Version mismatch, connection ID (" << connection_id_
70 << ") not in time wait list.";
71 return false;
75 // The following methods should never get called because we always return
76 // false from OnUnauthenticatedHeader(). As a result, we never process the
77 // payload of the packet.
78 void OnPublicResetPacket(const QuicPublicResetPacket& /*packet*/) override {
79 DCHECK(false);
81 void OnVersionNegotiationPacket(
82 const QuicVersionNegotiationPacket& /*packet*/) override {
83 DCHECK(false);
85 void OnDecryptedPacket(EncryptionLevel level) override { DCHECK(false); }
86 bool OnPacketHeader(const QuicPacketHeader& /*header*/) override {
87 DCHECK(false);
88 return false;
90 void OnRevivedPacket() override { DCHECK(false); }
91 void OnFecProtectedPayload(StringPiece /*payload*/) override {
92 DCHECK(false);
94 bool OnStreamFrame(const QuicStreamFrame& /*frame*/) override {
95 DCHECK(false);
96 return false;
98 bool OnAckFrame(const QuicAckFrame& /*frame*/) override {
99 DCHECK(false);
100 return false;
102 bool OnStopWaitingFrame(const QuicStopWaitingFrame& /*frame*/) override {
103 DCHECK(false);
104 return false;
106 bool OnPingFrame(const QuicPingFrame& /*frame*/) override {
107 DCHECK(false);
108 return false;
110 bool OnRstStreamFrame(const QuicRstStreamFrame& /*frame*/) override {
111 DCHECK(false);
112 return false;
114 bool OnConnectionCloseFrame(
115 const QuicConnectionCloseFrame& /*frame*/) override {
116 DCHECK(false);
117 return false;
119 bool OnGoAwayFrame(const QuicGoAwayFrame& /*frame*/) override {
120 DCHECK(false);
121 return false;
123 bool OnWindowUpdateFrame(const QuicWindowUpdateFrame& /*frame*/) override {
124 DCHECK(false);
125 return false;
127 bool OnBlockedFrame(const QuicBlockedFrame& frame) override {
128 DCHECK(false);
129 return false;
131 void OnFecData(const QuicFecData& /*fec*/) override { DCHECK(false); }
132 void OnPacketComplete() override { DCHECK(false); }
134 private:
135 QuicDispatcher* dispatcher_;
137 // Latched in OnUnauthenticatedPublicHeader for use later.
138 QuicConnectionId connection_id_;
141 QuicPacketWriter* QuicDispatcher::DefaultPacketWriterFactory::Create(
142 QuicServerPacketWriter* writer,
143 QuicConnection* connection) {
144 return new QuicPerConnectionPacketWriter(writer, connection);
147 QuicDispatcher::PacketWriterFactoryAdapter::PacketWriterFactoryAdapter(
148 QuicDispatcher* dispatcher)
149 : dispatcher_(dispatcher) {}
151 QuicDispatcher::PacketWriterFactoryAdapter::~PacketWriterFactoryAdapter() {}
153 QuicPacketWriter* QuicDispatcher::PacketWriterFactoryAdapter::Create(
154 QuicConnection* connection) const {
155 return dispatcher_->packet_writer_factory_->Create(
156 dispatcher_->writer_.get(),
157 connection);
160 QuicDispatcher::QuicDispatcher(const QuicConfig& config,
161 const QuicCryptoServerConfig& crypto_config,
162 const QuicVersionVector& supported_versions,
163 PacketWriterFactory* packet_writer_factory,
164 QuicConnectionHelperInterface* helper)
165 : config_(config),
166 crypto_config_(crypto_config),
167 helper_(helper),
168 delete_sessions_alarm_(
169 helper_->CreateAlarm(new DeleteSessionsAlarm(this))),
170 packet_writer_factory_(packet_writer_factory),
171 connection_writer_factory_(this),
172 supported_versions_(supported_versions),
173 current_packet_(nullptr),
174 framer_(supported_versions,
175 /*unused*/ QuicTime::Zero(),
176 Perspective::IS_SERVER),
177 framer_visitor_(new QuicFramerVisitor(this)) {
178 framer_.set_visitor(framer_visitor_.get());
181 QuicDispatcher::~QuicDispatcher() {
182 STLDeleteValues(&session_map_);
183 STLDeleteElements(&closed_session_list_);
186 void QuicDispatcher::Initialize(QuicServerPacketWriter* writer) {
187 DCHECK(writer_ == nullptr);
188 writer_.reset(writer);
189 time_wait_list_manager_.reset(CreateQuicTimeWaitListManager());
192 void QuicDispatcher::ProcessPacket(const IPEndPoint& server_address,
193 const IPEndPoint& client_address,
194 const QuicEncryptedPacket& packet) {
195 current_server_address_ = server_address;
196 current_client_address_ = client_address;
197 current_packet_ = &packet;
198 // ProcessPacket will cause the packet to be dispatched in
199 // OnUnauthenticatedPublicHeader, or sent to the time wait list manager
200 // in OnAuthenticatedHeader.
201 framer_.ProcessPacket(packet);
202 // TODO(rjshade): Return a status describing if/why a packet was dropped,
203 // and log somehow. Maybe expose as a varz.
206 bool QuicDispatcher::OnUnauthenticatedPublicHeader(
207 const QuicPacketPublicHeader& header) {
208 // Port zero is only allowed for unidirectional UDP, so is disallowed by QUIC.
209 // Given that we can't even send a reply rejecting the packet, just black hole
210 // it.
211 if (current_client_address_.port() == 0) {
212 return false;
215 // The session that we have identified as the one to which this packet
216 // belongs.
217 QuicServerSession* session = nullptr;
218 QuicConnectionId connection_id = header.connection_id;
219 SessionMap::iterator it = session_map_.find(connection_id);
220 if (it == session_map_.end()) {
221 if (time_wait_list_manager_->IsConnectionIdInTimeWait(connection_id)) {
222 return HandlePacketForTimeWait(header);
225 // The packet has an unknown connection ID.
226 // If the packet is a public reset, there is nothing we must do or can do.
227 if (header.reset_flag) {
228 return false;
231 // All packets within a connection sent by a client before receiving a
232 // response from the server are required to have the version negotiation
233 // flag set. Since this may be a client continuing a connection we lost
234 // track of via server restart, send a rejection to fast-fail the
235 // connection.
236 if (!header.version_flag) {
237 DVLOG(1) << "Packet without version arrived for unknown connection ID "
238 << connection_id;
239 // Add this connection_id fo the time-wait state, to safely reject future
240 // packets.
241 QuicVersion version = supported_versions_.front();
242 time_wait_list_manager_->AddConnectionIdToTimeWait(connection_id, version,
243 nullptr);
244 DCHECK(time_wait_list_manager_->IsConnectionIdInTimeWait(connection_id));
245 return HandlePacketForTimeWait(header);
248 session = AdditionalValidityChecksThenCreateSession(header, connection_id);
249 if (session == nullptr) {
250 return false;
252 } else {
253 session = it->second;
256 session->connection()->ProcessUdpPacket(
257 current_server_address_, current_client_address_, *current_packet_);
259 // Do not parse the packet further. The session methods called above have
260 // processed it completely.
261 return false;
264 QuicServerSession* QuicDispatcher::AdditionalValidityChecksThenCreateSession(
265 const QuicPacketPublicHeader& header,
266 QuicConnectionId connection_id) {
267 QuicServerSession* session = CreateQuicSession(
268 connection_id, current_server_address_, current_client_address_);
270 if (session == nullptr) {
271 DVLOG(1) << "Failed to create session for " << connection_id;
273 if (!framer_.IsSupportedVersion(header.versions.front())) {
274 // TODO(ianswett): Produce packet saying "no supported version".
275 return nullptr;
278 // Add this connection_id to the time-wait state, to safely reject future
279 // packets.
280 QuicVersion version = header.versions.front();
281 time_wait_list_manager_->AddConnectionIdToTimeWait(connection_id, version,
282 nullptr);
283 DCHECK(time_wait_list_manager_->IsConnectionIdInTimeWait(connection_id));
284 HandlePacketForTimeWait(header);
286 return nullptr;
289 DVLOG(1) << "Created new session for connection ID " << connection_id;
290 session_map_.insert(std::make_pair(connection_id, session));
292 return session;
295 void QuicDispatcher::OnUnauthenticatedHeader(const QuicPacketHeader& header) {
296 DCHECK(time_wait_list_manager_->IsConnectionIdInTimeWait(
297 header.public_header.connection_id));
298 time_wait_list_manager_->ProcessPacket(current_server_address_,
299 current_client_address_,
300 header.public_header.connection_id,
301 header.packet_sequence_number,
302 *current_packet_);
305 void QuicDispatcher::CleanUpSession(SessionMap::iterator it) {
306 QuicConnection* connection = it->second->connection();
307 QuicEncryptedPacket* connection_close_packet =
308 connection->ReleaseConnectionClosePacket();
309 write_blocked_list_.erase(connection);
310 time_wait_list_manager_->AddConnectionIdToTimeWait(it->first,
311 connection->version(),
312 connection_close_packet);
313 session_map_.erase(it);
316 void QuicDispatcher::DeleteSessions() {
317 STLDeleteElements(&closed_session_list_);
320 void QuicDispatcher::OnCanWrite() {
321 // We finished a write: the socket should not be blocked.
322 writer_->SetWritable();
324 // Give all the blocked writers one chance to write, until we're blocked again
325 // or there's no work left.
326 while (!write_blocked_list_.empty() && !writer_->IsWriteBlocked()) {
327 QuicBlockedWriterInterface* blocked_writer =
328 write_blocked_list_.begin()->first;
329 write_blocked_list_.erase(write_blocked_list_.begin());
330 blocked_writer->OnCanWrite();
334 bool QuicDispatcher::HasPendingWrites() const {
335 return !write_blocked_list_.empty();
338 void QuicDispatcher::Shutdown() {
339 while (!session_map_.empty()) {
340 QuicServerSession* session = session_map_.begin()->second;
341 session->connection()->SendConnectionClose(QUIC_PEER_GOING_AWAY);
342 // Validate that the session removes itself from the session map on close.
343 DCHECK(session_map_.empty() || session_map_.begin()->second != session);
345 DeleteSessions();
348 void QuicDispatcher::OnConnectionClosed(QuicConnectionId connection_id,
349 QuicErrorCode error) {
350 SessionMap::iterator it = session_map_.find(connection_id);
351 if (it == session_map_.end()) {
352 LOG(DFATAL) << "ConnectionId " << connection_id
353 << " does not exist in the session map. "
354 << "Error: " << QuicUtils::ErrorToString(error);
355 LOG(DFATAL) << base::debug::StackTrace().ToString();
356 return;
358 DVLOG_IF(1, error != QUIC_NO_ERROR) << "Closing connection ("
359 << connection_id
360 << ") due to error: "
361 << QuicUtils::ErrorToString(error);
362 if (closed_session_list_.empty()) {
363 delete_sessions_alarm_->Set(helper_->GetClock()->ApproximateNow());
365 closed_session_list_.push_back(it->second);
366 CleanUpSession(it);
369 void QuicDispatcher::OnWriteBlocked(
370 QuicBlockedWriterInterface* blocked_writer) {
371 if (!writer_->IsWriteBlocked()) {
372 LOG(DFATAL) <<
373 "QuicDispatcher::OnWriteBlocked called when the writer is not blocked.";
374 // Return without adding the connection to the blocked list, to avoid
375 // infinite loops in OnCanWrite.
376 return;
378 write_blocked_list_.insert(std::make_pair(blocked_writer, true));
381 void QuicDispatcher::OnConnectionAddedToTimeWaitList(
382 QuicConnectionId connection_id) {
383 DVLOG(1) << "Connection " << connection_id << " added to time wait list.";
386 void QuicDispatcher::OnConnectionRemovedFromTimeWaitList(
387 QuicConnectionId connection_id) {
388 DVLOG(1) << "Connection " << connection_id << " removed from time wait list.";
391 QuicServerSession* QuicDispatcher::CreateQuicSession(
392 QuicConnectionId connection_id,
393 const IPEndPoint& server_address,
394 const IPEndPoint& client_address) {
395 // The QuicServerSession takes ownership of |connection| below.
396 QuicConnection* connection = new QuicConnection(
397 connection_id, client_address, helper_, connection_writer_factory_,
398 /* owns_writer= */ true, Perspective::IS_SERVER,
399 crypto_config_.HasProofSource(), supported_versions_);
401 QuicServerSession* session = new QuicServerSession(config_, connection, this);
402 session->InitializeSession(&crypto_config_);
403 return session;
406 QuicTimeWaitListManager* QuicDispatcher::CreateQuicTimeWaitListManager() {
407 return new QuicTimeWaitListManager(
408 writer_.get(), this, helper_, supported_versions());
411 bool QuicDispatcher::HandlePacketForTimeWait(
412 const QuicPacketPublicHeader& header) {
413 if (header.reset_flag) {
414 // Public reset packets do not have sequence numbers, so ignore the packet.
415 return false;
418 // Switch the framer to the correct version, so that the sequence number can
419 // be parsed correctly.
420 framer_.set_version(time_wait_list_manager_->GetQuicVersionFromConnectionId(
421 header.connection_id));
423 // Continue parsing the packet to extract the sequence number. Then
424 // send it to the time wait manager in OnUnathenticatedHeader.
425 return true;
428 } // namespace net