1f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
2f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// found in the LICENSE file.
4f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
5f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "net/quic/quic_time_wait_list_manager.h"
6f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
7f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <errno.h>
8f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
9f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "base/containers/hash_tables.h"
10f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
11f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "base/stl_util.h"
12f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "net/base/ip_endpoint.h"
13f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "net/quic/crypto/crypto_protocol.h"
14f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "net/quic/crypto/quic_decrypter.h"
15f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "net/quic/crypto/quic_encrypter.h"
16f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "net/quic/quic_clock.h"
17f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "net/quic/quic_connection_helper.h"
18f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "net/quic/quic_framer.h"
19f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "net/quic/quic_protocol.h"
20f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "net/quic/quic_server_session.h"
21f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "net/quic/quic_utils.h"
22f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
23f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)using base::StringPiece;
24f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)using std::make_pair;
25f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
26f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)namespace net {
27f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
28f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)namespace {
29f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
30f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Time period for which the connection_id should live in time wait state..
31f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)const int kTimeWaitSeconds = 5;
32f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
33f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}  // namespace
34f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
35f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// A very simple alarm that just informs the QuicTimeWaitListManager to clean
36f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// up old connection_ids. This alarm should be unregistered and deleted before
37f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// the QuicTimeWaitListManager is deleted.
38f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)class ConnectionIdCleanUpAlarm : public QuicAlarm::Delegate {
39f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) public:
40f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  explicit ConnectionIdCleanUpAlarm(
41f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      QuicTimeWaitListManager* time_wait_list_manager)
42f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      : time_wait_list_manager_(time_wait_list_manager) {}
43f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
44f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  virtual QuicTime OnAlarm() OVERRIDE {
45f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    time_wait_list_manager_->CleanUpOldConnectionIds();
46f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // Let the time wait manager register the alarm at appropriate time.
47f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return QuicTime::Zero();
48f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
49f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
50f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) private:
51f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Not owned.
52f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  QuicTimeWaitListManager* time_wait_list_manager_;
53f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)};
54f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
55f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// This class stores pending public reset packets to be sent to clients.
56f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// server_address - server address on which a packet what was received for
57f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)//                  a connection_id in time wait state.
58f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// client_address - address of the client that sent that packet. Needed to send
59f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)//                  the public reset packet back to the client.
60f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// packet - the pending public reset packet that is to be sent to the client.
61f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)//          created instance takes the ownership of this packet.
62f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)class QuicTimeWaitListManager::QueuedPacket {
63f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) public:
64f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  QueuedPacket(const IPEndPoint& server_address,
65f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)               const IPEndPoint& client_address,
66f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)               QuicEncryptedPacket* packet)
67f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      : server_address_(server_address),
68f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        client_address_(client_address),
69f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        packet_(packet) {}
70f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
71f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  const IPEndPoint& server_address() const { return server_address_; }
72f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  const IPEndPoint& client_address() const { return client_address_; }
73f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  QuicEncryptedPacket* packet() { return packet_.get(); }
74f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
75f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) private:
76f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  const IPEndPoint server_address_;
77f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  const IPEndPoint client_address_;
78f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  scoped_ptr<QuicEncryptedPacket> packet_;
79f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
80f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(QueuedPacket);
81f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)};
82f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
83f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)QuicTimeWaitListManager::QuicTimeWaitListManager(
84f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    QuicPacketWriter* writer,
85f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    QuicServerSessionVisitor* visitor,
86f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    QuicConnectionHelperInterface* helper,
87f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const QuicVersionVector& supported_versions)
88f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    : helper_(helper),
89f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      kTimeWaitPeriod_(QuicTime::Delta::FromSeconds(kTimeWaitSeconds)),
90f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      connection_id_clean_up_alarm_(
91f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          helper_->CreateAlarm(new ConnectionIdCleanUpAlarm(this))),
92f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      writer_(writer),
93f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      visitor_(visitor) {
94f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  SetConnectionIdCleanUpAlarm();
95f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
96f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
97f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)QuicTimeWaitListManager::~QuicTimeWaitListManager() {
98f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  connection_id_clean_up_alarm_->Cancel();
99f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  STLDeleteElements(&pending_packets_queue_);
100f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  for (ConnectionIdMap::iterator it = connection_id_map_.begin();
101f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)       it != connection_id_map_.end();
102f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)       ++it) {
103f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    delete it->second.close_packet;
104f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
105f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
106f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
107f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void QuicTimeWaitListManager::AddConnectionIdToTimeWait(
108f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    QuicConnectionId connection_id,
109f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    QuicVersion version,
110f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    QuicEncryptedPacket* close_packet) {
111f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DVLOG(1) << "Adding " << connection_id << " to the time wait list.";
112f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  int num_packets = 0;
113f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  ConnectionIdMap::iterator it = connection_id_map_.find(connection_id);
114f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (it != connection_id_map_.end()) {  // Replace record if it is reinserted.
115f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    num_packets = it->second.num_packets;
116f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    delete it->second.close_packet;
117f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    connection_id_map_.erase(it);
118f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
119f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  ConnectionIdData data(num_packets,
120f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                        version,
121f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                        helper_->GetClock()->ApproximateNow(),
122f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                        close_packet);
123f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  connection_id_map_.insert(make_pair(connection_id, data));
124f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
125f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
126f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool QuicTimeWaitListManager::IsConnectionIdInTimeWait(
127f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    QuicConnectionId connection_id) const {
128f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return ContainsKey(connection_id_map_, connection_id);
129f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
130f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
131f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)QuicVersion QuicTimeWaitListManager::GetQuicVersionFromConnectionId(
132f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    QuicConnectionId connection_id) {
133f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  ConnectionIdMap::iterator it = connection_id_map_.find(connection_id);
134f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DCHECK(it != connection_id_map_.end());
135f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return (it->second).version;
136f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
137f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
138f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void QuicTimeWaitListManager::OnCanWrite() {
139f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  while (!pending_packets_queue_.empty()) {
140f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    QueuedPacket* queued_packet = pending_packets_queue_.front();
141f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (!WriteToWire(queued_packet)) {
142f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      return;
143f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
144f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    pending_packets_queue_.pop_front();
145f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    delete queued_packet;
146f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
147f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
148f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
149f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void QuicTimeWaitListManager::ProcessPacket(
150f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const IPEndPoint& server_address,
151f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const IPEndPoint& client_address,
152f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    QuicConnectionId connection_id,
153f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    QuicPacketSequenceNumber sequence_number,
154f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const QuicEncryptedPacket& /*packet*/) {
155f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DCHECK(IsConnectionIdInTimeWait(connection_id));
156f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DVLOG(1) << "Processing " << connection_id << " in time wait state.";
157f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // TODO(satyamshekhar): Think about handling packets from different client
158f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // addresses.
159f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  ConnectionIdMap::iterator it = connection_id_map_.find(connection_id);
160f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DCHECK(it != connection_id_map_.end());
161f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Increment the received packet count.
162f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  ++((it->second).num_packets);
163f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!ShouldSendResponse((it->second).num_packets)) {
164f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return;
165f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
166f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (it->second.close_packet) {
167f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    QueuedPacket* queued_packet =
168f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        new QueuedPacket(server_address,
169f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                         client_address,
170f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                         it->second.close_packet->Clone());
171f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // Takes ownership of the packet.
172f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    SendOrQueuePacket(queued_packet);
173f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  } else {
174f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    SendPublicReset(server_address,
175f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                    client_address,
176f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                    connection_id,
177f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                    sequence_number);
178f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
179f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
180f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
181f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Returns true if the number of packets received for this connection_id is a
182f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// power of 2 to throttle the number of public reset packets we send to a
183f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// client.
184f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool QuicTimeWaitListManager::ShouldSendResponse(int received_packet_count) {
185f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return (received_packet_count & (received_packet_count - 1)) == 0;
186f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
187f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
188f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void QuicTimeWaitListManager::SendPublicReset(
189f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const IPEndPoint& server_address,
190f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const IPEndPoint& client_address,
191f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    QuicConnectionId connection_id,
192f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    QuicPacketSequenceNumber rejected_sequence_number) {
193f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  QuicPublicResetPacket packet;
194f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  packet.public_header.connection_id = connection_id;
195f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  packet.public_header.reset_flag = true;
196f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  packet.public_header.version_flag = false;
197f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  packet.rejected_sequence_number = rejected_sequence_number;
198f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // TODO(satyamshekhar): generate a valid nonce for this connection_id.
199f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  packet.nonce_proof = 1010101;
200f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  packet.client_address = client_address;
201f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  QueuedPacket* queued_packet = new QueuedPacket(
202f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      server_address,
203f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      client_address,
204f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      BuildPublicReset(packet));
205f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Takes ownership of the packet.
206f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  SendOrQueuePacket(queued_packet);
207f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
208f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
209f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)QuicEncryptedPacket* QuicTimeWaitListManager::BuildPublicReset(
210f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const QuicPublicResetPacket& packet) {
211f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return QuicFramer::BuildPublicResetPacket(packet);
212f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
213f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
214f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Either sends the packet and deletes it or makes pending queue the
215f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// owner of the packet.
216f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void QuicTimeWaitListManager::SendOrQueuePacket(QueuedPacket* packet) {
217f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (WriteToWire(packet)) {
218f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    delete packet;
219f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  } else {
220f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // pending_packets_queue takes the ownership of the queued packet.
221f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    pending_packets_queue_.push_back(packet);
222f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
223f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
224f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
225f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool QuicTimeWaitListManager::WriteToWire(QueuedPacket* queued_packet) {
226f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (writer_->IsWriteBlocked()) {
227f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    visitor_->OnWriteBlocked(this);
228f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return false;
229f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
230f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  WriteResult result = writer_->WritePacket(
231f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      queued_packet->packet()->data(),
232f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      queued_packet->packet()->length(),
233f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      queued_packet->server_address().address(),
234f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      queued_packet->client_address());
235f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (result.status == WRITE_STATUS_BLOCKED) {
236f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // If blocked and unbuffered, return false to retry sending.
237f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    DCHECK(writer_->IsWriteBlocked());
238f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    visitor_->OnWriteBlocked(this);
239f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return writer_->IsWriteBlockedDataBuffered();
240f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  } else if (result.status == WRITE_STATUS_ERROR) {
241f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    LOG(WARNING) << "Received unknown error while sending reset packet to "
242f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                 << queued_packet->client_address().ToString() << ": "
243f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                 << strerror(result.error_code);
244f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
245f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return true;
246f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
247f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
248f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void QuicTimeWaitListManager::SetConnectionIdCleanUpAlarm() {
249f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  connection_id_clean_up_alarm_->Cancel();
250f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  QuicTime now = helper_->GetClock()->ApproximateNow();
251f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  QuicTime next_alarm_time = now;
252f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!connection_id_map_.empty()) {
253f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    QuicTime oldest_connection_id =
254f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        connection_id_map_.begin()->second.time_added;
255f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (now.Subtract(oldest_connection_id) < kTimeWaitPeriod_) {
256f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      next_alarm_time = oldest_connection_id.Add(kTimeWaitPeriod_);
257f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    } else {
258f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      LOG(ERROR) << "ConnectionId lingered for longer than kTimeWaitPeriod";
259f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
260f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  } else {
261f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // No connection_ids added so none will expire before kTimeWaitPeriod_.
262f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    next_alarm_time = now.Add(kTimeWaitPeriod_);
263f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
264f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
265f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  connection_id_clean_up_alarm_->Set(next_alarm_time);
266f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
267f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
268f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void QuicTimeWaitListManager::CleanUpOldConnectionIds() {
269f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  QuicTime now = helper_->GetClock()->ApproximateNow();
270f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  while (!connection_id_map_.empty()) {
271f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    ConnectionIdMap::iterator it = connection_id_map_.begin();
272f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    QuicTime oldest_connection_id = it->second.time_added;
273f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (now.Subtract(oldest_connection_id) < kTimeWaitPeriod_) {
274f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      break;
275f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
276f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // This connection_id has lived its age, retire it now.
277f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    delete it->second.close_packet;
278f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    connection_id_map_.erase(it);
279f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
280f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  SetConnectionIdCleanUpAlarm();
281f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
282f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
283f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}  // namespace net
284