| 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/macros.h" | 11 #include "base/macros.h" |
| 12 #include "base/stl_util.h" | 12 #include "base/stl_util.h" |
| 13 #include "net/quic/core/crypto/quic_random.h" | 13 #include "net/quic/core/crypto/quic_random.h" |
| 14 #include "net/quic/core/quic_bug_tracker.h" | 14 #include "net/quic/core/quic_bug_tracker.h" |
| 15 #include "net/quic/core/quic_flags.h" | 15 #include "net/quic/core/quic_flags.h" |
| 16 #include "net/quic/core/quic_utils.h" | 16 #include "net/quic/core/quic_utils.h" |
| 17 #include "net/tools/quic/chlo_extractor.h" | 17 #include "net/tools/quic/chlo_extractor.h" |
| 18 #include "net/tools/quic/quic_per_connection_packet_writer.h" | 18 #include "net/tools/quic/quic_per_connection_packet_writer.h" |
| 19 #include "net/tools/quic/quic_simple_server_session.h" | 19 #include "net/tools/quic/quic_simple_server_session.h" |
| 20 #include "net/tools/quic/quic_time_wait_list_manager.h" | 20 #include "net/tools/quic/quic_time_wait_list_manager.h" |
| 21 #include "net/tools/quic/stateless_rejector.h" | 21 #include "net/tools/quic/stateless_rejector.h" |
| 22 | 22 |
| 23 using base::StringPiece; | 23 using base::StringPiece; |
| 24 using std::string; | 24 using std::string; |
| 25 | 25 |
| 26 namespace net { | 26 namespace net { |
| 27 | 27 |
| 28 typedef QuicBufferedPacketStore::BufferedPacket BufferedPacket; |
| 29 typedef QuicBufferedPacketStore::BufferedPacketList BufferedPacketList; |
| 30 typedef QuicBufferedPacketStore::EnqueuePacketResult EnqueuePacketResult; |
| 31 |
| 28 namespace { | 32 namespace { |
| 29 | 33 |
| 30 // An alarm that informs the QuicDispatcher to delete old sessions. | 34 // An alarm that informs the QuicDispatcher to delete old sessions. |
| 31 class DeleteSessionsAlarm : public QuicAlarm::Delegate { | 35 class DeleteSessionsAlarm : public QuicAlarm::Delegate { |
| 32 public: | 36 public: |
| 33 explicit DeleteSessionsAlarm(QuicDispatcher* dispatcher) | 37 explicit DeleteSessionsAlarm(QuicDispatcher* dispatcher) |
| 34 : dispatcher_(dispatcher) {} | 38 : dispatcher_(dispatcher) {} |
| 35 | 39 |
| 36 void OnAlarm() override { dispatcher_->DeleteSessions(); } | 40 void OnAlarm() override { dispatcher_->DeleteSessions(); } |
| 37 | 41 |
| (...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 320 } | 324 } |
| 321 | 325 |
| 322 // Packet's connection ID is unknown. | 326 // Packet's connection ID is unknown. |
| 323 // Apply the validity checks. | 327 // Apply the validity checks. |
| 324 QuicPacketFate fate = ValidityChecks(header); | 328 QuicPacketFate fate = ValidityChecks(header); |
| 325 if (fate == kFateProcess) { | 329 if (fate == kFateProcess) { |
| 326 fate = MaybeRejectStatelessly(connection_id, header); | 330 fate = MaybeRejectStatelessly(connection_id, header); |
| 327 } | 331 } |
| 328 switch (fate) { | 332 switch (fate) { |
| 329 case kFateProcess: { | 333 case kFateProcess: { |
| 330 // Create a session and process the packet. | 334 ProcessChlo(); |
| 331 QuicServerSessionBase* session = | |
| 332 CreateQuicSession(connection_id, current_client_address_); | |
| 333 DVLOG(1) << "Created new session for " << connection_id; | |
| 334 session_map_.insert(std::make_pair(connection_id, session)); | |
| 335 session->ProcessUdpPacket(current_server_address_, | |
| 336 current_client_address_, *current_packet_); | |
| 337 std::list<QuicBufferedPacketStore::BufferedPacket> packets = | |
| 338 buffered_packets_.DeliverPackets(connection_id); | |
| 339 for (const auto& packet : packets) { | |
| 340 SessionMap::iterator it = session_map_.find(connection_id); | |
| 341 if (it == session_map_.end()) { | |
| 342 break; | |
| 343 } | |
| 344 it->second->ProcessUdpPacket(packet.server_address, | |
| 345 packet.client_address, *packet.packet); | |
| 346 } | |
| 347 break; | 335 break; |
| 348 } | 336 } |
| 349 case kFateTimeWait: | 337 case kFateTimeWait: |
| 350 // MaybeRejectStatelessly might have already added the connection to | 338 // MaybeRejectStatelessly might have already added the connection to |
| 351 // time wait, in which case it should not be added again. | 339 // time wait, in which case it should not be added again. |
| 352 if (!FLAGS_quic_use_cheap_stateless_rejects || | 340 if (!FLAGS_quic_use_cheap_stateless_rejects || |
| 353 !time_wait_list_manager_->IsConnectionIdInTimeWait( | 341 !time_wait_list_manager_->IsConnectionIdInTimeWait( |
| 354 header.public_header.connection_id)) { | 342 header.public_header.connection_id)) { |
| 355 // Add this connection_id to the time-wait state, to safely reject | 343 // Add this connection_id to the time-wait state, to safely reject |
| 356 // future packets. | 344 // future packets. |
| 357 DVLOG(1) << "Adding connection ID " << connection_id | 345 DVLOG(1) << "Adding connection ID " << connection_id |
| 358 << "to time-wait list."; | 346 << "to time-wait list."; |
| 359 time_wait_list_manager_->AddConnectionIdToTimeWait( | 347 time_wait_list_manager_->AddConnectionIdToTimeWait( |
| 360 connection_id, framer_.version(), | 348 connection_id, framer_.version(), |
| 361 /*connection_rejected_statelessly=*/false, nullptr); | 349 /*connection_rejected_statelessly=*/false, nullptr); |
| 362 } | 350 } |
| 363 DCHECK(time_wait_list_manager_->IsConnectionIdInTimeWait( | 351 DCHECK(time_wait_list_manager_->IsConnectionIdInTimeWait( |
| 364 header.public_header.connection_id)); | 352 header.public_header.connection_id)); |
| 365 time_wait_list_manager_->ProcessPacket( | 353 time_wait_list_manager_->ProcessPacket( |
| 366 current_server_address_, current_client_address_, | 354 current_server_address_, current_client_address_, |
| 367 header.public_header.connection_id, header.packet_number, | 355 header.public_header.connection_id, header.packet_number, |
| 368 *current_packet_); | 356 *current_packet_); |
| 369 break; | 357 break; |
| 358 case kFateBuffer: |
| 359 // This packet is a non-CHLO packet which has arrived out of order. |
| 360 // Buffer it. |
| 361 BufferEarlyPacket(connection_id); |
| 362 break; |
| 370 case kFateDrop: | 363 case kFateDrop: |
| 371 // Do nothing with the packet. | 364 // Do nothing with the packet. |
| 372 break; | 365 break; |
| 373 } | 366 } |
| 374 | 367 |
| 375 return false; | 368 return false; |
| 376 } | 369 } |
| 377 | 370 |
| 378 QuicDispatcher::QuicPacketFate QuicDispatcher::ValidityChecks( | 371 QuicDispatcher::QuicPacketFate QuicDispatcher::ValidityChecks( |
| 379 const QuicPacketHeader& header) { | 372 const QuicPacketHeader& header) { |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 599 DCHECK(false); | 592 DCHECK(false); |
| 600 return false; | 593 return false; |
| 601 } | 594 } |
| 602 | 595 |
| 603 void QuicDispatcher::OnPacketComplete() { | 596 void QuicDispatcher::OnPacketComplete() { |
| 604 DCHECK(false); | 597 DCHECK(false); |
| 605 } | 598 } |
| 606 | 599 |
| 607 void QuicDispatcher::OnExpiredPackets( | 600 void QuicDispatcher::OnExpiredPackets( |
| 608 QuicConnectionId connection_id, | 601 QuicConnectionId connection_id, |
| 609 QuicBufferedPacketStore::BufferedPacketList early_arrived_packets) {} | 602 BufferedPacketList early_arrived_packets) { |
| 603 time_wait_list_manager_->AddConnectionIdToTimeWait( |
| 604 connection_id, framer_.version(), false, nullptr); |
| 605 } |
| 606 |
| 607 void QuicDispatcher::OnNewConnectionAdded(QuicConnectionId connection_id) { |
| 608 VLOG(1) << "Received packet from new connection " << connection_id; |
| 609 } |
| 610 |
| 611 // Return true if there is any packet buffered in the store. |
| 612 bool QuicDispatcher::HasBufferedPackets(QuicConnectionId connection_id) { |
| 613 return buffered_packets_.HasBufferedPackets(connection_id); |
| 614 } |
| 615 |
| 616 void QuicDispatcher::OnBufferPacketFailure(EnqueuePacketResult result, |
| 617 QuicConnectionId connection_id) { |
| 618 DVLOG(1) << "Fail to buffer packet on connection " << connection_id |
| 619 << " because of " << result; |
| 620 } |
| 610 | 621 |
| 611 void QuicDispatcher::OnConnectionRejectedStatelessly() {} | 622 void QuicDispatcher::OnConnectionRejectedStatelessly() {} |
| 612 | 623 |
| 613 void QuicDispatcher::OnConnectionClosedStatelessly(QuicErrorCode error) {} | 624 void QuicDispatcher::OnConnectionClosedStatelessly(QuicErrorCode error) {} |
| 614 | 625 |
| 615 bool QuicDispatcher::ShouldAttemptCheapStatelessRejection() { | 626 bool QuicDispatcher::ShouldAttemptCheapStatelessRejection() { |
| 616 return true; | 627 return true; |
| 617 } | 628 } |
| 618 | 629 |
| 619 QuicTimeWaitListManager* QuicDispatcher::CreateQuicTimeWaitListManager() { | 630 QuicTimeWaitListManager* QuicDispatcher::CreateQuicTimeWaitListManager() { |
| 620 return new QuicTimeWaitListManager(writer_.get(), this, helper_.get(), | 631 return new QuicTimeWaitListManager(writer_.get(), this, helper_.get(), |
| 621 alarm_factory_.get()); | 632 alarm_factory_.get()); |
| 622 } | 633 } |
| 623 | 634 |
| 635 void QuicDispatcher::BufferEarlyPacket(QuicConnectionId connection_id) { |
| 636 bool is_new_connection = !buffered_packets_.HasBufferedPackets(connection_id); |
| 637 EnqueuePacketResult rs = buffered_packets_.EnqueuePacket( |
| 638 connection_id, *current_packet_, current_server_address_, |
| 639 current_client_address_); |
| 640 if (rs != EnqueuePacketResult::SUCCESS) { |
| 641 OnBufferPacketFailure(rs, connection_id); |
| 642 } else if (is_new_connection) { |
| 643 OnNewConnectionAdded(connection_id); |
| 644 } |
| 645 } |
| 646 |
| 647 void QuicDispatcher::ProcessChlo() { |
| 648 // Creates a new session and process all buffered packets for this connection. |
| 649 QuicServerSessionBase* session = |
| 650 CreateQuicSession(current_connection_id_, current_client_address_); |
| 651 DVLOG(1) << "Created new session for " << current_connection_id_; |
| 652 session_map_.insert(std::make_pair(current_connection_id_, session)); |
| 653 std::list<BufferedPacket> packets = |
| 654 buffered_packets_.DeliverPackets(current_connection_id_); |
| 655 // Check if CHLO is the first packet arrived on this connection. |
| 656 if (FLAGS_quic_buffer_packet_till_chlo && packets.empty()) { |
| 657 OnNewConnectionAdded(current_connection_id_); |
| 658 } |
| 659 // Process CHLO at first. |
| 660 session->ProcessUdpPacket(current_server_address_, current_client_address_, |
| 661 *current_packet_); |
| 662 |
| 663 // Deliver queued-up packets in the same order as they arrived. |
| 664 // Do this even when flag is off because there might be still some packets |
| 665 // buffered in the store before flag is turned off. |
| 666 for (const BufferedPacket& packet : packets) { |
| 667 session->ProcessUdpPacket(packet.server_address, packet.client_address, |
| 668 *(packet.packet)); |
| 669 } |
| 670 } |
| 671 |
| 624 bool QuicDispatcher::HandlePacketForTimeWait( | 672 bool QuicDispatcher::HandlePacketForTimeWait( |
| 625 const QuicPacketPublicHeader& header) { | 673 const QuicPacketPublicHeader& header) { |
| 626 if (header.reset_flag) { | 674 if (header.reset_flag) { |
| 627 // Public reset packets do not have packet numbers, so ignore the packet. | 675 // Public reset packets do not have packet numbers, so ignore the packet. |
| 628 return false; | 676 return false; |
| 629 } | 677 } |
| 630 | 678 |
| 631 // Switch the framer to the correct version, so that the packet number can | 679 // Switch the framer to the correct version, so that the packet number can |
| 632 // be parsed correctly. | 680 // be parsed correctly. |
| 633 framer_.set_version(time_wait_list_manager_->GetQuicVersionFromConnectionId( | 681 framer_.set_version(time_wait_list_manager_->GetQuicVersionFromConnectionId( |
| (...skipping 18 matching lines...) Expand all Loading... |
| 652 } | 700 } |
| 653 | 701 |
| 654 QuicDispatcher::QuicPacketFate QuicDispatcher::MaybeRejectStatelessly( | 702 QuicDispatcher::QuicPacketFate QuicDispatcher::MaybeRejectStatelessly( |
| 655 QuicConnectionId connection_id, | 703 QuicConnectionId connection_id, |
| 656 const QuicPacketHeader& header) { | 704 const QuicPacketHeader& header) { |
| 657 // TODO(rch): This logic should probably live completely inside the rejector. | 705 // TODO(rch): This logic should probably live completely inside the rejector. |
| 658 if (!FLAGS_quic_use_cheap_stateless_rejects || | 706 if (!FLAGS_quic_use_cheap_stateless_rejects || |
| 659 !FLAGS_enable_quic_stateless_reject_support || | 707 !FLAGS_enable_quic_stateless_reject_support || |
| 660 header.public_header.versions.front() <= QUIC_VERSION_32 || | 708 header.public_header.versions.front() <= QUIC_VERSION_32 || |
| 661 !ShouldAttemptCheapStatelessRejection()) { | 709 !ShouldAttemptCheapStatelessRejection()) { |
| 710 // Not use cheap stateless reject. |
| 711 if (FLAGS_quic_buffer_packet_till_chlo && |
| 712 !ChloExtractor::Extract(*current_packet_, GetSupportedVersions(), |
| 713 nullptr)) { |
| 714 // Buffer non-CHLO packets. |
| 715 return kFateBuffer; |
| 716 } |
| 662 return kFateProcess; | 717 return kFateProcess; |
| 663 } | 718 } |
| 664 | 719 |
| 665 StatelessRejector rejector( | 720 StatelessRejector rejector( |
| 666 header.public_header.versions.front(), GetSupportedVersions(), | 721 header.public_header.versions.front(), GetSupportedVersions(), |
| 667 crypto_config_, &compressed_certs_cache_, helper()->GetClock(), | 722 crypto_config_, &compressed_certs_cache_, helper()->GetClock(), |
| 668 helper()->GetRandomGenerator(), current_packet_->length(), | 723 helper()->GetRandomGenerator(), current_packet_->length(), |
| 669 current_client_address_, current_server_address_); | 724 current_client_address_, current_server_address_); |
| 670 ChloValidator validator(session_helper_.get(), current_server_address_, | 725 ChloValidator validator(session_helper_.get(), current_server_address_, |
| 671 &rejector); | 726 &rejector); |
| 672 if (!ChloExtractor::Extract(*current_packet_, GetSupportedVersions(), | 727 if (!ChloExtractor::Extract(*current_packet_, GetSupportedVersions(), |
| 673 &validator)) { | 728 &validator)) { |
| 674 DVLOG(1) << "Buffering undecryptable packet."; | 729 if (!FLAGS_quic_buffer_packet_till_chlo) { |
| 675 buffered_packets_.EnqueuePacket(connection_id, *current_packet_, | 730 QUIC_BUG << "Have to drop packet because buffering non-chlo packet is " |
| 676 current_server_address_, | 731 "not supported while trying to do stateless reject. " |
| 677 current_client_address_); | 732 << "--gfe2_reloadable_flag_quic_buffer_packet_till_chlo " |
| 678 return kFateDrop; | 733 << FLAGS_quic_buffer_packet_till_chlo |
| 734 << " --gfe2_reloadable_flag_quic_use_cheap_stateless_rejects " |
| 735 << FLAGS_quic_use_cheap_stateless_rejects; |
| 736 return kFateDrop; |
| 737 } |
| 738 return kFateBuffer; |
| 679 } | 739 } |
| 680 | 740 |
| 681 if (!validator.can_accept()) { | 741 if (!validator.can_accept()) { |
| 682 // This CHLO is prohibited by policy. | 742 // This CHLO is prohibited by policy. |
| 683 StatelessConnectionTerminator terminator(connection_id, &framer_, helper(), | 743 StatelessConnectionTerminator terminator(connection_id, &framer_, helper(), |
| 684 time_wait_list_manager_.get()); | 744 time_wait_list_manager_.get()); |
| 685 terminator.CloseConnection(QUIC_HANDSHAKE_FAILED, | 745 terminator.CloseConnection(QUIC_HANDSHAKE_FAILED, |
| 686 validator.error_details()); | 746 validator.error_details()); |
| 687 OnConnectionClosedStatelessly(QUIC_HANDSHAKE_FAILED); | 747 OnConnectionClosedStatelessly(QUIC_HANDSHAKE_FAILED); |
| 688 return kFateTimeWait; | 748 return kFateTimeWait; |
| (...skipping 30 matching lines...) Expand all Loading... |
| 719 | 779 |
| 720 QUIC_BUG << "Rejector has unknown invalid state."; | 780 QUIC_BUG << "Rejector has unknown invalid state."; |
| 721 return kFateDrop; | 781 return kFateDrop; |
| 722 } | 782 } |
| 723 | 783 |
| 724 const QuicVersionVector& QuicDispatcher::GetSupportedVersions() { | 784 const QuicVersionVector& QuicDispatcher::GetSupportedVersions() { |
| 725 return version_manager_->GetSupportedVersions(); | 785 return version_manager_->GetSupportedVersions(); |
| 726 } | 786 } |
| 727 | 787 |
| 728 } // namespace net | 788 } // namespace net |
| OLD | NEW |