Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(463)

Side by Side Diff: net/tools/quic/quic_dispatcher.cc

Issue 2322233004: Landing Recent QUIC changes until Sun Sep 4 03:41:00 (Closed)
Patch Set: Remove simulation files from the build. Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/tools/quic/quic_dispatcher.h ('k') | net/tools/quic/quic_dispatcher_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
17 #include "net/tools/quic/chlo_extractor.h" 18 #include "net/tools/quic/chlo_extractor.h"
18 #include "net/tools/quic/quic_per_connection_packet_writer.h" 19 #include "net/tools/quic/quic_per_connection_packet_writer.h"
19 #include "net/tools/quic/quic_simple_server_session.h" 20 #include "net/tools/quic/quic_simple_server_session.h"
21 #include "net/tools/quic/quic_simple_server_session.h"
20 #include "net/tools/quic/quic_time_wait_list_manager.h" 22 #include "net/tools/quic/quic_time_wait_list_manager.h"
21 #include "net/tools/quic/stateless_rejector.h" 23 #include "net/tools/quic/stateless_rejector.h"
22 24
23 using base::StringPiece; 25 using base::StringPiece;
24 using std::list; 26 using std::list;
25 using std::string; 27 using std::string;
26 28
27 namespace net { 29 namespace net {
28 30
29 typedef QuicBufferedPacketStore::BufferedPacket BufferedPacket; 31 typedef QuicBufferedPacketStore::BufferedPacket BufferedPacket;
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
148 // Set as the visitor of |creator_| to collect any generated packets. 150 // Set as the visitor of |creator_| to collect any generated packets.
149 PacketCollector collector_; 151 PacketCollector collector_;
150 QuicPacketCreator creator_; 152 QuicPacketCreator creator_;
151 QuicTimeWaitListManager* time_wait_list_manager_; 153 QuicTimeWaitListManager* time_wait_list_manager_;
152 }; 154 };
153 155
154 // Class which sits between the ChloExtractor and the StatelessRejector 156 // Class which sits between the ChloExtractor and the StatelessRejector
155 // to give the QuicDispatcher a chance to apply policy checks to the CHLO. 157 // to give the QuicDispatcher a chance to apply policy checks to the CHLO.
156 class ChloValidator : public ChloExtractor::Delegate { 158 class ChloValidator : public ChloExtractor::Delegate {
157 public: 159 public:
158 ChloValidator(QuicServerSessionBase::Helper* helper, 160 ChloValidator(QuicCryptoServerStream::Helper* helper,
159 IPEndPoint self_address, 161 IPEndPoint self_address,
160 StatelessRejector* rejector) 162 StatelessRejector* rejector)
161 : helper_(helper), 163 : helper_(helper),
162 self_address_(self_address), 164 self_address_(self_address),
163 rejector_(rejector), 165 rejector_(rejector),
164 can_accept_(false) {} 166 can_accept_(false) {}
165 167
166 // ChloExtractor::Delegate implementation. 168 // ChloExtractor::Delegate implementation.
167 void OnChlo(QuicVersion version, 169 void OnChlo(QuicVersion version,
168 QuicConnectionId connection_id, 170 QuicConnectionId connection_id,
169 const CryptoHandshakeMessage& chlo) override { 171 const CryptoHandshakeMessage& chlo) override {
170 if (helper_->CanAcceptClientHello(chlo, self_address_, &error_details_)) { 172 if (helper_->CanAcceptClientHello(chlo, self_address_, &error_details_)) {
171 can_accept_ = true; 173 can_accept_ = true;
172 rejector_->OnChlo(version, connection_id, 174 rejector_->OnChlo(version, connection_id,
173 helper_->GenerateConnectionIdForReject(connection_id), 175 helper_->GenerateConnectionIdForReject(connection_id),
174 chlo); 176 chlo);
175 } 177 }
176 } 178 }
177 179
178 bool can_accept() const { return can_accept_; } 180 bool can_accept() const { return can_accept_; }
179 181
180 const string& error_details() const { return error_details_; } 182 const string& error_details() const { return error_details_; }
181 183
182 private: 184 private:
183 QuicServerSessionBase::Helper* helper_; // Unowned. 185 QuicCryptoServerStream::Helper* helper_; // Unowned.
184 IPEndPoint self_address_; 186 IPEndPoint self_address_;
185 StatelessRejector* rejector_; // Unowned. 187 StatelessRejector* rejector_; // Unowned.
186 bool can_accept_; 188 bool can_accept_;
187 string error_details_; 189 string error_details_;
188 }; 190 };
189 191
190 } // namespace 192 } // namespace
191 193
192 QuicDispatcher::QuicDispatcher( 194 QuicDispatcher::QuicDispatcher(
193 const QuicConfig& config, 195 const QuicConfig& config,
194 const QuicCryptoServerConfig* crypto_config, 196 const QuicCryptoServerConfig* crypto_config,
195 QuicVersionManager* version_manager, 197 QuicVersionManager* version_manager,
196 std::unique_ptr<QuicConnectionHelperInterface> helper, 198 std::unique_ptr<QuicConnectionHelperInterface> helper,
197 std::unique_ptr<QuicServerSessionBase::Helper> session_helper, 199 std::unique_ptr<QuicCryptoServerStream::Helper> session_helper,
198 std::unique_ptr<QuicAlarmFactory> alarm_factory) 200 std::unique_ptr<QuicAlarmFactory> alarm_factory)
199 : config_(config), 201 : config_(config),
200 crypto_config_(crypto_config), 202 crypto_config_(crypto_config),
201 compressed_certs_cache_( 203 compressed_certs_cache_(
202 QuicCompressedCertsCache::kQuicCompressedCertsCacheSize), 204 QuicCompressedCertsCache::kQuicCompressedCertsCacheSize),
203 helper_(std::move(helper)), 205 helper_(std::move(helper)),
204 session_helper_(std::move(session_helper)), 206 session_helper_(std::move(session_helper)),
205 alarm_factory_(std::move(alarm_factory)), 207 alarm_factory_(std::move(alarm_factory)),
206 delete_sessions_alarm_( 208 delete_sessions_alarm_(
207 alarm_factory_->CreateAlarm(new DeleteSessionsAlarm(this))), 209 alarm_factory_->CreateAlarm(new DeleteSessionsAlarm(this))),
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
318 if (time_wait_list_manager_->IsConnectionIdInTimeWait( 320 if (time_wait_list_manager_->IsConnectionIdInTimeWait(
319 header.public_header.connection_id)) { 321 header.public_header.connection_id)) {
320 // This connection ID is already in time-wait state. 322 // This connection ID is already in time-wait state.
321 time_wait_list_manager_->ProcessPacket( 323 time_wait_list_manager_->ProcessPacket(
322 current_server_address_, current_client_address_, 324 current_server_address_, current_client_address_,
323 header.public_header.connection_id, header.packet_number, 325 header.public_header.connection_id, header.packet_number,
324 *current_packet_); 326 *current_packet_);
325 return false; 327 return false;
326 } 328 }
327 329
328 // Packet's connection ID is unknown. 330 // Packet's connection ID is unknown. Apply the validity checks.
329 // Apply the validity checks.
330 QuicPacketFate fate = ValidityChecks(header); 331 QuicPacketFate fate = ValidityChecks(header);
331 if (fate == kFateProcess) { 332 if (fate == kFateProcess) {
332 fate = MaybeRejectStatelessly(connection_id, header); 333 // Execute stateless rejection logic to determine the packet fate, then
334 // invoke ProcessUnauthenticatedHeaderFate.
335 MaybeRejectStatelessly(connection_id, header);
336 } else {
337 // If the fate is already known, process it without executing stateless
338 // rejection logic.
339 ProcessUnauthenticatedHeaderFate(fate, connection_id, header.packet_number);
333 } 340 }
341
342 return false;
343 }
344
345 void QuicDispatcher::ProcessUnauthenticatedHeaderFate(
346 QuicPacketFate fate,
347 QuicConnectionId connection_id,
348 QuicPacketNumber packet_number) {
334 switch (fate) { 349 switch (fate) {
335 case kFateProcess: { 350 case kFateProcess: {
336 ProcessChlo(); 351 ProcessChlo();
337 break; 352 break;
338 } 353 }
339 case kFateTimeWait: 354 case kFateTimeWait:
340 // MaybeRejectStatelessly might have already added the connection to 355 // MaybeRejectStatelessly might have already added the connection to
341 // time wait, in which case it should not be added again. 356 // time wait, in which case it should not be added again.
342 if (!FLAGS_quic_use_cheap_stateless_rejects || 357 if (!FLAGS_quic_use_cheap_stateless_rejects ||
343 !time_wait_list_manager_->IsConnectionIdInTimeWait( 358 !time_wait_list_manager_->IsConnectionIdInTimeWait(connection_id)) {
344 header.public_header.connection_id)) {
345 // Add this connection_id to the time-wait state, to safely reject 359 // Add this connection_id to the time-wait state, to safely reject
346 // future packets. 360 // future packets.
347 DVLOG(1) << "Adding connection ID " << connection_id 361 DVLOG(1) << "Adding connection ID " << connection_id
348 << "to time-wait list."; 362 << "to time-wait list.";
349 time_wait_list_manager_->AddConnectionIdToTimeWait( 363 time_wait_list_manager_->AddConnectionIdToTimeWait(
350 connection_id, framer_.version(), 364 connection_id, framer_.version(),
351 /*connection_rejected_statelessly=*/false, nullptr); 365 /*connection_rejected_statelessly=*/false, nullptr);
352 } 366 }
353 DCHECK(time_wait_list_manager_->IsConnectionIdInTimeWait( 367 DCHECK(time_wait_list_manager_->IsConnectionIdInTimeWait(connection_id));
354 header.public_header.connection_id));
355 time_wait_list_manager_->ProcessPacket( 368 time_wait_list_manager_->ProcessPacket(
356 current_server_address_, current_client_address_, 369 current_server_address_, current_client_address_, connection_id,
357 header.public_header.connection_id, header.packet_number, 370 packet_number, *current_packet_);
358 *current_packet_);
359 break; 371 break;
360 case kFateBuffer: 372 case kFateBuffer:
361 // This packet is a non-CHLO packet which has arrived out of order. 373 // This packet is a non-CHLO packet which has arrived out of order.
362 // Buffer it. 374 // Buffer it.
363 BufferEarlyPacket(connection_id); 375 BufferEarlyPacket(connection_id);
364 break; 376 break;
365 case kFateDrop: 377 case kFateDrop:
366 // Do nothing with the packet. 378 // Do nothing with the packet.
367 break; 379 break;
368 } 380 }
369
370 return false;
371 } 381 }
372 382
373 QuicDispatcher::QuicPacketFate QuicDispatcher::ValidityChecks( 383 QuicDispatcher::QuicPacketFate QuicDispatcher::ValidityChecks(
374 const QuicPacketHeader& header) { 384 const QuicPacketHeader& header) {
375 // To have all the checks work properly without tears, insert any new check 385 // To have all the checks work properly without tears, insert any new check
376 // into the framework of this method in the section for checks that return the 386 // into the framework of this method in the section for checks that return the
377 // check's fate value. The sections for checks must be ordered with the 387 // check's fate value. The sections for checks must be ordered with the
378 // highest priority fate first. 388 // highest priority fate first.
379 389
380 // Checks that return kFateDrop. 390 // Checks that return kFateDrop.
(...skipping 369 matching lines...) Expand 10 before | Expand all | Expand 10 after
750 760
751 void QuicDispatcher::SetLastError(QuicErrorCode error) { 761 void QuicDispatcher::SetLastError(QuicErrorCode error) {
752 last_error_ = error; 762 last_error_ = error;
753 } 763 }
754 764
755 bool QuicDispatcher::OnUnauthenticatedUnknownPublicHeader( 765 bool QuicDispatcher::OnUnauthenticatedUnknownPublicHeader(
756 const QuicPacketPublicHeader& header) { 766 const QuicPacketPublicHeader& header) {
757 return true; 767 return true;
758 } 768 }
759 769
760 QuicDispatcher::QuicPacketFate QuicDispatcher::MaybeRejectStatelessly( 770 class StatelessRejectorProcessDoneCallback
761 QuicConnectionId connection_id, 771 : public StatelessRejector::ProcessDoneCallback {
762 const QuicPacketHeader& header) { 772 public:
773 StatelessRejectorProcessDoneCallback(QuicDispatcher* dispatcher,
774 QuicPacketNumber packet_number,
775 QuicVersion first_version)
776 : dispatcher_(dispatcher),
777 packet_number_(packet_number),
778 first_version_(first_version) {}
779
780 void Run(std::unique_ptr<StatelessRejector> rejector) override {
781 dispatcher_->OnStatelessRejectorProcessDone(std::move(rejector),
782 packet_number_, first_version_);
783 }
784
785 private:
786 QuicDispatcher* dispatcher_;
787 QuicPacketNumber packet_number_;
788 QuicVersion first_version_;
789 };
790
791 void QuicDispatcher::MaybeRejectStatelessly(QuicConnectionId connection_id,
792 const QuicPacketHeader& header) {
763 // TODO(rch): This logic should probably live completely inside the rejector. 793 // TODO(rch): This logic should probably live completely inside the rejector.
764 if (!FLAGS_quic_use_cheap_stateless_rejects || 794 if (!FLAGS_quic_use_cheap_stateless_rejects ||
765 !FLAGS_enable_quic_stateless_reject_support || 795 !FLAGS_enable_quic_stateless_reject_support ||
766 header.public_header.versions.front() <= QUIC_VERSION_32 || 796 header.public_header.versions.front() <= QUIC_VERSION_32 ||
767 !ShouldAttemptCheapStatelessRejection()) { 797 !ShouldAttemptCheapStatelessRejection()) {
768 // Not use cheap stateless reject. 798 // Not use cheap stateless reject.
769 if (FLAGS_quic_buffer_packet_till_chlo && 799 if (FLAGS_quic_buffer_packet_till_chlo &&
770 !ChloExtractor::Extract(*current_packet_, GetSupportedVersions(), 800 !ChloExtractor::Extract(*current_packet_, GetSupportedVersions(),
771 nullptr)) { 801 nullptr)) {
772 // Buffer non-CHLO packets. 802 // Buffer non-CHLO packets.
773 return kFateBuffer; 803 ProcessUnauthenticatedHeaderFate(kFateBuffer, connection_id,
804 header.packet_number);
805 return;
774 } 806 }
775 return kFateProcess; 807 ProcessUnauthenticatedHeaderFate(kFateProcess, connection_id,
808 header.packet_number);
809 return;
776 } 810 }
777 811
778 StatelessRejector rejector( 812 std::unique_ptr<StatelessRejector> rejector(new StatelessRejector(
779 header.public_header.versions.front(), GetSupportedVersions(), 813 header.public_header.versions.front(), GetSupportedVersions(),
780 crypto_config_, &compressed_certs_cache_, helper()->GetClock(), 814 crypto_config_, &compressed_certs_cache_, helper()->GetClock(),
781 helper()->GetRandomGenerator(), current_packet_->length(), 815 helper()->GetRandomGenerator(), current_packet_->length(),
782 current_client_address_, current_server_address_); 816 current_client_address_, current_server_address_));
783 ChloValidator validator(session_helper_.get(), current_server_address_, 817 ChloValidator validator(session_helper_.get(), current_server_address_,
784 &rejector); 818 rejector.get());
785 if (!ChloExtractor::Extract(*current_packet_, GetSupportedVersions(), 819 if (!ChloExtractor::Extract(*current_packet_, GetSupportedVersions(),
786 &validator)) { 820 &validator)) {
787 if (!FLAGS_quic_buffer_packet_till_chlo) { 821 if (!FLAGS_quic_buffer_packet_till_chlo) {
788 QUIC_BUG 822 QUIC_BUG
789 << "Have to drop packet because buffering non-chlo packet is " 823 << "Have to drop packet because buffering non-chlo packet is "
790 "not supported while trying to do stateless reject. " 824 "not supported while trying to do stateless reject. "
791 "--gfe2_reloadable_flag_quic_buffer_packet_till_chlo false" 825 "--gfe2_reloadable_flag_quic_buffer_packet_till_chlo false"
792 " --gfe2_reloadable_flag_quic_use_cheap_stateless_rejects true"; 826 " --gfe2_reloadable_flag_quic_use_cheap_stateless_rejects true";
793 return kFateDrop; 827 ProcessUnauthenticatedHeaderFate(kFateDrop, connection_id,
828 header.packet_number);
829 return;
794 } 830 }
795 return kFateBuffer; 831 ProcessUnauthenticatedHeaderFate(kFateBuffer, connection_id,
832 header.packet_number);
833 return;
796 } 834 }
797 835
798 if (!validator.can_accept()) { 836 if (!validator.can_accept()) {
799 // This CHLO is prohibited by policy. 837 // This CHLO is prohibited by policy.
800 StatelessConnectionTerminator terminator(connection_id, &framer_, helper(), 838 StatelessConnectionTerminator terminator(connection_id, &framer_, helper(),
801 time_wait_list_manager_.get()); 839 time_wait_list_manager_.get());
802 terminator.CloseConnection(QUIC_HANDSHAKE_FAILED, 840 terminator.CloseConnection(QUIC_HANDSHAKE_FAILED,
803 validator.error_details()); 841 validator.error_details());
804 OnConnectionClosedStatelessly(QUIC_HANDSHAKE_FAILED); 842 OnConnectionClosedStatelessly(QUIC_HANDSHAKE_FAILED);
805 return kFateTimeWait; 843 ProcessUnauthenticatedHeaderFate(kFateTimeWait, connection_id,
844 header.packet_number);
845 return;
806 } 846 }
807 847
808 // This packet included a CHLO. See if it can be rejected statelessly. 848 // Continue stateless rejector processing
809 switch (rejector.state()) { 849 std::unique_ptr<StatelessRejectorProcessDoneCallback> cb(
850 new StatelessRejectorProcessDoneCallback(
851 this, header.packet_number, header.public_header.versions.front()));
852 StatelessRejector::Process(std::move(rejector), std::move(cb));
853 }
854
855 void QuicDispatcher::OnStatelessRejectorProcessDone(
856 std::unique_ptr<StatelessRejector> rejector,
857 QuicPacketNumber packet_number,
858 QuicVersion first_version) {
859 QuicPacketFate fate;
860 switch (rejector->state()) {
810 case StatelessRejector::FAILED: { 861 case StatelessRejector::FAILED: {
811 // There was an error processing the client hello. 862 // There was an error processing the client hello.
812 StatelessConnectionTerminator terminator( 863 StatelessConnectionTerminator terminator(rejector->connection_id(),
813 connection_id, &framer_, helper(), time_wait_list_manager_.get()); 864 &framer_, helper(),
814 terminator.CloseConnection(rejector.error(), rejector.error_details()); 865 time_wait_list_manager_.get());
815 return kFateTimeWait; 866 terminator.CloseConnection(rejector->error(), rejector->error_details());
867 fate = kFateTimeWait;
868 break;
816 } 869 }
817 870
818 case StatelessRejector::UNSUPPORTED: 871 case StatelessRejector::UNSUPPORTED:
819 // Cheap stateless rejects are not supported so process the packet. 872 // Cheap stateless rejects are not supported so process the packet.
820 return kFateProcess; 873 fate = kFateProcess;
874 break;
821 875
822 case StatelessRejector::ACCEPTED: 876 case StatelessRejector::ACCEPTED:
823 // Contains a valid CHLO, so process the packet and create a connection. 877 // Contains a valid CHLO, so process the packet and create a connection.
824 return kFateProcess; 878 fate = kFateProcess;
879 break;
825 880
826 case StatelessRejector::REJECTED: { 881 case StatelessRejector::REJECTED: {
827 DCHECK_EQ(framer_.version(), header.public_header.versions.front()); 882 DCHECK_EQ(framer_.version(), first_version);
828 StatelessConnectionTerminator terminator( 883 StatelessConnectionTerminator terminator(rejector->connection_id(),
829 connection_id, &framer_, helper(), time_wait_list_manager_.get()); 884 &framer_, helper(),
885 time_wait_list_manager_.get());
830 terminator.RejectConnection( 886 terminator.RejectConnection(
831 rejector.reply().GetSerialized().AsStringPiece()); 887 rejector->reply().GetSerialized().AsStringPiece());
832 OnConnectionRejectedStatelessly(); 888 OnConnectionRejectedStatelessly();
833 return kFateTimeWait; 889 fate = kFateTimeWait;
890 break;
834 } 891 }
892
893 default:
894 QUIC_BUG << "Rejector has invalid state " << rejector->state();
895 fate = kFateDrop;
896 break;
835 } 897 }
836 898 ProcessUnauthenticatedHeaderFate(fate, rejector->connection_id(),
837 QUIC_BUG << "Rejector has unknown invalid state."; 899 packet_number);
838 return kFateDrop;
839 } 900 }
840 901
841 const QuicVersionVector& QuicDispatcher::GetSupportedVersions() { 902 const QuicVersionVector& QuicDispatcher::GetSupportedVersions() {
842 return version_manager_->GetSupportedVersions(); 903 return version_manager_->GetSupportedVersions();
843 } 904 }
844 905
845 void QuicDispatcher::DeliverPacketsToSession( 906 void QuicDispatcher::DeliverPacketsToSession(
846 const std::list<BufferedPacket>& packets, 907 const std::list<BufferedPacket>& packets,
847 QuicServerSessionBase* session) { 908 QuicServerSessionBase* session) {
848 for (const BufferedPacket& packet : packets) { 909 for (const BufferedPacket& packet : packets) {
849 session->ProcessUdpPacket(packet.server_address, packet.client_address, 910 session->ProcessUdpPacket(packet.server_address, packet.client_address,
850 *(packet.packet)); 911 *(packet.packet));
851 } 912 }
852 } 913 }
853 914
854 } // namespace net 915 } // namespace net
OLDNEW
« no previous file with comments | « net/tools/quic/quic_dispatcher.h ('k') | net/tools/quic/quic_dispatcher_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698