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(header.public_header.versions.front(), | 720 StatelessRejector rejector( |
666 GetSupportedVersions(), crypto_config_, | 721 header.public_header.versions.front(), GetSupportedVersions(), |
667 &compressed_certs_cache_, helper()->GetClock(), | 722 crypto_config_, &compressed_certs_cache_, helper()->GetClock(), |
668 helper()->GetRandomGenerator(), | 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 |
676 current_server_address_, | 731 << "Have to drop packet because buffering non-chlo packet is " |
677 current_client_address_); | 732 "not supported while trying to do stateless reject. " |
678 return kFateDrop; | 733 "--gfe2_reloadable_flag_quic_buffer_packet_till_chlo false" |
| 734 " --gfe2_reloadable_flag_quic_use_cheap_stateless_rejects true"; |
| 735 return kFateDrop; |
| 736 } |
| 737 return kFateBuffer; |
679 } | 738 } |
680 | 739 |
681 if (!validator.can_accept()) { | 740 if (!validator.can_accept()) { |
682 // This CHLO is prohibited by policy. | 741 // This CHLO is prohibited by policy. |
683 StatelessConnectionTerminator terminator(connection_id, &framer_, helper(), | 742 StatelessConnectionTerminator terminator(connection_id, &framer_, helper(), |
684 time_wait_list_manager_.get()); | 743 time_wait_list_manager_.get()); |
685 terminator.CloseConnection(QUIC_HANDSHAKE_FAILED, | 744 terminator.CloseConnection(QUIC_HANDSHAKE_FAILED, |
686 validator.error_details()); | 745 validator.error_details()); |
687 OnConnectionClosedStatelessly(QUIC_HANDSHAKE_FAILED); | 746 OnConnectionClosedStatelessly(QUIC_HANDSHAKE_FAILED); |
688 return kFateTimeWait; | 747 return kFateTimeWait; |
(...skipping 30 matching lines...) Expand all Loading... |
719 | 778 |
720 QUIC_BUG << "Rejector has unknown invalid state."; | 779 QUIC_BUG << "Rejector has unknown invalid state."; |
721 return kFateDrop; | 780 return kFateDrop; |
722 } | 781 } |
723 | 782 |
724 const QuicVersionVector& QuicDispatcher::GetSupportedVersions() { | 783 const QuicVersionVector& QuicDispatcher::GetSupportedVersions() { |
725 return version_manager_->GetSupportedVersions(); | 784 return version_manager_->GetSupportedVersions(); |
726 } | 785 } |
727 | 786 |
728 } // namespace net | 787 } // namespace net |
OLD | NEW |