Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / net / quic / quic_dispatcher.cc
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.
4
5 #include "net/quic/quic_dispatcher.h"
6
7 #include <errno.h>
8
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_time_wait_list_manager.h"
17 #include "net/quic/quic_utils.h"
18
19 namespace net {
20
21 using base::StringPiece;
22 using std::make_pair;
23 using std::find;
24
25 class DeleteSessionsAlarm : public QuicAlarm::Delegate {
26  public:
27   explicit DeleteSessionsAlarm(QuicDispatcher* dispatcher)
28       : dispatcher_(dispatcher) {
29   }
30
31   QuicTime OnAlarm() override {
32     dispatcher_->DeleteSessions();
33     return QuicTime::Zero();
34   }
35
36  private:
37   QuicDispatcher* dispatcher_;
38 };
39
40 class QuicDispatcher::QuicFramerVisitor : public QuicFramerVisitorInterface {
41  public:
42   explicit QuicFramerVisitor(QuicDispatcher* dispatcher)
43       : dispatcher_(dispatcher),
44         connection_id_(0) {}
45
46   // QuicFramerVisitorInterface implementation
47   void OnPacket() override {}
48   bool OnUnauthenticatedPublicHeader(
49       const QuicPacketPublicHeader& header) override {
50     connection_id_ = header.connection_id;
51     return dispatcher_->OnUnauthenticatedPublicHeader(header);
52   }
53   bool OnUnauthenticatedHeader(const QuicPacketHeader& header) override {
54     dispatcher_->OnUnauthenticatedHeader(header);
55     return false;
56   }
57   void OnError(QuicFramer* framer) override {
58     DVLOG(1) << QuicUtils::ErrorToString(framer->error());
59   }
60
61   bool OnProtocolVersionMismatch(QuicVersion /*received_version*/) override {
62     if (dispatcher_->time_wait_list_manager()->IsConnectionIdInTimeWait(
63             connection_id_)) {
64       // Keep processing after protocol mismatch - this will be dealt with by
65       // the TimeWaitListManager.
66       return true;
67     } else {
68       DLOG(DFATAL) << "Version mismatch, connection ID (" << connection_id_
69                    << ") not in time wait list.";
70       return false;
71     }
72   }
73
74   // The following methods should never get called because we always return
75   // false from OnUnauthenticatedHeader().  As a result, we never process the
76   // payload of the packet.
77   void OnPublicResetPacket(const QuicPublicResetPacket& /*packet*/) override {
78     DCHECK(false);
79   }
80   void OnVersionNegotiationPacket(
81       const QuicVersionNegotiationPacket& /*packet*/) override {
82     DCHECK(false);
83   }
84   void OnDecryptedPacket(EncryptionLevel level) override { DCHECK(false); }
85   bool OnPacketHeader(const QuicPacketHeader& /*header*/) override {
86     DCHECK(false);
87     return false;
88   }
89   void OnRevivedPacket() override { DCHECK(false); }
90   void OnFecProtectedPayload(StringPiece /*payload*/) override {
91     DCHECK(false);
92   }
93   bool OnStreamFrame(const QuicStreamFrame& /*frame*/) override {
94     DCHECK(false);
95     return false;
96   }
97   bool OnAckFrame(const QuicAckFrame& /*frame*/) override {
98     DCHECK(false);
99     return false;
100   }
101   bool OnCongestionFeedbackFrame(
102       const QuicCongestionFeedbackFrame& /*frame*/) override {
103     DCHECK(false);
104     return false;
105   }
106   bool OnStopWaitingFrame(const QuicStopWaitingFrame& /*frame*/) override {
107     DCHECK(false);
108     return false;
109   }
110   bool OnPingFrame(const QuicPingFrame& /*frame*/) override {
111     DCHECK(false);
112     return false;
113   }
114   bool OnRstStreamFrame(const QuicRstStreamFrame& /*frame*/) override {
115     DCHECK(false);
116     return false;
117   }
118   bool OnConnectionCloseFrame(
119       const QuicConnectionCloseFrame& /*frame*/) override {
120     DCHECK(false);
121     return false;
122   }
123   bool OnGoAwayFrame(const QuicGoAwayFrame& /*frame*/) override {
124     DCHECK(false);
125     return false;
126   }
127   bool OnWindowUpdateFrame(const QuicWindowUpdateFrame& /*frame*/) override {
128     DCHECK(false);
129     return false;
130   }
131   bool OnBlockedFrame(const QuicBlockedFrame& frame) override {
132     DCHECK(false);
133     return false;
134   }
135   void OnFecData(const QuicFecData& /*fec*/) override { DCHECK(false); }
136   void OnPacketComplete() override { DCHECK(false); }
137
138  private:
139   QuicDispatcher* dispatcher_;
140
141   // Latched in OnUnauthenticatedPublicHeader for use later.
142   QuicConnectionId connection_id_;
143 };
144
145 QuicPacketWriter* QuicDispatcher::DefaultPacketWriterFactory::Create(
146     QuicServerPacketWriter* writer,
147     QuicConnection* connection) {
148   return new QuicPerConnectionPacketWriter(writer, connection);
149 }
150
151 QuicDispatcher::PacketWriterFactoryAdapter::PacketWriterFactoryAdapter(
152     QuicDispatcher* dispatcher)
153     : dispatcher_(dispatcher) {}
154
155 QuicDispatcher::PacketWriterFactoryAdapter::~PacketWriterFactoryAdapter() {}
156
157 QuicPacketWriter* QuicDispatcher::PacketWriterFactoryAdapter::Create(
158     QuicConnection* connection) const {
159   return dispatcher_->packet_writer_factory_->Create(
160       dispatcher_->writer_.get(),
161       connection);
162 }
163
164 QuicDispatcher::QuicDispatcher(const QuicConfig& config,
165                                const QuicCryptoServerConfig& crypto_config,
166                                const QuicVersionVector& supported_versions,
167                                PacketWriterFactory* packet_writer_factory,
168                                QuicConnectionHelperInterface* helper)
169     : config_(config),
170       crypto_config_(crypto_config),
171       helper_(helper),
172       delete_sessions_alarm_(
173           helper_->CreateAlarm(new DeleteSessionsAlarm(this))),
174       packet_writer_factory_(packet_writer_factory),
175       connection_writer_factory_(this),
176       supported_versions_(supported_versions),
177       current_packet_(nullptr),
178       framer_(supported_versions, /*unused*/ QuicTime::Zero(), true),
179       framer_visitor_(new QuicFramerVisitor(this)) {
180   framer_.set_visitor(framer_visitor_.get());
181 }
182
183 QuicDispatcher::~QuicDispatcher() {
184   STLDeleteValues(&session_map_);
185   STLDeleteElements(&closed_session_list_);
186 }
187
188 void QuicDispatcher::Initialize(QuicServerPacketWriter* writer) {
189   DCHECK(writer_ == nullptr);
190   writer_.reset(writer);
191   time_wait_list_manager_.reset(CreateQuicTimeWaitListManager());
192 }
193
194 void QuicDispatcher::ProcessPacket(const IPEndPoint& server_address,
195                                    const IPEndPoint& client_address,
196                                    const QuicEncryptedPacket& packet) {
197   current_server_address_ = server_address;
198   current_client_address_ = client_address;
199   current_packet_ = &packet;
200   // ProcessPacket will cause the packet to be dispatched in
201   // OnUnauthenticatedPublicHeader, or sent to the time wait list manager
202   // in OnAuthenticatedHeader.
203   framer_.ProcessPacket(packet);
204   // TODO(rjshade): Return a status describing if/why a packet was dropped,
205   //                and log somehow.  Maybe expose as a varz.
206 }
207
208 bool QuicDispatcher::OnUnauthenticatedPublicHeader(
209     const QuicPacketPublicHeader& header) {
210   QuicSession* session = nullptr;
211
212   QuicConnectionId connection_id = header.connection_id;
213   SessionMap::iterator it = session_map_.find(connection_id);
214   if (it == session_map_.end()) {
215     if (header.reset_flag) {
216       return false;
217     }
218     if (time_wait_list_manager_->IsConnectionIdInTimeWait(connection_id)) {
219       return HandlePacketForTimeWait(header);
220     }
221
222     // Ensure the packet has a version negotiation bit set before creating a new
223     // session for it.  All initial packets for a new connection are required to
224     // have the flag set.  Otherwise it may be a stray packet.
225     if (header.version_flag) {
226       session = CreateQuicSession(connection_id, current_server_address_,
227                                   current_client_address_);
228     }
229
230     if (session == nullptr) {
231       DVLOG(1) << "Failed to create session for " << connection_id;
232       // Add this connection_id fo the time-wait state, to safely reject future
233       // packets.
234
235       if (header.version_flag &&
236           !framer_.IsSupportedVersion(header.versions.front())) {
237         // TODO(ianswett): Produce a no-version version negotiation packet.
238         return false;
239       }
240
241       // Use the version in the packet if possible, otherwise assume the latest.
242       QuicVersion version = header.version_flag ? header.versions.front() :
243           supported_versions_.front();
244       time_wait_list_manager_->AddConnectionIdToTimeWait(connection_id, version,
245                                                          nullptr);
246       DCHECK(time_wait_list_manager_->IsConnectionIdInTimeWait(connection_id));
247       return HandlePacketForTimeWait(header);
248     }
249     DVLOG(1) << "Created new session for " << connection_id;
250     session_map_.insert(make_pair(connection_id, session));
251   } else {
252     session = it->second;
253   }
254
255   session->connection()->ProcessUdpPacket(
256       current_server_address_, current_client_address_, *current_packet_);
257
258   // Do not parse the packet further.  The session will process it completely.
259   return false;
260 }
261
262 void QuicDispatcher::OnUnauthenticatedHeader(const QuicPacketHeader& header) {
263   DCHECK(time_wait_list_manager_->IsConnectionIdInTimeWait(
264       header.public_header.connection_id));
265   time_wait_list_manager_->ProcessPacket(current_server_address_,
266                                          current_client_address_,
267                                          header.public_header.connection_id,
268                                          header.packet_sequence_number,
269                                          *current_packet_);
270 }
271
272 void QuicDispatcher::CleanUpSession(SessionMap::iterator it) {
273   QuicConnection* connection = it->second->connection();
274   QuicEncryptedPacket* connection_close_packet =
275       connection->ReleaseConnectionClosePacket();
276   write_blocked_list_.erase(connection);
277   time_wait_list_manager_->AddConnectionIdToTimeWait(it->first,
278                                                      connection->version(),
279                                                      connection_close_packet);
280   session_map_.erase(it);
281 }
282
283 void QuicDispatcher::DeleteSessions() {
284   STLDeleteElements(&closed_session_list_);
285 }
286
287 void QuicDispatcher::OnCanWrite() {
288   // We finished a write: the socket should not be blocked.
289   writer_->SetWritable();
290
291   // Give all the blocked writers one chance to write, until we're blocked again
292   // or there's no work left.
293   while (!write_blocked_list_.empty() && !writer_->IsWriteBlocked()) {
294     QuicBlockedWriterInterface* blocked_writer =
295         write_blocked_list_.begin()->first;
296     write_blocked_list_.erase(write_blocked_list_.begin());
297     blocked_writer->OnCanWrite();
298   }
299 }
300
301 bool QuicDispatcher::HasPendingWrites() const {
302   return !write_blocked_list_.empty();
303 }
304
305 void QuicDispatcher::Shutdown() {
306   while (!session_map_.empty()) {
307     QuicSession* session = session_map_.begin()->second;
308     session->connection()->SendConnectionClose(QUIC_PEER_GOING_AWAY);
309     // Validate that the session removes itself from the session map on close.
310     DCHECK(session_map_.empty() || session_map_.begin()->second != session);
311   }
312   DeleteSessions();
313 }
314
315 void QuicDispatcher::OnConnectionClosed(QuicConnectionId connection_id,
316                                         QuicErrorCode error) {
317   SessionMap::iterator it = session_map_.find(connection_id);
318   if (it == session_map_.end()) {
319     LOG(DFATAL) << "ConnectionId " << connection_id
320                 << " does not exist in the session map.  "
321                 << "Error: " << QuicUtils::ErrorToString(error);
322     LOG(DFATAL) << base::debug::StackTrace().ToString();
323     return;
324   }
325   DVLOG_IF(1, error != QUIC_NO_ERROR) << "Closing connection ("
326                                       << connection_id
327                                       << ") due to error: "
328                                       << QuicUtils::ErrorToString(error);
329   if (closed_session_list_.empty()) {
330     delete_sessions_alarm_->Set(helper_->GetClock()->ApproximateNow());
331   }
332   closed_session_list_.push_back(it->second);
333   CleanUpSession(it);
334 }
335
336 void QuicDispatcher::OnWriteBlocked(
337     QuicBlockedWriterInterface* blocked_writer) {
338   if (!writer_->IsWriteBlocked()) {
339     LOG(DFATAL) <<
340         "QuicDispatcher::OnWriteBlocked called when the writer is not blocked.";
341     // Return without adding the connection to the blocked list, to avoid
342     // infinite loops in OnCanWrite.
343     return;
344   }
345   write_blocked_list_.insert(make_pair(blocked_writer, true));
346 }
347
348 QuicSession* QuicDispatcher::CreateQuicSession(
349     QuicConnectionId connection_id,
350     const IPEndPoint& server_address,
351     const IPEndPoint& client_address) {
352   QuicServerSession* session = new QuicServerSession(
353       config_,
354       CreateQuicConnection(connection_id, server_address, client_address),
355       this,
356       crypto_config_.HasProofSource());
357   session->InitializeSession(crypto_config_);
358   return session;
359 }
360
361 QuicConnection* QuicDispatcher::CreateQuicConnection(
362     QuicConnectionId connection_id,
363     const IPEndPoint& server_address,
364     const IPEndPoint& client_address) {
365   return new QuicConnection(connection_id,
366                             client_address,
367                             helper_,
368                             connection_writer_factory_,
369                             /* owns_writer= */ true,
370                             /* is_server= */ true,
371                             supported_versions_);
372 }
373
374 QuicTimeWaitListManager* QuicDispatcher::CreateQuicTimeWaitListManager() {
375   return new QuicTimeWaitListManager(
376       writer_.get(), this, helper_, supported_versions());
377 }
378
379 bool QuicDispatcher::HandlePacketForTimeWait(
380     const QuicPacketPublicHeader& header) {
381   if (header.reset_flag) {
382     // Public reset packets do not have sequence numbers, so ignore the packet.
383     return false;
384   }
385
386   // Switch the framer to the correct version, so that the sequence number can
387   // be parsed correctly.
388   framer_.set_version(time_wait_list_manager_->GetQuicVersionFromConnectionId(
389       header.connection_id));
390
391   // Continue parsing the packet to extract the sequence number.  Then
392   // send it to the time wait manager in OnUnathenticatedHeader.
393   return true;
394 }
395
396 }  // namespace net