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/containers/hash_tables.h" | 9 #include "base/containers/hash_tables.h" |
10 #include "base/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.h" |
11 #include "base/stl_util.h" | 11 #include "base/stl_util.h" |
12 #include "net/base/ip_endpoint.h" | 12 #include "net/base/ip_endpoint.h" |
13 #include "net/quic/crypto/crypto_protocol.h" | 13 #include "net/quic/crypto/crypto_protocol.h" |
14 #include "net/quic/crypto/quic_decrypter.h" | 14 #include "net/quic/crypto/quic_decrypter.h" |
15 #include "net/quic/crypto/quic_encrypter.h" | 15 #include "net/quic/crypto/quic_encrypter.h" |
16 #include "net/quic/quic_clock.h" | 16 #include "net/quic/quic_clock.h" |
| 17 #include "net/quic/quic_flags.h" |
17 #include "net/quic/quic_framer.h" | 18 #include "net/quic/quic_framer.h" |
18 #include "net/quic/quic_protocol.h" | 19 #include "net/quic/quic_protocol.h" |
19 #include "net/quic/quic_utils.h" | 20 #include "net/quic/quic_utils.h" |
20 #include "net/tools/epoll_server/epoll_server.h" | 21 #include "net/tools/epoll_server/epoll_server.h" |
21 #include "net/tools/quic/quic_server_session.h" | 22 #include "net/tools/quic/quic_server_session.h" |
22 | 23 |
23 using base::StringPiece; | 24 using base::StringPiece; |
24 using std::make_pair; | 25 using std::make_pair; |
25 | 26 |
26 namespace net { | 27 namespace net { |
27 namespace tools { | 28 namespace tools { |
28 | 29 |
29 namespace { | 30 // TODO(rtenneti): Remove the duplicated code in this file. Share code with |
30 | 31 // "net/quic/quic_time_wait_list_manager.cc" |
31 // Time period for which a given connection_id should live in the time-wait | |
32 // state. | |
33 int64 FLAGS_quic_time_wait_list_seconds = 5; | |
34 | |
35 } // namespace | |
36 | 32 |
37 // A very simple alarm that just informs the QuicTimeWaitListManager to clean | 33 // A very simple alarm that just informs the QuicTimeWaitListManager to clean |
38 // up old connection_ids. This alarm should be unregistered and deleted before | 34 // up old connection_ids. This alarm should be unregistered and deleted before |
39 // the QuicTimeWaitListManager is deleted. | 35 // the QuicTimeWaitListManager is deleted. |
40 class ConnectionIdCleanUpAlarm : public EpollAlarm { | 36 class ConnectionIdCleanUpAlarm : public EpollAlarm { |
41 public: | 37 public: |
42 explicit ConnectionIdCleanUpAlarm( | 38 explicit ConnectionIdCleanUpAlarm( |
43 QuicTimeWaitListManager* time_wait_list_manager) | 39 QuicTimeWaitListManager* time_wait_list_manager) |
44 : time_wait_list_manager_(time_wait_list_manager) { | 40 : time_wait_list_manager_(time_wait_list_manager) { |
45 } | 41 } |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
115 QuicVersion version, | 111 QuicVersion version, |
116 QuicEncryptedPacket* close_packet) { | 112 QuicEncryptedPacket* close_packet) { |
117 int num_packets = 0; | 113 int num_packets = 0; |
118 ConnectionIdMap::iterator it = connection_id_map_.find(connection_id); | 114 ConnectionIdMap::iterator it = connection_id_map_.find(connection_id); |
119 const bool new_connection_id = it == connection_id_map_.end(); | 115 const bool new_connection_id = it == connection_id_map_.end(); |
120 if (!new_connection_id) { // Replace record if it is reinserted. | 116 if (!new_connection_id) { // Replace record if it is reinserted. |
121 num_packets = it->second.num_packets; | 117 num_packets = it->second.num_packets; |
122 delete it->second.close_packet; | 118 delete it->second.close_packet; |
123 connection_id_map_.erase(it); | 119 connection_id_map_.erase(it); |
124 } | 120 } |
| 121 TrimTimeWaitListIfNeeded(); |
| 122 if (FLAGS_quic_limit_time_wait_list_size) { |
| 123 DCHECK_LT(num_connections(), |
| 124 static_cast<size_t>(FLAGS_quic_time_wait_list_max_connections)); |
| 125 } |
125 ConnectionIdData data(num_packets, | 126 ConnectionIdData data(num_packets, |
126 version, | 127 version, |
127 clock_.ApproximateNow(), | 128 clock_.ApproximateNow(), |
128 close_packet); | 129 close_packet); |
129 connection_id_map_.insert(make_pair(connection_id, data)); | 130 connection_id_map_.insert(make_pair(connection_id, data)); |
130 if (new_connection_id) { | 131 if (new_connection_id) { |
131 visitor_->OnConnectionAddedToTimeWaitList(connection_id); | 132 visitor_->OnConnectionAddedToTimeWaitList(connection_id); |
132 } | 133 } |
133 } | 134 } |
134 | 135 |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
271 } | 272 } |
272 } else { | 273 } else { |
273 // No connection_ids added so none will expire before kTimeWaitPeriod_. | 274 // No connection_ids added so none will expire before kTimeWaitPeriod_. |
274 next_alarm_interval = kTimeWaitPeriod_.ToMicroseconds(); | 275 next_alarm_interval = kTimeWaitPeriod_.ToMicroseconds(); |
275 } | 276 } |
276 | 277 |
277 epoll_server_->RegisterAlarmApproximateDelta( | 278 epoll_server_->RegisterAlarmApproximateDelta( |
278 next_alarm_interval, connection_id_clean_up_alarm_.get()); | 279 next_alarm_interval, connection_id_clean_up_alarm_.get()); |
279 } | 280 } |
280 | 281 |
| 282 bool QuicTimeWaitListManager::MaybeExpireOldestConnection( |
| 283 QuicTime expiration_time) { |
| 284 if (connection_id_map_.empty()) { |
| 285 return false; |
| 286 } |
| 287 ConnectionIdMap::iterator it = connection_id_map_.begin(); |
| 288 QuicTime oldest_connection_id_time = it->second.time_added; |
| 289 if (oldest_connection_id_time > expiration_time) { |
| 290 // Too recent, don't retire. |
| 291 return false; |
| 292 } |
| 293 // This connection_id has lived its age, retire it now. |
| 294 const QuicConnectionId connection_id = it->first; |
| 295 delete it->second.close_packet; |
| 296 connection_id_map_.erase(it); |
| 297 visitor_->OnConnectionRemovedFromTimeWaitList(connection_id); |
| 298 return true; |
| 299 } |
| 300 |
281 void QuicTimeWaitListManager::CleanUpOldConnectionIds() { | 301 void QuicTimeWaitListManager::CleanUpOldConnectionIds() { |
282 QuicTime now = clock_.ApproximateNow(); | 302 QuicTime now = clock_.ApproximateNow(); |
283 while (!connection_id_map_.empty()) { | 303 QuicTime expiration = now.Subtract(kTimeWaitPeriod_); |
284 ConnectionIdMap::iterator it = connection_id_map_.begin(); | 304 if (FLAGS_quic_limit_time_wait_list_size) { |
285 QuicTime oldest_connection_id = it->second.time_added; | 305 while (MaybeExpireOldestConnection(expiration)) { |
286 if (now.Subtract(oldest_connection_id) < kTimeWaitPeriod_) { | |
287 break; | |
288 } | 306 } |
289 const QuicConnectionId connection_id = it->first; | 307 } else { |
290 // This connection_id has lived its age, retire it now. | 308 while (!connection_id_map_.empty()) { |
291 delete it->second.close_packet; | 309 ConnectionIdMap::iterator it = connection_id_map_.begin(); |
292 connection_id_map_.erase(it); | 310 QuicTime oldest_connection_id = it->second.time_added; |
293 visitor_->OnConnectionRemovedFromTimeWaitList(connection_id); | 311 if (now.Subtract(oldest_connection_id) < kTimeWaitPeriod_) { |
| 312 break; |
| 313 } |
| 314 const QuicConnectionId connection_id = it->first; |
| 315 // This connection_id has lived its age, retire it now. |
| 316 delete it->second.close_packet; |
| 317 connection_id_map_.erase(it); |
| 318 visitor_->OnConnectionRemovedFromTimeWaitList(connection_id); |
| 319 } |
294 } | 320 } |
| 321 |
295 SetConnectionIdCleanUpAlarm(); | 322 SetConnectionIdCleanUpAlarm(); |
296 } | 323 } |
297 | 324 |
| 325 void QuicTimeWaitListManager::TrimTimeWaitListIfNeeded() { |
| 326 if (FLAGS_quic_limit_time_wait_list_size) { |
| 327 if (FLAGS_quic_time_wait_list_max_connections < 0) { |
| 328 return; |
| 329 } |
| 330 while (num_connections() >= |
| 331 static_cast<size_t>(FLAGS_quic_time_wait_list_max_connections)) { |
| 332 MaybeExpireOldestConnection(QuicTime::Infinite()); |
| 333 } |
| 334 } |
| 335 } |
| 336 |
298 } // namespace tools | 337 } // namespace tools |
299 } // namespace net | 338 } // namespace net |
OLD | NEW |