1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "net/quic/quic_dispatcher.h" 6 7 #include <errno.h> 8 9 #include "base/debug/stack_trace.h" 10 #include "base/logging.h" 11 #include "base/stl_util.h" 12 #include "net/quic/quic_blocked_writer_interface.h" 13 #include "net/quic/quic_connection_helper.h" 14 #include "net/quic/quic_flags.h" 15 #include "net/quic/quic_time_wait_list_manager.h" 16 #include "net/quic/quic_utils.h" 17 18 namespace net { 19 20 using base::StringPiece; 21 using std::make_pair; 22 using std::find; 23 24 class DeleteSessionsAlarm : public QuicAlarm::Delegate { 25 public: 26 explicit DeleteSessionsAlarm(QuicDispatcher* dispatcher) 27 : dispatcher_(dispatcher) { 28 } 29 30 virtual QuicTime OnAlarm() OVERRIDE { 31 dispatcher_->DeleteSessions(); 32 return QuicTime::Zero(); 33 } 34 35 private: 36 QuicDispatcher* dispatcher_; 37 }; 38 39 class QuicDispatcher::QuicFramerVisitor : public QuicFramerVisitorInterface { 40 public: 41 explicit QuicFramerVisitor(QuicDispatcher* dispatcher) 42 : dispatcher_(dispatcher), 43 connection_id_(0) {} 44 45 // QuicFramerVisitorInterface implementation 46 virtual void OnPacket() OVERRIDE {} 47 virtual bool OnUnauthenticatedPublicHeader( 48 const QuicPacketPublicHeader& header) OVERRIDE { 49 connection_id_ = header.connection_id; 50 return dispatcher_->OnUnauthenticatedPublicHeader(header); 51 } 52 virtual bool OnUnauthenticatedHeader( 53 const QuicPacketHeader& header) OVERRIDE { 54 dispatcher_->OnUnauthenticatedHeader(header); 55 return false; 56 } 57 virtual void OnError(QuicFramer* framer) OVERRIDE { 58 DVLOG(1) << QuicUtils::ErrorToString(framer->error()); 59 } 60 61 virtual bool OnProtocolVersionMismatch( 62 QuicVersion /*received_version*/) OVERRIDE { 63 if (dispatcher_->time_wait_list_manager()->IsConnectionIdInTimeWait( 64 connection_id_)) { 65 // Keep processing after protocol mismatch - this will be dealt with by 66 // the TimeWaitListManager. 67 return true; 68 } else { 69 DLOG(DFATAL) << "Version mismatch, connection ID (" << connection_id_ 70 << ") not in time wait list."; 71 return false; 72 } 73 } 74 75 // The following methods should never get called because we always return 76 // false from OnUnauthenticatedHeader(). As a result, we never process the 77 // payload of the packet. 78 virtual void OnPublicResetPacket( 79 const QuicPublicResetPacket& /*packet*/) OVERRIDE { 80 DCHECK(false); 81 } 82 virtual void OnVersionNegotiationPacket( 83 const QuicVersionNegotiationPacket& /*packet*/) OVERRIDE { 84 DCHECK(false); 85 } 86 virtual void OnDecryptedPacket(EncryptionLevel level) OVERRIDE { 87 DCHECK(false); 88 } 89 virtual bool OnPacketHeader(const QuicPacketHeader& /*header*/) OVERRIDE { 90 DCHECK(false); 91 return false; 92 } 93 virtual void OnRevivedPacket() OVERRIDE { 94 DCHECK(false); 95 } 96 virtual void OnFecProtectedPayload(StringPiece /*payload*/) OVERRIDE { 97 DCHECK(false); 98 } 99 virtual bool OnStreamFrame(const QuicStreamFrame& /*frame*/) OVERRIDE { 100 DCHECK(false); 101 return false; 102 } 103 virtual bool OnAckFrame(const QuicAckFrame& /*frame*/) OVERRIDE { 104 DCHECK(false); 105 return false; 106 } 107 virtual bool OnCongestionFeedbackFrame( 108 const QuicCongestionFeedbackFrame& /*frame*/) OVERRIDE { 109 DCHECK(false); 110 return false; 111 } 112 virtual bool OnStopWaitingFrame( 113 const QuicStopWaitingFrame& /*frame*/) OVERRIDE { 114 DCHECK(false); 115 return false; 116 } 117 virtual bool OnPingFrame(const QuicPingFrame& /*frame*/) OVERRIDE { 118 DCHECK(false); 119 return false; 120 } 121 virtual bool OnRstStreamFrame(const QuicRstStreamFrame& /*frame*/) OVERRIDE { 122 DCHECK(false); 123 return false; 124 } 125 virtual bool OnConnectionCloseFrame( 126 const QuicConnectionCloseFrame & /*frame*/) OVERRIDE { 127 DCHECK(false); 128 return false; 129 } 130 virtual bool OnGoAwayFrame(const QuicGoAwayFrame& /*frame*/) OVERRIDE { 131 DCHECK(false); 132 return false; 133 } 134 virtual bool OnWindowUpdateFrame(const QuicWindowUpdateFrame& /*frame*/) 135 OVERRIDE { 136 DCHECK(false); 137 return false; 138 } 139 virtual bool OnBlockedFrame(const QuicBlockedFrame& frame) OVERRIDE { 140 DCHECK(false); 141 return false; 142 } 143 virtual void OnFecData(const QuicFecData& /*fec*/) OVERRIDE { 144 DCHECK(false); 145 } 146 virtual void OnPacketComplete() OVERRIDE { 147 DCHECK(false); 148 } 149 150 private: 151 QuicDispatcher* dispatcher_; 152 153 // Latched in OnUnauthenticatedPublicHeader for use later. 154 QuicConnectionId connection_id_; 155 }; 156 157 QuicDispatcher::QuicDispatcher(const QuicConfig& config, 158 const QuicCryptoServerConfig& crypto_config, 159 const QuicVersionVector& supported_versions, 160 QuicConnectionHelperInterface* helper) 161 : config_(config), 162 crypto_config_(crypto_config), 163 helper_(helper), 164 delete_sessions_alarm_( 165 helper_->CreateAlarm(new DeleteSessionsAlarm(this))), 166 supported_versions_(supported_versions), 167 supported_versions_no_flow_control_(supported_versions), 168 supported_versions_no_connection_flow_control_(supported_versions), 169 current_packet_(NULL), 170 framer_(supported_versions, /*unused*/ QuicTime::Zero(), true), 171 framer_visitor_(new QuicFramerVisitor(this)) { 172 framer_.set_visitor(framer_visitor_.get()); 173 } 174 175 QuicDispatcher::~QuicDispatcher() { 176 STLDeleteValues(&session_map_); 177 STLDeleteElements(&closed_session_list_); 178 } 179 180 void QuicDispatcher::Initialize(QuicPacketWriter* writer) { 181 DCHECK(writer_ == NULL); 182 writer_.reset(writer); 183 time_wait_list_manager_.reset(CreateQuicTimeWaitListManager()); 184 185 // Remove all versions > QUIC_VERSION_16 from the 186 // supported_versions_no_flow_control_ vector. 187 QuicVersionVector::iterator it = 188 find(supported_versions_no_flow_control_.begin(), 189 supported_versions_no_flow_control_.end(), QUIC_VERSION_17); 190 if (it != supported_versions_no_flow_control_.end()) { 191 supported_versions_no_flow_control_.erase( 192 supported_versions_no_flow_control_.begin(), it + 1); 193 } 194 CHECK(!supported_versions_no_flow_control_.empty()); 195 196 // Remove all versions > QUIC_VERSION_18 from the 197 // supported_versions_no_connection_flow_control_ vector. 198 QuicVersionVector::iterator connection_it = 199 find(supported_versions_no_connection_flow_control_.begin(), 200 supported_versions_no_connection_flow_control_.end(), 201 QUIC_VERSION_19); 202 if (connection_it != supported_versions_no_connection_flow_control_.end()) { 203 supported_versions_no_connection_flow_control_.erase( 204 supported_versions_no_connection_flow_control_.begin(), 205 connection_it + 1); 206 } 207 CHECK(!supported_versions_no_connection_flow_control_.empty()); 208 } 209 210 void QuicDispatcher::ProcessPacket(const IPEndPoint& server_address, 211 const IPEndPoint& client_address, 212 const QuicEncryptedPacket& packet) { 213 current_server_address_ = server_address; 214 current_client_address_ = client_address; 215 current_packet_ = &packet; 216 // ProcessPacket will cause the packet to be dispatched in 217 // OnUnauthenticatedPublicHeader, or sent to the time wait list manager 218 // in OnAuthenticatedHeader. 219 framer_.ProcessPacket(packet); 220 // TODO(rjshade): Return a status describing if/why a packet was dropped, 221 // and log somehow. Maybe expose as a varz. 222 } 223 224 bool QuicDispatcher::OnUnauthenticatedPublicHeader( 225 const QuicPacketPublicHeader& header) { 226 QuicSession* session = NULL; 227 228 QuicConnectionId connection_id = header.connection_id; 229 SessionMap::iterator it = session_map_.find(connection_id); 230 if (it == session_map_.end()) { 231 if (header.reset_flag) { 232 return false; 233 } 234 if (time_wait_list_manager_->IsConnectionIdInTimeWait(connection_id)) { 235 return HandlePacketForTimeWait(header); 236 } 237 238 // Ensure the packet has a version negotiation bit set before creating a new 239 // session for it. All initial packets for a new connection are required to 240 // have the flag set. Otherwise it may be a stray packet. 241 if (header.version_flag) { 242 session = CreateQuicSession(connection_id, current_server_address_, 243 current_client_address_); 244 } 245 246 if (session == NULL) { 247 DVLOG(1) << "Failed to create session for " << connection_id; 248 // Add this connection_id fo the time-wait state, to safely reject future 249 // packets. 250 251 if (header.version_flag && 252 !framer_.IsSupportedVersion(header.versions.front())) { 253 // TODO(ianswett): Produce a no-version version negotiation packet. 254 return false; 255 } 256 257 // Use the version in the packet if possible, otherwise assume the latest. 258 QuicVersion version = header.version_flag ? header.versions.front() : 259 supported_versions_.front(); 260 time_wait_list_manager_->AddConnectionIdToTimeWait( 261 connection_id, version, NULL); 262 DCHECK(time_wait_list_manager_->IsConnectionIdInTimeWait(connection_id)); 263 return HandlePacketForTimeWait(header); 264 } 265 DVLOG(1) << "Created new session for " << connection_id; 266 session_map_.insert(make_pair(connection_id, session)); 267 } else { 268 session = it->second; 269 } 270 271 session->connection()->ProcessUdpPacket( 272 current_server_address_, current_client_address_, *current_packet_); 273 274 // Do not parse the packet further. The session will process it completely. 275 return false; 276 } 277 278 void QuicDispatcher::OnUnauthenticatedHeader(const QuicPacketHeader& header) { 279 DCHECK(time_wait_list_manager_->IsConnectionIdInTimeWait( 280 header.public_header.connection_id)); 281 time_wait_list_manager_->ProcessPacket(current_server_address_, 282 current_client_address_, 283 header.public_header.connection_id, 284 header.packet_sequence_number, 285 *current_packet_); 286 } 287 288 void QuicDispatcher::CleanUpSession(SessionMap::iterator it) { 289 QuicConnection* connection = it->second->connection(); 290 QuicEncryptedPacket* connection_close_packet = 291 connection->ReleaseConnectionClosePacket(); 292 write_blocked_list_.erase(connection); 293 time_wait_list_manager_->AddConnectionIdToTimeWait(it->first, 294 connection->version(), 295 connection_close_packet); 296 session_map_.erase(it); 297 } 298 299 void QuicDispatcher::DeleteSessions() { 300 STLDeleteElements(&closed_session_list_); 301 } 302 303 void QuicDispatcher::OnCanWrite() { 304 // We got an EPOLLOUT: the socket should not be blocked. 305 writer_->SetWritable(); 306 307 // Give each writer one attempt to write. 308 int num_writers = write_blocked_list_.size(); 309 for (int i = 0; i < num_writers; ++i) { 310 if (write_blocked_list_.empty()) { 311 return; 312 } 313 QuicBlockedWriterInterface* blocked_writer = 314 write_blocked_list_.begin()->first; 315 write_blocked_list_.erase(write_blocked_list_.begin()); 316 blocked_writer->OnCanWrite(); 317 if (writer_->IsWriteBlocked()) { 318 // We were unable to write. Wait for the next EPOLLOUT. The writer is 319 // responsible for adding itself to the blocked list via OnWriteBlocked(). 320 return; 321 } 322 } 323 } 324 325 bool QuicDispatcher::HasPendingWrites() const { 326 return !write_blocked_list_.empty(); 327 } 328 329 void QuicDispatcher::Shutdown() { 330 while (!session_map_.empty()) { 331 QuicSession* session = session_map_.begin()->second; 332 session->connection()->SendConnectionClose(QUIC_PEER_GOING_AWAY); 333 // Validate that the session removes itself from the session map on close. 334 DCHECK(session_map_.empty() || session_map_.begin()->second != session); 335 } 336 DeleteSessions(); 337 } 338 339 void QuicDispatcher::OnConnectionClosed(QuicConnectionId connection_id, 340 QuicErrorCode error) { 341 SessionMap::iterator it = session_map_.find(connection_id); 342 if (it == session_map_.end()) { 343 LOG(DFATAL) << "ConnectionId " << connection_id 344 << " does not exist in the session map. " 345 << "Error: " << QuicUtils::ErrorToString(error); 346 LOG(DFATAL) << base::debug::StackTrace().ToString(); 347 return; 348 } 349 DVLOG_IF(1, error != QUIC_NO_ERROR) << "Closing connection (" 350 << connection_id 351 << ") due to error: " 352 << QuicUtils::ErrorToString(error); 353 if (closed_session_list_.empty()) { 354 delete_sessions_alarm_->Set(helper_->GetClock()->ApproximateNow()); 355 } 356 closed_session_list_.push_back(it->second); 357 CleanUpSession(it); 358 } 359 360 void QuicDispatcher::OnWriteBlocked(QuicBlockedWriterInterface* writer) { 361 DCHECK(writer_->IsWriteBlocked()); 362 write_blocked_list_.insert(make_pair(writer, true)); 363 } 364 365 QuicSession* QuicDispatcher::CreateQuicSession( 366 QuicConnectionId connection_id, 367 const IPEndPoint& server_address, 368 const IPEndPoint& client_address) { 369 QuicServerSession* session = new QuicServerSession( 370 config_, 371 CreateQuicConnection(connection_id, server_address, client_address), 372 this); 373 session->InitializeSession(crypto_config_); 374 return session; 375 } 376 377 QuicConnection* QuicDispatcher::CreateQuicConnection( 378 QuicConnectionId connection_id, 379 const IPEndPoint& server_address, 380 const IPEndPoint& client_address) { 381 if (FLAGS_enable_quic_stream_flow_control_2 && 382 FLAGS_enable_quic_connection_flow_control_2) { 383 DVLOG(1) << "Creating QuicDispatcher with all versions."; 384 return new QuicConnection(connection_id, client_address, helper_, 385 writer_.get(), true, supported_versions_); 386 } 387 388 if (FLAGS_enable_quic_stream_flow_control_2 && 389 !FLAGS_enable_quic_connection_flow_control_2) { 390 DVLOG(1) << "Connection flow control disabled, creating QuicDispatcher " 391 << "WITHOUT version 19 or higher."; 392 return new QuicConnection(connection_id, client_address, helper_, 393 writer_.get(), true, 394 supported_versions_no_connection_flow_control_); 395 } 396 397 DVLOG(1) << "Flow control disabled, creating QuicDispatcher WITHOUT " 398 << "version 17 or higher."; 399 return new QuicConnection(connection_id, client_address, helper_, 400 writer_.get(), true, 401 supported_versions_no_flow_control_); 402 } 403 404 QuicTimeWaitListManager* QuicDispatcher::CreateQuicTimeWaitListManager() { 405 return new QuicTimeWaitListManager( 406 writer_.get(), this, helper_, supported_versions()); 407 } 408 409 bool QuicDispatcher::HandlePacketForTimeWait( 410 const QuicPacketPublicHeader& header) { 411 if (header.reset_flag) { 412 // Public reset packets do not have sequence numbers, so ignore the packet. 413 return false; 414 } 415 416 // Switch the framer to the correct version, so that the sequence number can 417 // be parsed correctly. 418 framer_.set_version(time_wait_list_manager_->GetQuicVersionFromConnectionId( 419 header.connection_id)); 420 421 // Continue parsing the packet to extract the sequence number. Then 422 // send it to the time wait manager in OnUnathenticatedHeader. 423 return true; 424 } 425 426 } // namespace net 427