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