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_framer.h" | 17 #include "net/quic/quic_framer.h" |
18 #include "net/quic/quic_protocol.h" | 18 #include "net/quic/quic_protocol.h" |
19 #include "net/quic/quic_utils.h" | 19 #include "net/quic/quic_utils.h" |
20 #include "net/tools/quic/quic_server_session.h" | 20 #include "net/tools/quic/quic_server_session.h" |
21 | 21 |
22 using base::StringPiece; | 22 using base::StringPiece; |
23 using std::make_pair; | 23 using std::make_pair; |
24 | 24 |
25 namespace net { | 25 namespace net { |
26 namespace tools { | 26 namespace tools { |
27 | 27 |
28 namespace { | 28 namespace { |
29 | 29 |
30 // Time period for which the guid should live in time wait state.. | 30 // Time period for which the connection_id should live in time wait state.. |
31 const int kTimeWaitSeconds = 5; | 31 const int kTimeWaitSeconds = 5; |
32 | 32 |
33 } // namespace | 33 } // namespace |
34 | 34 |
35 // A very simple alarm that just informs the QuicTimeWaitListManager to clean | 35 // A very simple alarm that just informs the QuicTimeWaitListManager to clean |
36 // up old guids. This alarm should be unregistered and deleted before the | 36 // up old connection_ids. This alarm should be unregistered and deleted before |
37 // QuicTimeWaitListManager is deleted. | 37 // the QuicTimeWaitListManager is deleted. |
38 class GuidCleanUpAlarm : public EpollAlarm { | 38 class ConnectionIdCleanUpAlarm : public EpollAlarm { |
39 public: | 39 public: |
40 explicit GuidCleanUpAlarm(QuicTimeWaitListManager* time_wait_list_manager) | 40 explicit ConnectionIdCleanUpAlarm( |
| 41 QuicTimeWaitListManager* time_wait_list_manager) |
41 : time_wait_list_manager_(time_wait_list_manager) { | 42 : time_wait_list_manager_(time_wait_list_manager) { |
42 } | 43 } |
43 | 44 |
44 virtual int64 OnAlarm() OVERRIDE { | 45 virtual int64 OnAlarm() OVERRIDE { |
45 EpollAlarm::OnAlarm(); | 46 EpollAlarm::OnAlarm(); |
46 time_wait_list_manager_->CleanUpOldGuids(); | 47 time_wait_list_manager_->CleanUpOldConnectionIds(); |
47 // Let the time wait manager register the alarm at appropriate time. | 48 // Let the time wait manager register the alarm at appropriate time. |
48 return 0; | 49 return 0; |
49 } | 50 } |
50 | 51 |
51 private: | 52 private: |
52 // Not owned. | 53 // Not owned. |
53 QuicTimeWaitListManager* time_wait_list_manager_; | 54 QuicTimeWaitListManager* time_wait_list_manager_; |
54 }; | 55 }; |
55 | 56 |
56 // This class stores pending public reset packets to be sent to clients. | 57 // This class stores pending public reset packets to be sent to clients. |
57 // server_address - server address on which a packet what was received for | 58 // server_address - server address on which a packet what was received for |
58 // a guid in time wait state. | 59 // a connection_id in time wait state. |
59 // client_address - address of the client that sent that packet. Needed to send | 60 // client_address - address of the client that sent that packet. Needed to send |
60 // the public reset packet back to the client. | 61 // the public reset packet back to the client. |
61 // packet - the pending public reset packet that is to be sent to the client. | 62 // packet - the pending public reset packet that is to be sent to the client. |
62 // created instance takes the ownership of this packet. | 63 // created instance takes the ownership of this packet. |
63 class QuicTimeWaitListManager::QueuedPacket { | 64 class QuicTimeWaitListManager::QueuedPacket { |
64 public: | 65 public: |
65 QueuedPacket(const IPEndPoint& server_address, | 66 QueuedPacket(const IPEndPoint& server_address, |
66 const IPEndPoint& client_address, | 67 const IPEndPoint& client_address, |
67 QuicEncryptedPacket* packet) | 68 QuicEncryptedPacket* packet) |
68 : server_address_(server_address), | 69 : server_address_(server_address), |
(...skipping 13 matching lines...) Expand all Loading... |
82 DISALLOW_COPY_AND_ASSIGN(QueuedPacket); | 83 DISALLOW_COPY_AND_ASSIGN(QueuedPacket); |
83 }; | 84 }; |
84 | 85 |
85 QuicTimeWaitListManager::QuicTimeWaitListManager( | 86 QuicTimeWaitListManager::QuicTimeWaitListManager( |
86 QuicPacketWriter* writer, | 87 QuicPacketWriter* writer, |
87 QuicServerSessionVisitor* visitor, | 88 QuicServerSessionVisitor* visitor, |
88 EpollServer* epoll_server, | 89 EpollServer* epoll_server, |
89 const QuicVersionVector& supported_versions) | 90 const QuicVersionVector& supported_versions) |
90 : epoll_server_(epoll_server), | 91 : epoll_server_(epoll_server), |
91 kTimeWaitPeriod_(QuicTime::Delta::FromSeconds(kTimeWaitSeconds)), | 92 kTimeWaitPeriod_(QuicTime::Delta::FromSeconds(kTimeWaitSeconds)), |
92 guid_clean_up_alarm_(new GuidCleanUpAlarm(this)), | 93 connection_id_clean_up_alarm_(new ConnectionIdCleanUpAlarm(this)), |
93 clock_(epoll_server_), | 94 clock_(epoll_server_), |
94 writer_(writer), | 95 writer_(writer), |
95 visitor_(visitor) { | 96 visitor_(visitor) { |
96 SetGuidCleanUpAlarm(); | 97 SetConnectionIdCleanUpAlarm(); |
97 } | 98 } |
98 | 99 |
99 QuicTimeWaitListManager::~QuicTimeWaitListManager() { | 100 QuicTimeWaitListManager::~QuicTimeWaitListManager() { |
100 guid_clean_up_alarm_->UnregisterIfRegistered(); | 101 connection_id_clean_up_alarm_->UnregisterIfRegistered(); |
101 STLDeleteElements(&pending_packets_queue_); | 102 STLDeleteElements(&pending_packets_queue_); |
102 for (GuidMap::iterator it = guid_map_.begin(); it != guid_map_.end(); ++it) { | 103 for (ConnectionIdMap::iterator it = connection_id_map_.begin(); |
| 104 it != connection_id_map_.end(); |
| 105 ++it) { |
103 delete it->second.close_packet; | 106 delete it->second.close_packet; |
104 } | 107 } |
105 } | 108 } |
106 | 109 |
107 void QuicTimeWaitListManager::AddGuidToTimeWait( | 110 void QuicTimeWaitListManager::AddConnectionIdToTimeWait( |
108 QuicGuid guid, | 111 QuicConnectionId connection_id, |
109 QuicVersion version, | 112 QuicVersion version, |
110 QuicEncryptedPacket* close_packet) { | 113 QuicEncryptedPacket* close_packet) { |
111 int num_packets = 0; | 114 int num_packets = 0; |
112 GuidMap::iterator it = guid_map_.find(guid); | 115 ConnectionIdMap::iterator it = connection_id_map_.find(connection_id); |
113 if (it != guid_map_.end()) { // Replace record if it is reinserted. | 116 if (it != connection_id_map_.end()) { // Replace record if it is reinserted. |
114 num_packets = it->second.num_packets; | 117 num_packets = it->second.num_packets; |
115 delete it->second.close_packet; | 118 delete it->second.close_packet; |
116 guid_map_.erase(it); | 119 connection_id_map_.erase(it); |
117 } | 120 } |
118 GuidData data(num_packets, version, clock_.ApproximateNow(), close_packet); | 121 ConnectionIdData data(num_packets, version, clock_.ApproximateNow(), |
119 guid_map_.insert(make_pair(guid, data)); | 122 close_packet); |
| 123 connection_id_map_.insert(make_pair(connection_id, data)); |
120 } | 124 } |
121 | 125 |
122 bool QuicTimeWaitListManager::IsGuidInTimeWait(QuicGuid guid) const { | 126 bool QuicTimeWaitListManager::IsConnectionIdInTimeWait( |
123 return guid_map_.find(guid) != guid_map_.end(); | 127 QuicConnectionId connection_id) const { |
| 128 return ContainsKey(connection_id_map_, connection_id); |
124 } | 129 } |
125 | 130 |
126 QuicVersion QuicTimeWaitListManager::GetQuicVersionFromGuid(QuicGuid guid) { | 131 QuicVersion QuicTimeWaitListManager::GetQuicVersionFromConnectionId( |
127 GuidMap::iterator it = guid_map_.find(guid); | 132 QuicConnectionId connection_id) { |
128 DCHECK(it != guid_map_.end()); | 133 ConnectionIdMap::iterator it = connection_id_map_.find(connection_id); |
| 134 DCHECK(it != connection_id_map_.end()); |
129 return (it->second).version; | 135 return (it->second).version; |
130 } | 136 } |
131 | 137 |
132 void QuicTimeWaitListManager::OnCanWrite() { | 138 void QuicTimeWaitListManager::OnCanWrite() { |
133 while (!pending_packets_queue_.empty()) { | 139 while (!pending_packets_queue_.empty()) { |
134 QueuedPacket* queued_packet = pending_packets_queue_.front(); | 140 QueuedPacket* queued_packet = pending_packets_queue_.front(); |
135 if (!WriteToWire(queued_packet)) { | 141 if (!WriteToWire(queued_packet)) { |
136 return; | 142 return; |
137 } | 143 } |
138 pending_packets_queue_.pop_front(); | 144 pending_packets_queue_.pop_front(); |
139 delete queued_packet; | 145 delete queued_packet; |
140 } | 146 } |
141 } | 147 } |
142 | 148 |
143 void QuicTimeWaitListManager::ProcessPacket( | 149 void QuicTimeWaitListManager::ProcessPacket( |
144 const IPEndPoint& server_address, | 150 const IPEndPoint& server_address, |
145 const IPEndPoint& client_address, | 151 const IPEndPoint& client_address, |
146 QuicGuid guid, | 152 QuicConnectionId connection_id, |
147 QuicPacketSequenceNumber sequence_number) { | 153 QuicPacketSequenceNumber sequence_number) { |
148 DCHECK(IsGuidInTimeWait(guid)); | 154 DCHECK(IsConnectionIdInTimeWait(connection_id)); |
149 // TODO(satyamshekhar): Think about handling packets from different client | 155 // TODO(satyamshekhar): Think about handling packets from different client |
150 // addresses. | 156 // addresses. |
151 GuidMap::iterator it = guid_map_.find(guid); | 157 ConnectionIdMap::iterator it = connection_id_map_.find(connection_id); |
152 DCHECK(it != guid_map_.end()); | 158 DCHECK(it != connection_id_map_.end()); |
153 // Increment the received packet count. | 159 // Increment the received packet count. |
154 ++((it->second).num_packets); | 160 ++((it->second).num_packets); |
155 if (!ShouldSendResponse((it->second).num_packets)) { | 161 if (!ShouldSendResponse((it->second).num_packets)) { |
156 return; | 162 return; |
157 } | 163 } |
158 if (it->second.close_packet) { | 164 if (it->second.close_packet) { |
159 QueuedPacket* queued_packet = | 165 QueuedPacket* queued_packet = |
160 new QueuedPacket(server_address, | 166 new QueuedPacket(server_address, |
161 client_address, | 167 client_address, |
162 it->second.close_packet->Clone()); | 168 it->second.close_packet->Clone()); |
163 // Takes ownership of the packet. | 169 // Takes ownership of the packet. |
164 SendOrQueuePacket(queued_packet); | 170 SendOrQueuePacket(queued_packet); |
165 } else { | 171 } else { |
166 SendPublicReset(server_address, client_address, guid, sequence_number); | 172 SendPublicReset(server_address, |
| 173 client_address, |
| 174 connection_id, |
| 175 sequence_number); |
167 } | 176 } |
168 } | 177 } |
169 | 178 |
170 // Returns true if the number of packets received for this guid is a power of 2 | 179 // Returns true if the number of packets received for this connection_id is a |
171 // to throttle the number of public reset packets we send to a client. | 180 // power of 2 to throttle the number of public reset packets we send to a |
| 181 // client. |
172 bool QuicTimeWaitListManager::ShouldSendResponse(int received_packet_count) { | 182 bool QuicTimeWaitListManager::ShouldSendResponse(int received_packet_count) { |
173 return (received_packet_count & (received_packet_count - 1)) == 0; | 183 return (received_packet_count & (received_packet_count - 1)) == 0; |
174 } | 184 } |
175 | 185 |
176 void QuicTimeWaitListManager::SendPublicReset( | 186 void QuicTimeWaitListManager::SendPublicReset( |
177 const IPEndPoint& server_address, | 187 const IPEndPoint& server_address, |
178 const IPEndPoint& client_address, | 188 const IPEndPoint& client_address, |
179 QuicGuid guid, | 189 QuicConnectionId connection_id, |
180 QuicPacketSequenceNumber rejected_sequence_number) { | 190 QuicPacketSequenceNumber rejected_sequence_number) { |
181 QuicPublicResetPacket packet; | 191 QuicPublicResetPacket packet; |
182 packet.public_header.guid = guid; | 192 packet.public_header.connection_id = connection_id; |
183 packet.public_header.reset_flag = true; | 193 packet.public_header.reset_flag = true; |
184 packet.public_header.version_flag = false; | 194 packet.public_header.version_flag = false; |
185 packet.rejected_sequence_number = rejected_sequence_number; | 195 packet.rejected_sequence_number = rejected_sequence_number; |
186 // TODO(satyamshekhar): generate a valid nonce for this guid. | 196 // TODO(satyamshekhar): generate a valid nonce for this connection_id. |
187 packet.nonce_proof = 1010101; | 197 packet.nonce_proof = 1010101; |
188 packet.client_address = client_address; | 198 packet.client_address = client_address; |
189 QueuedPacket* queued_packet = new QueuedPacket( | 199 QueuedPacket* queued_packet = new QueuedPacket( |
190 server_address, | 200 server_address, |
191 client_address, | 201 client_address, |
192 QuicFramer::BuildPublicResetPacket(packet)); | 202 QuicFramer::BuildPublicResetPacket(packet)); |
193 // Takes ownership of the packet. | 203 // Takes ownership of the packet. |
194 SendOrQueuePacket(queued_packet); | 204 SendOrQueuePacket(queued_packet); |
195 } | 205 } |
196 | 206 |
(...skipping 24 matching lines...) Expand all Loading... |
221 visitor_->OnWriteBlocked(this); | 231 visitor_->OnWriteBlocked(this); |
222 return writer_->IsWriteBlockedDataBuffered(); | 232 return writer_->IsWriteBlockedDataBuffered(); |
223 } else if (result.status == WRITE_STATUS_ERROR) { | 233 } else if (result.status == WRITE_STATUS_ERROR) { |
224 LOG(WARNING) << "Received unknown error while sending reset packet to " | 234 LOG(WARNING) << "Received unknown error while sending reset packet to " |
225 << queued_packet->client_address().ToString() << ": " | 235 << queued_packet->client_address().ToString() << ": " |
226 << strerror(result.error_code); | 236 << strerror(result.error_code); |
227 } | 237 } |
228 return true; | 238 return true; |
229 } | 239 } |
230 | 240 |
231 void QuicTimeWaitListManager::SetGuidCleanUpAlarm() { | 241 void QuicTimeWaitListManager::SetConnectionIdCleanUpAlarm() { |
232 guid_clean_up_alarm_->UnregisterIfRegistered(); | 242 connection_id_clean_up_alarm_->UnregisterIfRegistered(); |
233 int64 next_alarm_interval; | 243 int64 next_alarm_interval; |
234 if (!guid_map_.empty()) { | 244 if (!connection_id_map_.empty()) { |
235 QuicTime oldest_guid = guid_map_.begin()->second.time_added; | 245 QuicTime oldest_connection_id = |
| 246 connection_id_map_.begin()->second.time_added; |
236 QuicTime now = clock_.ApproximateNow(); | 247 QuicTime now = clock_.ApproximateNow(); |
237 if (now.Subtract(oldest_guid) < kTimeWaitPeriod_) { | 248 if (now.Subtract(oldest_connection_id) < kTimeWaitPeriod_) { |
238 next_alarm_interval = oldest_guid.Add(kTimeWaitPeriod_) | 249 next_alarm_interval = oldest_connection_id.Add(kTimeWaitPeriod_) |
239 .Subtract(now) | 250 .Subtract(now) |
240 .ToMicroseconds(); | 251 .ToMicroseconds(); |
241 } else { | 252 } else { |
242 LOG(ERROR) << "GUID lingered for longer than kTimeWaitPeriod"; | 253 LOG(ERROR) << "ConnectionId lingered for longer than kTimeWaitPeriod"; |
243 next_alarm_interval = 0; | 254 next_alarm_interval = 0; |
244 } | 255 } |
245 } else { | 256 } else { |
246 // No guids added so none will expire before kTimeWaitPeriod_. | 257 // No connection_ids added so none will expire before kTimeWaitPeriod_. |
247 next_alarm_interval = kTimeWaitPeriod_.ToMicroseconds(); | 258 next_alarm_interval = kTimeWaitPeriod_.ToMicroseconds(); |
248 } | 259 } |
249 | 260 |
250 epoll_server_->RegisterAlarmApproximateDelta(next_alarm_interval, | 261 epoll_server_->RegisterAlarmApproximateDelta( |
251 guid_clean_up_alarm_.get()); | 262 next_alarm_interval, connection_id_clean_up_alarm_.get()); |
252 } | 263 } |
253 | 264 |
254 void QuicTimeWaitListManager::CleanUpOldGuids() { | 265 void QuicTimeWaitListManager::CleanUpOldConnectionIds() { |
255 QuicTime now = clock_.ApproximateNow(); | 266 QuicTime now = clock_.ApproximateNow(); |
256 while (!guid_map_.empty()) { | 267 while (!connection_id_map_.empty()) { |
257 GuidMap::iterator it = guid_map_.begin(); | 268 ConnectionIdMap::iterator it = connection_id_map_.begin(); |
258 QuicTime oldest_guid = it->second.time_added; | 269 QuicTime oldest_connection_id = it->second.time_added; |
259 if (now.Subtract(oldest_guid) < kTimeWaitPeriod_) { | 270 if (now.Subtract(oldest_connection_id) < kTimeWaitPeriod_) { |
260 break; | 271 break; |
261 } | 272 } |
262 // This guid has lived its age, retire it now. | 273 // This connection_id has lived its age, retire it now. |
263 delete it->second.close_packet; | 274 delete it->second.close_packet; |
264 guid_map_.erase(it); | 275 connection_id_map_.erase(it); |
265 } | 276 } |
266 SetGuidCleanUpAlarm(); | 277 SetConnectionIdCleanUpAlarm(); |
267 } | 278 } |
268 | 279 |
269 } // namespace tools | 280 } // namespace tools |
270 } // namespace net | 281 } // namespace net |
OLD | NEW |