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
19namespace net {
20
21using base::StringPiece;
22using std::make_pair;
23using std::find;
24
25class 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
40class 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
158QuicPacketWriter* QuicDispatcher::DefaultPacketWriterFactory::Create(
159    QuicServerPacketWriter* writer,
160    QuicConnection* connection) {
161  return new QuicPerConnectionPacketWriter(writer, connection);
162}
163
164QuicDispatcher::PacketWriterFactoryAdapter::PacketWriterFactoryAdapter(
165    QuicDispatcher* dispatcher)
166    : dispatcher_(dispatcher) {}
167
168QuicDispatcher::PacketWriterFactoryAdapter::~PacketWriterFactoryAdapter() {}
169
170QuicPacketWriter* QuicDispatcher::PacketWriterFactoryAdapter::Create(
171    QuicConnection* connection) const {
172  return dispatcher_->packet_writer_factory_->Create(
173      dispatcher_->writer_.get(),
174      connection);
175}
176
177QuicDispatcher::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
196QuicDispatcher::~QuicDispatcher() {
197  STLDeleteValues(&session_map_);
198  STLDeleteElements(&closed_session_list_);
199}
200
201void QuicDispatcher::Initialize(QuicServerPacketWriter* writer) {
202  DCHECK(writer_ == NULL);
203  writer_.reset(writer);
204  time_wait_list_manager_.reset(CreateQuicTimeWaitListManager());
205}
206
207void 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
221bool 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
275void 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
285void 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
296void QuicDispatcher::DeleteSessions() {
297  STLDeleteElements(&closed_session_list_);
298}
299
300void 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
314bool QuicDispatcher::HasPendingWrites() const {
315  return !write_blocked_list_.empty();
316}
317
318void 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
328void 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
349void 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
361QuicSession* 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
373QuicConnection* 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
386QuicTimeWaitListManager* QuicDispatcher::CreateQuicTimeWaitListManager() {
387  return new QuicTimeWaitListManager(
388      writer_.get(), this, helper_, supported_versions());
389}
390
391bool 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
409