| 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" |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 88 const IPEndPoint client_address_; | 88 const IPEndPoint client_address_; |
| 89 scoped_ptr<QuicEncryptedPacket> packet_; | 89 scoped_ptr<QuicEncryptedPacket> packet_; |
| 90 | 90 |
| 91 DISALLOW_COPY_AND_ASSIGN(QueuedPacket); | 91 DISALLOW_COPY_AND_ASSIGN(QueuedPacket); |
| 92 }; | 92 }; |
| 93 | 93 |
| 94 QuicTimeWaitListManager::QuicTimeWaitListManager( | 94 QuicTimeWaitListManager::QuicTimeWaitListManager( |
| 95 QuicPacketWriter* writer, | 95 QuicPacketWriter* writer, |
| 96 EpollServer* epoll_server, | 96 EpollServer* epoll_server, |
| 97 const QuicVersionVector& supported_versions) | 97 const QuicVersionVector& supported_versions) |
| 98 : framer_(supported_versions, | 98 : epoll_server_(epoll_server), |
| 99 QuicTime::Zero(), // unused | |
| 100 true), | |
| 101 epoll_server_(epoll_server), | |
| 102 kTimeWaitPeriod_(QuicTime::Delta::FromSeconds(kTimeWaitSeconds)), | 99 kTimeWaitPeriod_(QuicTime::Delta::FromSeconds(kTimeWaitSeconds)), |
| 103 guid_clean_up_alarm_(new GuidCleanUpAlarm(this)), | 100 guid_clean_up_alarm_(new GuidCleanUpAlarm(this)), |
| 104 clock_(epoll_server), | 101 clock_(epoll_server_), |
| 105 writer_(writer), | 102 writer_(writer), |
| 106 is_write_blocked_(false) { | 103 is_write_blocked_(false) { |
| 107 framer_.set_visitor(this); | |
| 108 SetGuidCleanUpAlarm(); | 104 SetGuidCleanUpAlarm(); |
| 109 } | 105 } |
| 110 | 106 |
| 111 QuicTimeWaitListManager::~QuicTimeWaitListManager() { | 107 QuicTimeWaitListManager::~QuicTimeWaitListManager() { |
| 112 guid_clean_up_alarm_->UnregisterIfRegistered(); | 108 guid_clean_up_alarm_->UnregisterIfRegistered(); |
| 113 STLDeleteElements(&time_ordered_guid_list_); | 109 STLDeleteElements(&time_ordered_guid_list_); |
| 114 STLDeleteElements(&pending_packets_queue_); | 110 STLDeleteElements(&pending_packets_queue_); |
| 115 for (GuidMapIterator it = guid_map_.begin(); it != guid_map_.end(); ++it) { | 111 for (GuidMapIterator it = guid_map_.begin(); it != guid_map_.end(); ++it) { |
| 116 delete it->second.close_packet; | 112 delete it->second.close_packet; |
| 117 } | 113 } |
| 118 } | 114 } |
| 119 | 115 |
| 120 void QuicTimeWaitListManager::AddGuidToTimeWait( | 116 void QuicTimeWaitListManager::AddGuidToTimeWait( |
| 121 QuicGuid guid, | 117 QuicGuid guid, |
| 122 QuicVersion version, | 118 QuicVersion version, |
| 123 QuicEncryptedPacket* close_packet) { | 119 QuicEncryptedPacket* close_packet) { |
| 124 DCHECK(!IsGuidInTimeWait(guid)); | 120 DCHECK(!IsGuidInTimeWait(guid)); |
| 125 // Initialize the guid with 0 packets received. | 121 // Initialize the guid with 0 packets received. |
| 126 GuidData data(0, version, close_packet); | 122 GuidData data(0, version, close_packet); |
| 127 guid_map_.insert(make_pair(guid, data)); | 123 guid_map_.insert(make_pair(guid, data)); |
| 128 time_ordered_guid_list_.push_back(new GuidAddTime(guid, | 124 time_ordered_guid_list_.push_back(new GuidAddTime(guid, |
| 129 clock_.ApproximateNow())); | 125 clock_.ApproximateNow())); |
| 126 DCHECK(IsGuidInTimeWait(guid)); |
| 130 } | 127 } |
| 131 | 128 |
| 132 bool QuicTimeWaitListManager::IsGuidInTimeWait(QuicGuid guid) const { | 129 bool QuicTimeWaitListManager::IsGuidInTimeWait(QuicGuid guid) const { |
| 133 return guid_map_.find(guid) != guid_map_.end(); | 130 return guid_map_.find(guid) != guid_map_.end(); |
| 134 } | 131 } |
| 135 | 132 |
| 136 void QuicTimeWaitListManager::ProcessPacket( | |
| 137 const IPEndPoint& server_address, | |
| 138 const IPEndPoint& client_address, | |
| 139 QuicGuid guid, | |
| 140 const QuicEncryptedPacket& packet) { | |
| 141 DCHECK(IsGuidInTimeWait(guid)); | |
| 142 server_address_ = server_address; | |
| 143 client_address_ = client_address; | |
| 144 | |
| 145 // Set the framer to the appropriate version for this GUID, before processing. | |
| 146 QuicVersion version = GetQuicVersionFromGuid(guid); | |
| 147 framer_.set_version(version); | |
| 148 | |
| 149 framer_.ProcessPacket(packet); | |
| 150 } | |
| 151 | |
| 152 QuicVersion QuicTimeWaitListManager::GetQuicVersionFromGuid(QuicGuid guid) { | 133 QuicVersion QuicTimeWaitListManager::GetQuicVersionFromGuid(QuicGuid guid) { |
| 153 GuidMapIterator it = guid_map_.find(guid); | 134 GuidMapIterator it = guid_map_.find(guid); |
| 154 DCHECK(it != guid_map_.end()); | 135 DCHECK(it != guid_map_.end()); |
| 155 return (it->second).version; | 136 return (it->second).version; |
| 156 } | 137 } |
| 157 | 138 |
| 158 bool QuicTimeWaitListManager::OnCanWrite() { | 139 bool QuicTimeWaitListManager::OnCanWrite() { |
| 159 is_write_blocked_ = false; | 140 is_write_blocked_ = false; |
| 160 while (!is_write_blocked_ && !pending_packets_queue_.empty()) { | 141 while (!is_write_blocked_ && !pending_packets_queue_.empty()) { |
| 161 QueuedPacket* queued_packet = pending_packets_queue_.front(); | 142 QueuedPacket* queued_packet = pending_packets_queue_.front(); |
| 162 WriteToWire(queued_packet); | 143 WriteToWire(queued_packet); |
| 163 if (!is_write_blocked_) { | 144 if (!is_write_blocked_) { |
| 164 pending_packets_queue_.pop_front(); | 145 pending_packets_queue_.pop_front(); |
| 165 delete queued_packet; | 146 delete queued_packet; |
| 166 } | 147 } |
| 167 } | 148 } |
| 168 | 149 |
| 169 return !is_write_blocked_; | 150 return !is_write_blocked_; |
| 170 } | 151 } |
| 171 | 152 |
| 172 void QuicTimeWaitListManager::OnError(QuicFramer* framer) { | 153 void QuicTimeWaitListManager::ProcessPacket( |
| 173 DLOG(INFO) << QuicUtils::ErrorToString(framer->error()); | 154 const IPEndPoint& server_address, |
| 174 } | 155 const IPEndPoint& client_address, |
| 175 | 156 QuicGuid guid, |
| 176 bool QuicTimeWaitListManager::OnProtocolVersionMismatch( | 157 QuicPacketSequenceNumber sequence_number) { |
| 177 QuicVersion received_version) { | 158 DCHECK(IsGuidInTimeWait(guid)); |
| 178 if (!framer_.IsSupportedVersion(received_version)) { | |
| 179 // Drop such packets whose version don't match. | |
| 180 return false; | |
| 181 } | |
| 182 // Allow the framer to continue processing this packet. | |
| 183 framer_.set_version(received_version); | |
| 184 return true; | |
| 185 } | |
| 186 | |
| 187 bool QuicTimeWaitListManager::OnUnauthenticatedHeader( | |
| 188 const QuicPacketHeader& header) { | |
| 189 // TODO(satyamshekhar): Think about handling packets from different client | 159 // TODO(satyamshekhar): Think about handling packets from different client |
| 190 // addresses. | 160 // addresses. |
| 191 GuidMapIterator it = guid_map_.find(header.public_header.guid); | 161 GuidMapIterator it = guid_map_.find(guid); |
| 192 DCHECK(it != guid_map_.end()); | 162 DCHECK(it != guid_map_.end()); |
| 193 // Increment the received packet count. | 163 // Increment the received packet count. |
| 194 ++((it->second).num_packets); | 164 ++((it->second).num_packets); |
| 195 if (!ShouldSendResponse((it->second).num_packets)) { | 165 if (!ShouldSendResponse((it->second).num_packets)) { |
| 196 return false; | 166 return; |
| 197 } | 167 } |
| 198 if (it->second.close_packet) { | 168 if (it->second.close_packet) { |
| 199 QueuedPacket* queued_packet = | 169 QueuedPacket* queued_packet = |
| 200 new QueuedPacket(server_address_, | 170 new QueuedPacket(server_address, |
| 201 client_address_, | 171 client_address, |
| 202 it->second.close_packet->Clone()); | 172 it->second.close_packet->Clone()); |
| 203 // Takes ownership of the packet. | 173 // Takes ownership of the packet. |
| 204 SendOrQueuePacket(queued_packet); | 174 SendOrQueuePacket(queued_packet); |
| 205 } else { | 175 } else { |
| 206 // We don't need the packet anymore. Just tell the client what sequence | 176 SendPublicReset(server_address, client_address, guid, sequence_number); |
| 207 // number we rejected. | |
| 208 SendPublicReset(server_address_, | |
| 209 client_address_, | |
| 210 header.public_header.guid, | |
| 211 header.packet_sequence_number); | |
| 212 } | 177 } |
| 213 // Never process the body of the packet in time wait state. | |
| 214 return false; | |
| 215 } | |
| 216 | |
| 217 bool QuicTimeWaitListManager::OnPacketHeader(const QuicPacketHeader& header) { | |
| 218 DCHECK(false); | |
| 219 return false; | |
| 220 } | |
| 221 | |
| 222 void QuicTimeWaitListManager::OnRevivedPacket() { | |
| 223 DCHECK(false); | |
| 224 } | |
| 225 | |
| 226 void QuicTimeWaitListManager::OnFecProtectedPayload(StringPiece /*payload*/) { | |
| 227 DCHECK(false); | |
| 228 } | |
| 229 | |
| 230 bool QuicTimeWaitListManager::OnStreamFrame(const QuicStreamFrame& /*frame*/) { | |
| 231 DCHECK(false); | |
| 232 return false; | |
| 233 } | |
| 234 | |
| 235 bool QuicTimeWaitListManager::OnAckFrame(const QuicAckFrame& /*frame*/) { | |
| 236 DCHECK(false); | |
| 237 return false; | |
| 238 } | |
| 239 | |
| 240 bool QuicTimeWaitListManager::OnCongestionFeedbackFrame( | |
| 241 const QuicCongestionFeedbackFrame& /*frame*/) { | |
| 242 DCHECK(false); | |
| 243 return false; | |
| 244 } | |
| 245 | |
| 246 bool QuicTimeWaitListManager::OnRstStreamFrame( | |
| 247 const QuicRstStreamFrame& /*frame*/) { | |
| 248 DCHECK(false); | |
| 249 return false; | |
| 250 } | |
| 251 | |
| 252 bool QuicTimeWaitListManager::OnConnectionCloseFrame( | |
| 253 const QuicConnectionCloseFrame & /*frame*/) { | |
| 254 DCHECK(false); | |
| 255 return false; | |
| 256 } | |
| 257 | |
| 258 bool QuicTimeWaitListManager::OnGoAwayFrame(const QuicGoAwayFrame& /*frame*/) { | |
| 259 DCHECK(false); | |
| 260 return false; | |
| 261 } | |
| 262 | |
| 263 void QuicTimeWaitListManager::OnFecData(const QuicFecData& /*fec*/) { | |
| 264 DCHECK(false); | |
| 265 } | 178 } |
| 266 | 179 |
| 267 // Returns true if the number of packets received for this guid is a power of 2 | 180 // Returns true if the number of packets received for this guid is a power of 2 |
| 268 // to throttle the number of public reset packets we send to a client. | 181 // to throttle the number of public reset packets we send to a client. |
| 269 bool QuicTimeWaitListManager::ShouldSendResponse(int received_packet_count) { | 182 bool QuicTimeWaitListManager::ShouldSendResponse(int received_packet_count) { |
| 270 return (received_packet_count & (received_packet_count - 1)) == 0; | 183 return (received_packet_count & (received_packet_count - 1)) == 0; |
| 271 } | 184 } |
| 272 | 185 |
| 273 void QuicTimeWaitListManager::SendPublicReset( | 186 void QuicTimeWaitListManager::SendPublicReset( |
| 274 const IPEndPoint& server_address, | 187 const IPEndPoint& server_address, |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 308 } | 221 } |
| 309 | 222 |
| 310 void QuicTimeWaitListManager::WriteToWire(QueuedPacket* queued_packet) { | 223 void QuicTimeWaitListManager::WriteToWire(QueuedPacket* queued_packet) { |
| 311 DCHECK(!is_write_blocked_); | 224 DCHECK(!is_write_blocked_); |
| 312 WriteResult result = writer_->WritePacket( | 225 WriteResult result = writer_->WritePacket( |
| 313 queued_packet->packet()->data(), | 226 queued_packet->packet()->data(), |
| 314 queued_packet->packet()->length(), | 227 queued_packet->packet()->length(), |
| 315 queued_packet->server_address().address(), | 228 queued_packet->server_address().address(), |
| 316 queued_packet->client_address(), | 229 queued_packet->client_address(), |
| 317 this); | 230 this); |
| 318 | |
| 319 if (result.status == WRITE_STATUS_BLOCKED) { | 231 if (result.status == WRITE_STATUS_BLOCKED) { |
| 320 is_write_blocked_ = true; | 232 is_write_blocked_ = true; |
| 321 } else if (result.status == WRITE_STATUS_ERROR) { | 233 } else if (result.status == WRITE_STATUS_ERROR) { |
| 322 LOG(WARNING) << "Received unknown error while sending reset packet to " | 234 LOG(WARNING) << "Received unknown error while sending reset packet to " |
| 323 << queued_packet->client_address().ToString() << ": " | 235 << queued_packet->client_address().ToString() << ": " |
| 324 << strerror(result.error_code); | 236 << strerror(result.error_code); |
| 325 } | 237 } |
| 326 } | 238 } |
| 327 | 239 |
| 328 void QuicTimeWaitListManager::SetGuidCleanUpAlarm() { | 240 void QuicTimeWaitListManager::SetGuidCleanUpAlarm() { |
| (...skipping 30 matching lines...) Expand all Loading... |
| 359 delete it->second.close_packet; | 271 delete it->second.close_packet; |
| 360 guid_map_.erase(oldest_guid->guid); | 272 guid_map_.erase(oldest_guid->guid); |
| 361 time_ordered_guid_list_.pop_front(); | 273 time_ordered_guid_list_.pop_front(); |
| 362 delete oldest_guid; | 274 delete oldest_guid; |
| 363 } | 275 } |
| 364 SetGuidCleanUpAlarm(); | 276 SetGuidCleanUpAlarm(); |
| 365 } | 277 } |
| 366 | 278 |
| 367 } // namespace tools | 279 } // namespace tools |
| 368 } // namespace net | 280 } // namespace net |
| OLD | NEW |