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