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