1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file.
4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/tools/quic/quic_time_wait_list_manager.h"
6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <errno.h>
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
97d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/containers/hash_tables.h"
10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/memory/scoped_ptr.h"
11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/stl_util.h"
12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/base/ip_endpoint.h"
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/quic/crypto/crypto_protocol.h"
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/quic/crypto/quic_decrypter.h"
15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/quic/crypto/quic_encrypter.h"
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/quic/quic_clock.h"
17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/quic/quic_framer.h"
18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/quic/quic_protocol.h"
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/quic/quic_utils.h"
20f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "net/tools/epoll_server/epoll_server.h"
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/tools/quic/quic_server_session.h"
22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
23f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using base::StringPiece;
24558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochusing std::make_pair;
25558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace net {
27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace tools {
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace {
30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
31a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Time period for which the connection_id should live in time wait state..
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const int kTimeWaitSeconds = 5;
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// A very simple alarm that just informs the QuicTimeWaitListManager to clean
37a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// up old connection_ids. This alarm should be unregistered and deleted before
38a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// the QuicTimeWaitListManager is deleted.
39a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)class ConnectionIdCleanUpAlarm : public EpollAlarm {
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
41a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  explicit ConnectionIdCleanUpAlarm(
42a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      QuicTimeWaitListManager* time_wait_list_manager)
43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      : time_wait_list_manager_(time_wait_list_manager) {
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual int64 OnAlarm() OVERRIDE {
47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    EpollAlarm::OnAlarm();
48a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    time_wait_list_manager_->CleanUpOldConnectionIds();
49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Let the time wait manager register the alarm at appropriate time.
50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return 0;
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private:
54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Not owned.
55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  QuicTimeWaitListManager* time_wait_list_manager_;
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// This class stores pending public reset packets to be sent to clients.
59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// server_address - server address on which a packet what was received for
60a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)//                  a connection_id in time wait state.
61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// client_address - address of the client that sent that packet. Needed to send
62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//                  the public reset packet back to the client.
63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// packet - the pending public reset packet that is to be sent to the client.
64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//          created instance takes the ownership of this packet.
65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class QuicTimeWaitListManager::QueuedPacket {
66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  QueuedPacket(const IPEndPoint& server_address,
68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)               const IPEndPoint& client_address,
69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)               QuicEncryptedPacket* packet)
70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      : server_address_(server_address),
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        client_address_(client_address),
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        packet_(packet) {
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const IPEndPoint& server_address() const { return server_address_; }
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const IPEndPoint& client_address() const { return client_address_; }
77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  QuicEncryptedPacket* packet() { return packet_.get(); }
78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private:
80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const IPEndPoint server_address_;
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const IPEndPoint client_address_;
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<QuicEncryptedPacket> packet_;
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(QueuedPacket);
85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)QuicTimeWaitListManager::QuicTimeWaitListManager(
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    QuicPacketWriter* writer,
895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    QuicServerSessionVisitor* visitor,
901e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    EpollServer* epoll_server,
911e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const QuicVersionVector& supported_versions)
925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : epoll_server_(epoll_server),
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      kTimeWaitPeriod_(QuicTime::Delta::FromSeconds(kTimeWaitSeconds)),
94a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      connection_id_clean_up_alarm_(new ConnectionIdCleanUpAlarm(this)),
955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      clock_(epoll_server_),
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      writer_(writer),
975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      visitor_(visitor) {
98a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  SetConnectionIdCleanUpAlarm();
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)QuicTimeWaitListManager::~QuicTimeWaitListManager() {
102a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  connection_id_clean_up_alarm_->UnregisterIfRegistered();
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  STLDeleteElements(&pending_packets_queue_);
104a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  for (ConnectionIdMap::iterator it = connection_id_map_.begin();
105a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)       it != connection_id_map_.end();
106a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)       ++it) {
107f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    delete it->second.close_packet;
108f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
111a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void QuicTimeWaitListManager::AddConnectionIdToTimeWait(
112a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    QuicConnectionId connection_id,
113f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    QuicVersion version,
114f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    QuicEncryptedPacket* close_packet) {
1150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  DVLOG(1) << "Adding " << connection_id << " to the time wait list.";
1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int num_packets = 0;
117a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ConnectionIdMap::iterator it = connection_id_map_.find(connection_id);
118a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (it != connection_id_map_.end()) {  // Replace record if it is reinserted.
1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    num_packets = it->second.num_packets;
1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    delete it->second.close_packet;
121a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    connection_id_map_.erase(it);
1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
123a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ConnectionIdData data(num_packets, version, clock_.ApproximateNow(),
124a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                        close_packet);
125a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  connection_id_map_.insert(make_pair(connection_id, data));
126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
128a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool QuicTimeWaitListManager::IsConnectionIdInTimeWait(
129a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    QuicConnectionId connection_id) const {
130a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return ContainsKey(connection_id_map_, connection_id);
131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
133a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)QuicVersion QuicTimeWaitListManager::GetQuicVersionFromConnectionId(
134a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    QuicConnectionId connection_id) {
135a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ConnectionIdMap::iterator it = connection_id_map_.find(connection_id);
136a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK(it != connection_id_map_.end());
137558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  return (it->second).version;
138558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch}
139558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
140a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void QuicTimeWaitListManager::OnCanWrite() {
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  while (!pending_packets_queue_.empty()) {
142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    QueuedPacket* queued_packet = pending_packets_queue_.front();
143a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (!WriteToWire(queued_packet)) {
144a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return;
145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
146a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    pending_packets_queue_.pop_front();
147a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    delete queued_packet;
148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void QuicTimeWaitListManager::ProcessPacket(
1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const IPEndPoint& server_address,
1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const IPEndPoint& client_address,
154a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    QuicConnectionId connection_id,
1550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    QuicPacketSequenceNumber sequence_number,
1560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    const QuicEncryptedPacket& /*packet*/) {
157a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK(IsConnectionIdInTimeWait(connection_id));
1580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  DVLOG(1) << "Processing " << connection_id << " in time wait state.";
159f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // TODO(satyamshekhar): Think about handling packets from different client
160f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // addresses.
161a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ConnectionIdMap::iterator it = connection_id_map_.find(connection_id);
162a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK(it != connection_id_map_.end());
163f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Increment the received packet count.
164f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ++((it->second).num_packets);
165f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!ShouldSendResponse((it->second).num_packets)) {
1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
167f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
168f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (it->second.close_packet) {
169f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)     QueuedPacket* queued_packet =
1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)         new QueuedPacket(server_address,
1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                          client_address,
172f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                          it->second.close_packet->Clone());
173f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)     // Takes ownership of the packet.
174f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)     SendOrQueuePacket(queued_packet);
175f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  } else {
176a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    SendPublicReset(server_address,
177a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                    client_address,
178a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                    connection_id,
179a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                    sequence_number);
180f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
183a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Returns true if the number of packets received for this connection_id is a
184a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// power of 2 to throttle the number of public reset packets we send to a
185a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// client.
186f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)bool QuicTimeWaitListManager::ShouldSendResponse(int received_packet_count) {
187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return (received_packet_count & (received_packet_count - 1)) == 0;
188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void QuicTimeWaitListManager::SendPublicReset(
191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const IPEndPoint& server_address,
192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const IPEndPoint& client_address,
193a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    QuicConnectionId connection_id,
194c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    QuicPacketSequenceNumber rejected_sequence_number) {
195c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  QuicPublicResetPacket packet;
196a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  packet.public_header.connection_id = connection_id;
197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  packet.public_header.reset_flag = true;
198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  packet.public_header.version_flag = false;
199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  packet.rejected_sequence_number = rejected_sequence_number;
200a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // TODO(satyamshekhar): generate a valid nonce for this connection_id.
201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  packet.nonce_proof = 1010101;
2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  packet.client_address = client_address;
203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  QueuedPacket* queued_packet = new QueuedPacket(
204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      server_address,
205c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      client_address,
2060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      BuildPublicReset(packet));
207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Takes ownership of the packet.
208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SendOrQueuePacket(queued_packet);
209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
210c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2110529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochQuicEncryptedPacket* QuicTimeWaitListManager::BuildPublicReset(
2120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    const QuicPublicResetPacket& packet) {
2130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return QuicFramer::BuildPublicResetPacket(packet);
2140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
2150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Either sends the packet and deletes it or makes pending queue the
217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// owner of the packet.
218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void QuicTimeWaitListManager::SendOrQueuePacket(QueuedPacket* packet) {
2195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (WriteToWire(packet)) {
2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    delete packet;
2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else {
222c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // pending_packets_queue takes the ownership of the queued packet.
223c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    pending_packets_queue_.push_back(packet);
224c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool QuicTimeWaitListManager::WriteToWire(QueuedPacket* queued_packet) {
2285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (writer_->IsWriteBlocked()) {
2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    visitor_->OnWriteBlocked(this);
2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  WriteResult result = writer_->WritePacket(
2334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      queued_packet->packet()->data(),
2344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      queued_packet->packet()->length(),
2354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      queued_packet->server_address().address(),
2365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      queued_packet->client_address());
2374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (result.status == WRITE_STATUS_BLOCKED) {
2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // If blocked and unbuffered, return false to retry sending.
2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DCHECK(writer_->IsWriteBlocked());
2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    visitor_->OnWriteBlocked(this);
2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return writer_->IsWriteBlockedDataBuffered();
2424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  } else if (result.status == WRITE_STATUS_ERROR) {
2434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    LOG(WARNING) << "Received unknown error while sending reset packet to "
2444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                 << queued_packet->client_address().ToString() << ": "
2454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                 << strerror(result.error_code);
246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return true;
248c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
249c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
250a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void QuicTimeWaitListManager::SetConnectionIdCleanUpAlarm() {
251a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  connection_id_clean_up_alarm_->UnregisterIfRegistered();
252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int64 next_alarm_interval;
253a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!connection_id_map_.empty()) {
254a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    QuicTime oldest_connection_id =
255a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        connection_id_map_.begin()->second.time_added;
256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    QuicTime now = clock_.ApproximateNow();
257a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (now.Subtract(oldest_connection_id) < kTimeWaitPeriod_) {
258a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      next_alarm_interval = oldest_connection_id.Add(kTimeWaitPeriod_)
259a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                                .Subtract(now)
260a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                                .ToMicroseconds();
2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    } else {
262a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      LOG(ERROR) << "ConnectionId lingered for longer than kTimeWaitPeriod";
2635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      next_alarm_interval = 0;
2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
265c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else {
266a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // No connection_ids added so none will expire before kTimeWaitPeriod_.
267c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    next_alarm_interval = kTimeWaitPeriod_.ToMicroseconds();
268c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
269c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
270a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  epoll_server_->RegisterAlarmApproximateDelta(
271a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      next_alarm_interval, connection_id_clean_up_alarm_.get());
272c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
273c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
274a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void QuicTimeWaitListManager::CleanUpOldConnectionIds() {
275c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  QuicTime now = clock_.ApproximateNow();
276a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  while (!connection_id_map_.empty()) {
277a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    ConnectionIdMap::iterator it = connection_id_map_.begin();
278a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    QuicTime oldest_connection_id = it->second.time_added;
279a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (now.Subtract(oldest_connection_id) < kTimeWaitPeriod_) {
280c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      break;
281c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
282a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // This connection_id has lived its age, retire it now.
283f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    delete it->second.close_packet;
284a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    connection_id_map_.erase(it);
285c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
286a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  SetConnectionIdCleanUpAlarm();
287c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
288c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
289c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace tools
290c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace net
291