| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/tools/quic/quic_time_wait_list_manager.h" | 5 #include "net/tools/quic/quic_time_wait_list_manager.h" |
| 6 | 6 |
| 7 #include <errno.h> | 7 #include <errno.h> |
| 8 | 8 |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.h" |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 90 visitor_(visitor) { | 90 visitor_(visitor) { |
| 91 SetConnectionIdCleanUpAlarm(); | 91 SetConnectionIdCleanUpAlarm(); |
| 92 } | 92 } |
| 93 | 93 |
| 94 QuicTimeWaitListManager::~QuicTimeWaitListManager() { | 94 QuicTimeWaitListManager::~QuicTimeWaitListManager() { |
| 95 connection_id_clean_up_alarm_->Cancel(); | 95 connection_id_clean_up_alarm_->Cancel(); |
| 96 STLDeleteElements(&pending_packets_queue_); | 96 STLDeleteElements(&pending_packets_queue_); |
| 97 for (ConnectionIdMap::iterator it = connection_id_map_.begin(); | 97 for (ConnectionIdMap::iterator it = connection_id_map_.begin(); |
| 98 it != connection_id_map_.end(); | 98 it != connection_id_map_.end(); |
| 99 ++it) { | 99 ++it) { |
| 100 delete it->second.close_packet; | 100 STLDeleteElements(&it->second.termination_packets); |
| 101 } | 101 } |
| 102 } | 102 } |
| 103 | 103 |
| 104 void QuicTimeWaitListManager::AddConnectionIdToTimeWait( | 104 void QuicTimeWaitListManager::AddConnectionIdToTimeWait( |
| 105 QuicConnectionId connection_id, | 105 QuicConnectionId connection_id, |
| 106 QuicVersion version, | 106 QuicVersion version, |
| 107 bool connection_rejected_statelessly, | 107 bool connection_rejected_statelessly, |
| 108 QuicEncryptedPacket* close_packet) { | 108 std::vector<QuicEncryptedPacket*>* termination_packets) { |
| 109 DCHECK(!connection_rejected_statelessly || !close_packet) | 109 if (connection_rejected_statelessly) { |
| 110 << "Connections that were rejected statelessly should not " | 110 DCHECK(termination_packets != nullptr && !termination_packets->empty()) |
| 111 << "have a close packet. connection_id = " << connection_id; | 111 << "Connections that were rejected statelessly must " |
| 112 << "have a close packet. connection_id = " << connection_id; |
| 113 } |
| 112 int num_packets = 0; | 114 int num_packets = 0; |
| 113 ConnectionIdMap::iterator it = connection_id_map_.find(connection_id); | 115 ConnectionIdMap::iterator it = connection_id_map_.find(connection_id); |
| 114 const bool new_connection_id = it == connection_id_map_.end(); | 116 const bool new_connection_id = it == connection_id_map_.end(); |
| 115 if (!new_connection_id) { // Replace record if it is reinserted. | 117 if (!new_connection_id) { // Replace record if it is reinserted. |
| 116 num_packets = it->second.num_packets; | 118 num_packets = it->second.num_packets; |
| 117 delete it->second.close_packet; | 119 STLDeleteElements(&it->second.termination_packets); |
| 118 connection_id_map_.erase(it); | 120 connection_id_map_.erase(it); |
| 119 } | 121 } |
| 120 TrimTimeWaitListIfNeeded(); | 122 TrimTimeWaitListIfNeeded(); |
| 121 DCHECK_LT(num_connections(), | 123 DCHECK_LT(num_connections(), |
| 122 static_cast<size_t>(FLAGS_quic_time_wait_list_max_connections)); | 124 static_cast<size_t>(FLAGS_quic_time_wait_list_max_connections)); |
| 123 ConnectionIdData data(num_packets, version, clock_->ApproximateNow(), | 125 ConnectionIdData data(num_packets, version, clock_->ApproximateNow(), |
| 124 close_packet, connection_rejected_statelessly); | 126 connection_rejected_statelessly); |
| 127 if (termination_packets != nullptr) { |
| 128 data.termination_packets.swap(*termination_packets); |
| 129 } |
| 125 connection_id_map_.insert(std::make_pair(connection_id, data)); | 130 connection_id_map_.insert(std::make_pair(connection_id, data)); |
| 126 if (new_connection_id) { | 131 if (new_connection_id) { |
| 127 visitor_->OnConnectionAddedToTimeWaitList(connection_id); | 132 visitor_->OnConnectionAddedToTimeWaitList(connection_id); |
| 128 } | 133 } |
| 129 } | 134 } |
| 130 | 135 |
| 131 bool QuicTimeWaitListManager::IsConnectionIdInTimeWait( | 136 bool QuicTimeWaitListManager::IsConnectionIdInTimeWait( |
| 132 QuicConnectionId connection_id) const { | 137 QuicConnectionId connection_id) const { |
| 133 return ContainsKey(connection_id_map_, connection_id); | 138 return ContainsKey(connection_id_map_, connection_id); |
| 134 } | 139 } |
| (...skipping 29 matching lines...) Expand all Loading... |
| 164 ConnectionIdMap::iterator it = connection_id_map_.find(connection_id); | 169 ConnectionIdMap::iterator it = connection_id_map_.find(connection_id); |
| 165 DCHECK(it != connection_id_map_.end()); | 170 DCHECK(it != connection_id_map_.end()); |
| 166 // Increment the received packet count. | 171 // Increment the received packet count. |
| 167 ConnectionIdData* connection_data = &it->second; | 172 ConnectionIdData* connection_data = &it->second; |
| 168 ++(connection_data->num_packets); | 173 ++(connection_data->num_packets); |
| 169 | 174 |
| 170 if (!ShouldSendResponse(connection_data->num_packets)) { | 175 if (!ShouldSendResponse(connection_data->num_packets)) { |
| 171 return; | 176 return; |
| 172 } | 177 } |
| 173 | 178 |
| 174 if (connection_data->close_packet) { | 179 if (!connection_data->termination_packets.empty()) { |
| 175 QueuedPacket* queued_packet = new QueuedPacket( | 180 if (connection_data->connection_rejected_statelessly) { |
| 176 server_address, client_address, connection_data->close_packet->Clone()); | 181 DVLOG(3) << "Time wait list sending previous stateless reject response " |
| 177 // Takes ownership of the packet. | 182 << "for connection " << connection_id; |
| 178 SendOrQueuePacket(queued_packet); | 183 } |
| 184 for (QuicEncryptedPacket* packet : connection_data->termination_packets) { |
| 185 QueuedPacket* queued_packet = |
| 186 new QueuedPacket(server_address, client_address, packet->Clone()); |
| 187 // Takes ownership of the packet. |
| 188 SendOrQueuePacket(queued_packet); |
| 189 } |
| 179 return; | 190 return; |
| 180 } | 191 } |
| 181 | 192 |
| 182 if (connection_data->connection_rejected_statelessly) { | |
| 183 DVLOG(3) << "Time wait list not sending response for connection " | |
| 184 << connection_id << " due to previous stateless reject."; | |
| 185 return; | |
| 186 } | |
| 187 | |
| 188 SendPublicReset(server_address, client_address, connection_id, packet_number); | 193 SendPublicReset(server_address, client_address, connection_id, packet_number); |
| 189 } | 194 } |
| 190 | 195 |
| 191 // Returns true if the number of packets received for this connection_id is a | 196 // Returns true if the number of packets received for this connection_id is a |
| 192 // power of 2 to throttle the number of public reset packets we send to a | 197 // power of 2 to throttle the number of public reset packets we send to a |
| 193 // client. | 198 // client. |
| 194 bool QuicTimeWaitListManager::ShouldSendResponse(int received_packet_count) { | 199 bool QuicTimeWaitListManager::ShouldSendResponse(int received_packet_count) { |
| 195 return (received_packet_count & (received_packet_count - 1)) == 0; | 200 return (received_packet_count & (received_packet_count - 1)) == 0; |
| 196 } | 201 } |
| 197 | 202 |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 283 return false; | 288 return false; |
| 284 } | 289 } |
| 285 ConnectionIdMap::iterator it = connection_id_map_.begin(); | 290 ConnectionIdMap::iterator it = connection_id_map_.begin(); |
| 286 QuicTime oldest_connection_id_time = it->second.time_added; | 291 QuicTime oldest_connection_id_time = it->second.time_added; |
| 287 if (oldest_connection_id_time > expiration_time) { | 292 if (oldest_connection_id_time > expiration_time) { |
| 288 // Too recent, don't retire. | 293 // Too recent, don't retire. |
| 289 return false; | 294 return false; |
| 290 } | 295 } |
| 291 // This connection_id has lived its age, retire it now. | 296 // This connection_id has lived its age, retire it now. |
| 292 const QuicConnectionId connection_id = it->first; | 297 const QuicConnectionId connection_id = it->first; |
| 293 delete it->second.close_packet; | 298 STLDeleteElements(&it->second.termination_packets); |
| 294 connection_id_map_.erase(it); | 299 connection_id_map_.erase(it); |
| 295 visitor_->OnConnectionRemovedFromTimeWaitList(connection_id); | 300 visitor_->OnConnectionRemovedFromTimeWaitList(connection_id); |
| 296 return true; | 301 return true; |
| 297 } | 302 } |
| 298 | 303 |
| 299 void QuicTimeWaitListManager::CleanUpOldConnectionIds() { | 304 void QuicTimeWaitListManager::CleanUpOldConnectionIds() { |
| 300 QuicTime now = clock_->ApproximateNow(); | 305 QuicTime now = clock_->ApproximateNow(); |
| 301 QuicTime expiration = now.Subtract(time_wait_period_); | 306 QuicTime expiration = now.Subtract(time_wait_period_); |
| 302 | 307 |
| 303 while (MaybeExpireOldestConnection(expiration)) { | 308 while (MaybeExpireOldestConnection(expiration)) { |
| 304 } | 309 } |
| 305 | 310 |
| 306 SetConnectionIdCleanUpAlarm(); | 311 SetConnectionIdCleanUpAlarm(); |
| 307 } | 312 } |
| 308 | 313 |
| 309 void QuicTimeWaitListManager::TrimTimeWaitListIfNeeded() { | 314 void QuicTimeWaitListManager::TrimTimeWaitListIfNeeded() { |
| 310 if (FLAGS_quic_time_wait_list_max_connections < 0) { | 315 if (FLAGS_quic_time_wait_list_max_connections < 0) { |
| 311 return; | 316 return; |
| 312 } | 317 } |
| 313 while (num_connections() >= | 318 while (num_connections() >= |
| 314 static_cast<size_t>(FLAGS_quic_time_wait_list_max_connections)) { | 319 static_cast<size_t>(FLAGS_quic_time_wait_list_max_connections)) { |
| 315 MaybeExpireOldestConnection(QuicTime::Infinite()); | 320 MaybeExpireOldestConnection(QuicTime::Infinite()); |
| 316 } | 321 } |
| 317 } | 322 } |
| 318 | 323 |
| 324 QuicTimeWaitListManager::ConnectionIdData::ConnectionIdData( |
| 325 int num_packets_, |
| 326 QuicVersion version_, |
| 327 QuicTime time_added_, |
| 328 bool connection_rejected_statelessly) |
| 329 : num_packets(num_packets_), |
| 330 version(version_), |
| 331 time_added(time_added_), |
| 332 connection_rejected_statelessly(connection_rejected_statelessly) {} |
| 333 |
| 334 QuicTimeWaitListManager::ConnectionIdData::~ConnectionIdData() {} |
| 335 |
| 319 } // namespace tools | 336 } // namespace tools |
| 320 } // namespace net | 337 } // namespace net |
| OLD | NEW |