| 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_dispatcher.h" | 5 #include "net/tools/quic/quic_dispatcher.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/debug/stack_trace.h" | 9 #include "base/debug/stack_trace.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| 11 #include "base/stl_util.h" | 11 #include "base/stl_util.h" |
| 12 #include "net/quic/quic_flags.h" |
| 12 #include "net/quic/quic_utils.h" | 13 #include "net/quic/quic_utils.h" |
| 13 #include "net/tools/quic/quic_per_connection_packet_writer.h" | 14 #include "net/tools/quic/quic_per_connection_packet_writer.h" |
| 14 #include "net/tools/quic/quic_time_wait_list_manager.h" | 15 #include "net/tools/quic/quic_time_wait_list_manager.h" |
| 15 | 16 |
| 16 namespace net { | 17 namespace net { |
| 17 | 18 |
| 18 namespace tools { | 19 namespace tools { |
| 19 | 20 |
| 20 using std::make_pair; | 21 using std::make_pair; |
| 21 using base::StringPiece; | 22 using base::StringPiece; |
| 22 | 23 |
| 24 // The threshold size for the session map, over which the dispatcher will start |
| 25 // sending stateless rejects (SREJ), rather than stateful rejects (REJ) to |
| 26 // clients who support them. If -1, stateless rejects will not be sent. If 0, |
| 27 // the server will only send stateless rejects to clients who support them. |
| 28 int32 FLAGS_quic_session_map_threshold_for_stateless_rejects = -1; |
| 29 |
| 23 namespace { | 30 namespace { |
| 24 | 31 |
| 25 // An alarm that informs the QuicDispatcher to delete old sessions. | 32 // An alarm that informs the QuicDispatcher to delete old sessions. |
| 26 class DeleteSessionsAlarm : public QuicAlarm::Delegate { | 33 class DeleteSessionsAlarm : public QuicAlarm::Delegate { |
| 27 public: | 34 public: |
| 28 explicit DeleteSessionsAlarm(QuicDispatcher* dispatcher) | 35 explicit DeleteSessionsAlarm(QuicDispatcher* dispatcher) |
| 29 : dispatcher_(dispatcher) { | 36 : dispatcher_(dispatcher) { |
| 30 } | 37 } |
| 31 | 38 |
| 32 QuicTime OnAlarm() override { | 39 QuicTime OnAlarm() override { |
| (...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 283 QuicPacketFate fate = ValidityChecks(header); | 290 QuicPacketFate fate = ValidityChecks(header); |
| 284 switch (fate) { | 291 switch (fate) { |
| 285 case kFateProcess: { | 292 case kFateProcess: { |
| 286 // Create a session and process the packet. | 293 // Create a session and process the packet. |
| 287 QuicServerSession* session = CreateQuicSession( | 294 QuicServerSession* session = CreateQuicSession( |
| 288 connection_id, current_server_address_, current_client_address_); | 295 connection_id, current_server_address_, current_client_address_); |
| 289 DVLOG(1) << "Created new session for " << connection_id; | 296 DVLOG(1) << "Created new session for " << connection_id; |
| 290 session_map_.insert(make_pair(connection_id, session)); | 297 session_map_.insert(make_pair(connection_id, session)); |
| 291 session->connection()->ProcessUdpPacket( | 298 session->connection()->ProcessUdpPacket( |
| 292 current_server_address_, current_client_address_, *current_packet_); | 299 current_server_address_, current_client_address_, *current_packet_); |
| 300 |
| 301 if (FLAGS_enable_quic_stateless_reject_support && |
| 302 session->UsingStatelessRejectsIfPeerSupported() && |
| 303 session->PeerSupportsStatelessRejects() && |
| 304 !session->IsCryptoHandshakeConfirmed()) { |
| 305 DVLOG(1) << "Removing new session for " << connection_id |
| 306 << " because the session is in stateless reject mode and" |
| 307 << " encryption has not been established."; |
| 308 session->connection()->CloseConnection( |
| 309 QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT, /* from_peer */ false); |
| 310 } |
| 293 break; | 311 break; |
| 294 } | 312 } |
| 295 case kFateTimeWait: | 313 case kFateTimeWait: |
| 296 // Add this connection_id to the time-wait state, to safely reject | 314 // Add this connection_id to the time-wait state, to safely reject |
| 297 // future packets. | 315 // future packets. |
| 298 DVLOG(1) << "Adding connection ID " << connection_id | 316 DVLOG(1) << "Adding connection ID " << connection_id |
| 299 << "to time-wait list."; | 317 << "to time-wait list."; |
| 300 time_wait_list_manager_->AddConnectionIdToTimeWait( | 318 time_wait_list_manager_->AddConnectionIdToTimeWait( |
| 301 connection_id, framer_.version(), nullptr); | 319 connection_id, framer_.version(), |
| 320 /*connection_rejected_statelessly=*/false, nullptr); |
| 302 DCHECK(time_wait_list_manager_->IsConnectionIdInTimeWait( | 321 DCHECK(time_wait_list_manager_->IsConnectionIdInTimeWait( |
| 303 header.public_header.connection_id)); | 322 header.public_header.connection_id)); |
| 304 time_wait_list_manager_->ProcessPacket( | 323 time_wait_list_manager_->ProcessPacket( |
| 305 current_server_address_, current_client_address_, | 324 current_server_address_, current_client_address_, |
| 306 header.public_header.connection_id, header.packet_sequence_number, | 325 header.public_header.connection_id, header.packet_sequence_number, |
| 307 *current_packet_); | 326 *current_packet_); |
| 308 break; | 327 break; |
| 309 case kFateDrop: | 328 case kFateDrop: |
| 310 // Do nothing with the packet. | 329 // Do nothing with the packet. |
| 311 break; | 330 break; |
| (...skipping 24 matching lines...) Expand all Loading... |
| 336 // Check that the sequence numer is within the range that the client is | 355 // Check that the sequence numer is within the range that the client is |
| 337 // expected to send before receiving a response from the server. | 356 // expected to send before receiving a response from the server. |
| 338 if (header.packet_sequence_number == kInvalidPacketSequenceNumber || | 357 if (header.packet_sequence_number == kInvalidPacketSequenceNumber || |
| 339 header.packet_sequence_number > kMaxReasonableInitialSequenceNumber) { | 358 header.packet_sequence_number > kMaxReasonableInitialSequenceNumber) { |
| 340 return kFateTimeWait; | 359 return kFateTimeWait; |
| 341 } | 360 } |
| 342 | 361 |
| 343 return kFateProcess; | 362 return kFateProcess; |
| 344 } | 363 } |
| 345 | 364 |
| 346 void QuicDispatcher::CleanUpSession(SessionMap::iterator it) { | 365 void QuicDispatcher::CleanUpSession(SessionMap::iterator it, |
| 366 bool should_close_statelessly) { |
| 347 QuicConnection* connection = it->second->connection(); | 367 QuicConnection* connection = it->second->connection(); |
| 348 QuicEncryptedPacket* connection_close_packet = | 368 QuicEncryptedPacket* connection_close_packet = |
| 349 connection->ReleaseConnectionClosePacket(); | 369 connection->ReleaseConnectionClosePacket(); |
| 350 write_blocked_list_.erase(connection); | 370 write_blocked_list_.erase(connection); |
| 351 time_wait_list_manager_->AddConnectionIdToTimeWait(it->first, | 371 DCHECK(!should_close_statelessly || !connection_close_packet); |
| 352 connection->version(), | 372 time_wait_list_manager_->AddConnectionIdToTimeWait( |
| 353 connection_close_packet); | 373 it->first, connection->version(), should_close_statelessly, |
| 374 connection_close_packet); |
| 354 session_map_.erase(it); | 375 session_map_.erase(it); |
| 355 } | 376 } |
| 356 | 377 |
| 357 void QuicDispatcher::DeleteSessions() { | 378 void QuicDispatcher::DeleteSessions() { |
| 358 STLDeleteElements(&closed_session_list_); | 379 STLDeleteElements(&closed_session_list_); |
| 359 } | 380 } |
| 360 | 381 |
| 361 void QuicDispatcher::OnCanWrite() { | 382 void QuicDispatcher::OnCanWrite() { |
| 362 // The socket is now writable. | 383 // The socket is now writable. |
| 363 writer_->SetWritable(); | 384 writer_->SetWritable(); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 400 DVLOG_IF(1, error != QUIC_NO_ERROR) << "Closing connection (" | 421 DVLOG_IF(1, error != QUIC_NO_ERROR) << "Closing connection (" |
| 401 << connection_id | 422 << connection_id |
| 402 << ") due to error: " | 423 << ") due to error: " |
| 403 << QuicUtils::ErrorToString(error); | 424 << QuicUtils::ErrorToString(error); |
| 404 | 425 |
| 405 if (closed_session_list_.empty()) { | 426 if (closed_session_list_.empty()) { |
| 406 delete_sessions_alarm_->Cancel(); | 427 delete_sessions_alarm_->Cancel(); |
| 407 delete_sessions_alarm_->Set(helper()->GetClock()->ApproximateNow()); | 428 delete_sessions_alarm_->Set(helper()->GetClock()->ApproximateNow()); |
| 408 } | 429 } |
| 409 closed_session_list_.push_back(it->second); | 430 closed_session_list_.push_back(it->second); |
| 410 CleanUpSession(it); | 431 const bool should_close_statelessly = |
| 432 (error == QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT); |
| 433 CleanUpSession(it, should_close_statelessly); |
| 411 } | 434 } |
| 412 | 435 |
| 413 void QuicDispatcher::OnWriteBlocked( | 436 void QuicDispatcher::OnWriteBlocked( |
| 414 QuicBlockedWriterInterface* blocked_writer) { | 437 QuicBlockedWriterInterface* blocked_writer) { |
| 415 if (!writer_->IsWriteBlocked()) { | 438 if (!writer_->IsWriteBlocked()) { |
| 416 LOG(DFATAL) << | 439 LOG(DFATAL) << |
| 417 "QuicDispatcher::OnWriteBlocked called when the writer is not blocked."; | 440 "QuicDispatcher::OnWriteBlocked called when the writer is not blocked."; |
| 418 // Return without adding the connection to the blocked list, to avoid | 441 // Return without adding the connection to the blocked list, to avoid |
| 419 // infinite loops in OnCanWrite. | 442 // infinite loops in OnCanWrite. |
| 420 return; | 443 return; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 437 const IPEndPoint& server_address, | 460 const IPEndPoint& server_address, |
| 438 const IPEndPoint& client_address) { | 461 const IPEndPoint& client_address) { |
| 439 // The QuicServerSession takes ownership of |connection| below. | 462 // The QuicServerSession takes ownership of |connection| below. |
| 440 QuicConnection* connection = new QuicConnection( | 463 QuicConnection* connection = new QuicConnection( |
| 441 connection_id, client_address, helper_.get(), connection_writer_factory_, | 464 connection_id, client_address, helper_.get(), connection_writer_factory_, |
| 442 /* owns_writer= */ true, Perspective::IS_SERVER, | 465 /* owns_writer= */ true, Perspective::IS_SERVER, |
| 443 crypto_config_->HasProofSource(), supported_versions_); | 466 crypto_config_->HasProofSource(), supported_versions_); |
| 444 | 467 |
| 445 QuicServerSession* session = new QuicServerSession(config_, connection, this); | 468 QuicServerSession* session = new QuicServerSession(config_, connection, this); |
| 446 session->InitializeSession(crypto_config_); | 469 session->InitializeSession(crypto_config_); |
| 470 if (FLAGS_quic_session_map_threshold_for_stateless_rejects != -1 && |
| 471 session_map_.size() >= |
| 472 static_cast<size_t>( |
| 473 FLAGS_quic_session_map_threshold_for_stateless_rejects)) { |
| 474 session->set_use_stateless_rejects_if_peer_supported(true); |
| 475 } |
| 447 return session; | 476 return session; |
| 448 } | 477 } |
| 449 | 478 |
| 450 QuicTimeWaitListManager* QuicDispatcher::CreateQuicTimeWaitListManager() { | 479 QuicTimeWaitListManager* QuicDispatcher::CreateQuicTimeWaitListManager() { |
| 451 return new QuicTimeWaitListManager( | 480 return new QuicTimeWaitListManager( |
| 452 writer_.get(), this, helper_.get(), supported_versions()); | 481 writer_.get(), this, helper_.get(), supported_versions()); |
| 453 } | 482 } |
| 454 | 483 |
| 455 bool QuicDispatcher::HandlePacketForTimeWait( | 484 bool QuicDispatcher::HandlePacketForTimeWait( |
| 456 const QuicPacketPublicHeader& header) { | 485 const QuicPacketPublicHeader& header) { |
| 457 if (header.reset_flag) { | 486 if (header.reset_flag) { |
| 458 // Public reset packets do not have sequence numbers, so ignore the packet. | 487 // Public reset packets do not have sequence numbers, so ignore the packet. |
| 459 return false; | 488 return false; |
| 460 } | 489 } |
| 461 | 490 |
| 462 // Switch the framer to the correct version, so that the sequence number can | 491 // Switch the framer to the correct version, so that the sequence number can |
| 463 // be parsed correctly. | 492 // be parsed correctly. |
| 464 framer_.set_version(time_wait_list_manager_->GetQuicVersionFromConnectionId( | 493 framer_.set_version(time_wait_list_manager_->GetQuicVersionFromConnectionId( |
| 465 header.connection_id)); | 494 header.connection_id)); |
| 466 | 495 |
| 467 // Continue parsing the packet to extract the sequence number. Then | 496 // Continue parsing the packet to extract the sequence number. Then |
| 468 // send it to the time wait manager in OnUnathenticatedHeader. | 497 // send it to the time wait manager in OnUnathenticatedHeader. |
| 469 return true; | 498 return true; |
| 470 } | 499 } |
| 471 | 500 |
| 472 } // namespace tools | 501 } // namespace tools |
| 473 } // namespace net | 502 } // namespace net |
| OLD | NEW |