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