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 |