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_flags.h" |
18 #include "net/quic/quic_framer.h" | 18 #include "net/quic/quic_framer.h" |
19 #include "net/quic/quic_protocol.h" | 19 #include "net/quic/quic_protocol.h" |
20 #include "net/quic/quic_utils.h" | 20 #include "net/quic/quic_utils.h" |
21 #include "net/tools/epoll_server/epoll_server.h" | |
22 #include "net/tools/quic/quic_server_session.h" | 21 #include "net/tools/quic/quic_server_session.h" |
23 | 22 |
24 using base::StringPiece; | 23 using base::StringPiece; |
25 | 24 |
26 namespace net { | 25 namespace net { |
27 namespace tools { | 26 namespace tools { |
28 | 27 |
29 // TODO(rtenneti): Remove the duplicated code in this file. Share code with | 28 // TODO(rtenneti): Remove the duplicated code in this file. Share code with |
30 // "net/quic/quic_time_wait_list_manager.cc" | 29 // "net/quic/quic_time_wait_list_manager.cc" |
31 | 30 |
32 // A very simple alarm that just informs the QuicTimeWaitListManager to clean | 31 // A very simple alarm that just informs the QuicTimeWaitListManager to clean |
33 // up old connection_ids. This alarm should be unregistered and deleted before | 32 // up old connection_ids. This alarm should be cancelled and deleted before |
34 // the QuicTimeWaitListManager is deleted. | 33 // the QuicTimeWaitListManager is deleted. |
35 class ConnectionIdCleanUpAlarm : public EpollAlarm { | 34 class ConnectionIdCleanUpAlarm : public QuicAlarm::Delegate { |
36 public: | 35 public: |
37 explicit ConnectionIdCleanUpAlarm( | 36 explicit ConnectionIdCleanUpAlarm( |
38 QuicTimeWaitListManager* time_wait_list_manager) | 37 QuicTimeWaitListManager* time_wait_list_manager) |
39 : time_wait_list_manager_(time_wait_list_manager) { | 38 : time_wait_list_manager_(time_wait_list_manager) { |
40 } | 39 } |
41 | 40 |
42 int64 OnAlarm() override { | 41 QuicTime OnAlarm() override { |
43 EpollAlarm::OnAlarm(); | |
44 time_wait_list_manager_->CleanUpOldConnectionIds(); | 42 time_wait_list_manager_->CleanUpOldConnectionIds(); |
45 // Let the time wait manager register the alarm at appropriate time. | 43 // Let the time wait manager register the alarm at appropriate time. |
46 return 0; | 44 return QuicTime::Zero(); |
47 } | 45 } |
48 | 46 |
49 private: | 47 private: |
50 // Not owned. | 48 // Not owned. |
51 QuicTimeWaitListManager* time_wait_list_manager_; | 49 QuicTimeWaitListManager* time_wait_list_manager_; |
| 50 |
| 51 DISALLOW_COPY_AND_ASSIGN(ConnectionIdCleanUpAlarm); |
52 }; | 52 }; |
53 | 53 |
| 54 |
54 // This class stores pending public reset packets to be sent to clients. | 55 // This class stores pending public reset packets to be sent to clients. |
55 // server_address - server address on which a packet what was received for | 56 // server_address - server address on which a packet what was received for |
56 // a connection_id in time wait state. | 57 // a connection_id in time wait state. |
57 // client_address - address of the client that sent that packet. Needed to send | 58 // client_address - address of the client that sent that packet. Needed to send |
58 // the public reset packet back to the client. | 59 // the public reset packet back to the client. |
59 // packet - the pending public reset packet that is to be sent to the client. | 60 // packet - the pending public reset packet that is to be sent to the client. |
60 // created instance takes the ownership of this packet. | 61 // created instance takes the ownership of this packet. |
61 class QuicTimeWaitListManager::QueuedPacket { | 62 class QuicTimeWaitListManager::QueuedPacket { |
62 public: | 63 public: |
63 QueuedPacket(const IPEndPoint& server_address, | 64 QueuedPacket(const IPEndPoint& server_address, |
(...skipping 12 matching lines...) Expand all Loading... |
76 const IPEndPoint server_address_; | 77 const IPEndPoint server_address_; |
77 const IPEndPoint client_address_; | 78 const IPEndPoint client_address_; |
78 scoped_ptr<QuicEncryptedPacket> packet_; | 79 scoped_ptr<QuicEncryptedPacket> packet_; |
79 | 80 |
80 DISALLOW_COPY_AND_ASSIGN(QueuedPacket); | 81 DISALLOW_COPY_AND_ASSIGN(QueuedPacket); |
81 }; | 82 }; |
82 | 83 |
83 QuicTimeWaitListManager::QuicTimeWaitListManager( | 84 QuicTimeWaitListManager::QuicTimeWaitListManager( |
84 QuicPacketWriter* writer, | 85 QuicPacketWriter* writer, |
85 QuicServerSessionVisitor* visitor, | 86 QuicServerSessionVisitor* visitor, |
86 EpollServer* epoll_server, | 87 QuicConnectionHelperInterface* helper, |
87 const QuicVersionVector& supported_versions) | 88 const QuicVersionVector& supported_versions) |
88 : epoll_server_(epoll_server), | 89 : time_wait_period_( |
89 kTimeWaitPeriod_( | |
90 QuicTime::Delta::FromSeconds(FLAGS_quic_time_wait_list_seconds)), | 90 QuicTime::Delta::FromSeconds(FLAGS_quic_time_wait_list_seconds)), |
91 connection_id_clean_up_alarm_(new ConnectionIdCleanUpAlarm(this)), | 91 connection_id_clean_up_alarm_( |
92 clock_(epoll_server_), | 92 helper->CreateAlarm(new ConnectionIdCleanUpAlarm(this))), |
| 93 clock_(helper->GetClock()), |
93 writer_(writer), | 94 writer_(writer), |
94 visitor_(visitor) { | 95 visitor_(visitor) { |
95 SetConnectionIdCleanUpAlarm(); | 96 SetConnectionIdCleanUpAlarm(); |
96 } | 97 } |
97 | 98 |
98 QuicTimeWaitListManager::~QuicTimeWaitListManager() { | 99 QuicTimeWaitListManager::~QuicTimeWaitListManager() { |
99 connection_id_clean_up_alarm_->UnregisterIfRegistered(); | 100 connection_id_clean_up_alarm_->Cancel(); |
100 STLDeleteElements(&pending_packets_queue_); | 101 STLDeleteElements(&pending_packets_queue_); |
101 for (ConnectionIdMap::iterator it = connection_id_map_.begin(); | 102 for (ConnectionIdMap::iterator it = connection_id_map_.begin(); |
102 it != connection_id_map_.end(); | 103 it != connection_id_map_.end(); |
103 ++it) { | 104 ++it) { |
104 delete it->second.close_packet; | 105 delete it->second.close_packet; |
105 } | 106 } |
106 } | 107 } |
107 | 108 |
108 void QuicTimeWaitListManager::AddConnectionIdToTimeWait( | 109 void QuicTimeWaitListManager::AddConnectionIdToTimeWait( |
109 QuicConnectionId connection_id, | 110 QuicConnectionId connection_id, |
110 QuicVersion version, | 111 QuicVersion version, |
111 QuicEncryptedPacket* close_packet) { | 112 QuicEncryptedPacket* close_packet) { |
112 int num_packets = 0; | 113 int num_packets = 0; |
113 ConnectionIdMap::iterator it = connection_id_map_.find(connection_id); | 114 ConnectionIdMap::iterator it = connection_id_map_.find(connection_id); |
114 const bool new_connection_id = it == connection_id_map_.end(); | 115 const bool new_connection_id = it == connection_id_map_.end(); |
115 if (!new_connection_id) { // Replace record if it is reinserted. | 116 if (!new_connection_id) { // Replace record if it is reinserted. |
116 num_packets = it->second.num_packets; | 117 num_packets = it->second.num_packets; |
117 delete it->second.close_packet; | 118 delete it->second.close_packet; |
118 connection_id_map_.erase(it); | 119 connection_id_map_.erase(it); |
119 } | 120 } |
120 TrimTimeWaitListIfNeeded(); | 121 TrimTimeWaitListIfNeeded(); |
121 DCHECK_LT(num_connections(), | 122 DCHECK_LT(num_connections(), |
122 static_cast<size_t>(FLAGS_quic_time_wait_list_max_connections)); | 123 static_cast<size_t>(FLAGS_quic_time_wait_list_max_connections)); |
123 ConnectionIdData data(num_packets, | 124 ConnectionIdData data(num_packets, |
124 version, | 125 version, |
125 clock_.ApproximateNow(), | 126 clock_->ApproximateNow(), |
126 close_packet); | 127 close_packet); |
127 connection_id_map_.insert(std::make_pair(connection_id, data)); | 128 connection_id_map_.insert(std::make_pair(connection_id, data)); |
128 if (new_connection_id) { | 129 if (new_connection_id) { |
129 visitor_->OnConnectionAddedToTimeWaitList(connection_id); | 130 visitor_->OnConnectionAddedToTimeWaitList(connection_id); |
130 } | 131 } |
131 } | 132 } |
132 | 133 |
133 bool QuicTimeWaitListManager::IsConnectionIdInTimeWait( | 134 bool QuicTimeWaitListManager::IsConnectionIdInTimeWait( |
134 QuicConnectionId connection_id) const { | 135 QuicConnectionId connection_id) const { |
135 return ContainsKey(connection_id_map_, connection_id); | 136 return ContainsKey(connection_id_map_, connection_id); |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
246 return writer_->IsWriteBlockedDataBuffered(); | 247 return writer_->IsWriteBlockedDataBuffered(); |
247 } else if (result.status == WRITE_STATUS_ERROR) { | 248 } else if (result.status == WRITE_STATUS_ERROR) { |
248 LOG(WARNING) << "Received unknown error while sending reset packet to " | 249 LOG(WARNING) << "Received unknown error while sending reset packet to " |
249 << queued_packet->client_address().ToString() << ": " | 250 << queued_packet->client_address().ToString() << ": " |
250 << strerror(result.error_code); | 251 << strerror(result.error_code); |
251 } | 252 } |
252 return true; | 253 return true; |
253 } | 254 } |
254 | 255 |
255 void QuicTimeWaitListManager::SetConnectionIdCleanUpAlarm() { | 256 void QuicTimeWaitListManager::SetConnectionIdCleanUpAlarm() { |
256 connection_id_clean_up_alarm_->UnregisterIfRegistered(); | 257 connection_id_clean_up_alarm_->Cancel(); |
257 int64 next_alarm_interval; | 258 QuicTime::Delta next_alarm_interval = QuicTime::Delta::Zero(); |
258 if (!connection_id_map_.empty()) { | 259 if (!connection_id_map_.empty()) { |
259 QuicTime oldest_connection_id = | 260 QuicTime oldest_connection_id = |
260 connection_id_map_.begin()->second.time_added; | 261 connection_id_map_.begin()->second.time_added; |
261 QuicTime now = clock_.ApproximateNow(); | 262 QuicTime now = clock_->ApproximateNow(); |
262 if (now.Subtract(oldest_connection_id) < kTimeWaitPeriod_) { | 263 if (now.Subtract(oldest_connection_id) < time_wait_period_) { |
263 next_alarm_interval = oldest_connection_id.Add(kTimeWaitPeriod_) | 264 next_alarm_interval = oldest_connection_id.Add(time_wait_period_) |
264 .Subtract(now) | 265 .Subtract(now); |
265 .ToMicroseconds(); | |
266 } else { | 266 } else { |
267 LOG(ERROR) << "ConnectionId lingered for longer than kTimeWaitPeriod"; | 267 LOG(ERROR) << "ConnectionId lingered for longer than time_wait_period_"; |
268 next_alarm_interval = 0; | |
269 } | 268 } |
270 } else { | 269 } else { |
271 // No connection_ids added so none will expire before kTimeWaitPeriod_. | 270 // No connection_ids added so none will expire before time_wait_period_. |
272 next_alarm_interval = kTimeWaitPeriod_.ToMicroseconds(); | 271 next_alarm_interval = time_wait_period_; |
273 } | 272 } |
274 | 273 |
275 epoll_server_->RegisterAlarmApproximateDelta( | 274 connection_id_clean_up_alarm_->Set( |
276 next_alarm_interval, connection_id_clean_up_alarm_.get()); | 275 clock_->ApproximateNow().Add(next_alarm_interval)); |
277 } | 276 } |
278 | 277 |
279 bool QuicTimeWaitListManager::MaybeExpireOldestConnection( | 278 bool QuicTimeWaitListManager::MaybeExpireOldestConnection( |
280 QuicTime expiration_time) { | 279 QuicTime expiration_time) { |
281 if (connection_id_map_.empty()) { | 280 if (connection_id_map_.empty()) { |
282 return false; | 281 return false; |
283 } | 282 } |
284 ConnectionIdMap::iterator it = connection_id_map_.begin(); | 283 ConnectionIdMap::iterator it = connection_id_map_.begin(); |
285 QuicTime oldest_connection_id_time = it->second.time_added; | 284 QuicTime oldest_connection_id_time = it->second.time_added; |
286 if (oldest_connection_id_time > expiration_time) { | 285 if (oldest_connection_id_time > expiration_time) { |
287 // Too recent, don't retire. | 286 // Too recent, don't retire. |
288 return false; | 287 return false; |
289 } | 288 } |
290 // This connection_id has lived its age, retire it now. | 289 // This connection_id has lived its age, retire it now. |
291 const QuicConnectionId connection_id = it->first; | 290 const QuicConnectionId connection_id = it->first; |
292 delete it->second.close_packet; | 291 delete it->second.close_packet; |
293 connection_id_map_.erase(it); | 292 connection_id_map_.erase(it); |
294 visitor_->OnConnectionRemovedFromTimeWaitList(connection_id); | 293 visitor_->OnConnectionRemovedFromTimeWaitList(connection_id); |
295 return true; | 294 return true; |
296 } | 295 } |
297 | 296 |
298 void QuicTimeWaitListManager::CleanUpOldConnectionIds() { | 297 void QuicTimeWaitListManager::CleanUpOldConnectionIds() { |
299 QuicTime now = clock_.ApproximateNow(); | 298 QuicTime now = clock_->ApproximateNow(); |
300 QuicTime expiration = now.Subtract(kTimeWaitPeriod_); | 299 QuicTime expiration = now.Subtract(time_wait_period_); |
301 | 300 |
302 while (MaybeExpireOldestConnection(expiration)) { | 301 while (MaybeExpireOldestConnection(expiration)) { |
303 } | 302 } |
304 | 303 |
305 SetConnectionIdCleanUpAlarm(); | 304 SetConnectionIdCleanUpAlarm(); |
306 } | 305 } |
307 | 306 |
308 void QuicTimeWaitListManager::TrimTimeWaitListIfNeeded() { | 307 void QuicTimeWaitListManager::TrimTimeWaitListIfNeeded() { |
309 if (FLAGS_quic_time_wait_list_max_connections < 0) { | 308 if (FLAGS_quic_time_wait_list_max_connections < 0) { |
310 return; | 309 return; |
311 } | 310 } |
312 while (num_connections() >= | 311 while (num_connections() >= |
313 static_cast<size_t>(FLAGS_quic_time_wait_list_max_connections)) { | 312 static_cast<size_t>(FLAGS_quic_time_wait_list_max_connections)) { |
314 MaybeExpireOldestConnection(QuicTime::Infinite()); | 313 MaybeExpireOldestConnection(QuicTime::Infinite()); |
315 } | 314 } |
316 } | 315 } |
317 | 316 |
318 } // namespace tools | 317 } // namespace tools |
319 } // namespace net | 318 } // namespace net |
OLD | NEW |