Index: net/tools/quic/quic_dispatcher.cc |
diff --git a/net/tools/quic/quic_dispatcher.cc b/net/tools/quic/quic_dispatcher.cc |
index 486aea70a3eb36947b0af412b27756a54ab86fd7..0d558694418f84c74ddabd2696a2d179cfd53a7f 100644 |
--- a/net/tools/quic/quic_dispatcher.cc |
+++ b/net/tools/quic/quic_dispatcher.cc |
@@ -14,9 +14,11 @@ |
#include "net/quic/core/quic_bug_tracker.h" |
#include "net/quic/core/quic_flags.h" |
#include "net/quic/core/quic_utils.h" |
+ |
#include "net/tools/quic/chlo_extractor.h" |
#include "net/tools/quic/quic_per_connection_packet_writer.h" |
#include "net/tools/quic/quic_simple_server_session.h" |
+#include "net/tools/quic/quic_simple_server_session.h" |
#include "net/tools/quic/quic_time_wait_list_manager.h" |
#include "net/tools/quic/stateless_rejector.h" |
@@ -155,7 +157,7 @@ class StatelessConnectionTerminator { |
// to give the QuicDispatcher a chance to apply policy checks to the CHLO. |
class ChloValidator : public ChloExtractor::Delegate { |
public: |
- ChloValidator(QuicServerSessionBase::Helper* helper, |
+ ChloValidator(QuicCryptoServerStream::Helper* helper, |
IPEndPoint self_address, |
StatelessRejector* rejector) |
: helper_(helper), |
@@ -180,7 +182,7 @@ class ChloValidator : public ChloExtractor::Delegate { |
const string& error_details() const { return error_details_; } |
private: |
- QuicServerSessionBase::Helper* helper_; // Unowned. |
+ QuicCryptoServerStream::Helper* helper_; // Unowned. |
IPEndPoint self_address_; |
StatelessRejector* rejector_; // Unowned. |
bool can_accept_; |
@@ -194,7 +196,7 @@ QuicDispatcher::QuicDispatcher( |
const QuicCryptoServerConfig* crypto_config, |
QuicVersionManager* version_manager, |
std::unique_ptr<QuicConnectionHelperInterface> helper, |
- std::unique_ptr<QuicServerSessionBase::Helper> session_helper, |
+ std::unique_ptr<QuicCryptoServerStream::Helper> session_helper, |
std::unique_ptr<QuicAlarmFactory> alarm_factory) |
: config_(config), |
crypto_config_(crypto_config), |
@@ -325,12 +327,25 @@ bool QuicDispatcher::OnUnauthenticatedHeader(const QuicPacketHeader& header) { |
return false; |
} |
- // Packet's connection ID is unknown. |
- // Apply the validity checks. |
+ // Packet's connection ID is unknown. Apply the validity checks. |
QuicPacketFate fate = ValidityChecks(header); |
if (fate == kFateProcess) { |
- fate = MaybeRejectStatelessly(connection_id, header); |
+ // Execute stateless rejection logic to determine the packet fate, then |
+ // invoke ProcessUnauthenticatedHeaderFate. |
+ MaybeRejectStatelessly(connection_id, header); |
+ } else { |
+ // If the fate is already known, process it without executing stateless |
+ // rejection logic. |
+ ProcessUnauthenticatedHeaderFate(fate, connection_id, header.packet_number); |
} |
+ |
+ return false; |
+} |
+ |
+void QuicDispatcher::ProcessUnauthenticatedHeaderFate( |
+ QuicPacketFate fate, |
+ QuicConnectionId connection_id, |
+ QuicPacketNumber packet_number) { |
switch (fate) { |
case kFateProcess: { |
ProcessChlo(); |
@@ -340,8 +355,7 @@ bool QuicDispatcher::OnUnauthenticatedHeader(const QuicPacketHeader& header) { |
// MaybeRejectStatelessly might have already added the connection to |
// time wait, in which case it should not be added again. |
if (!FLAGS_quic_use_cheap_stateless_rejects || |
- !time_wait_list_manager_->IsConnectionIdInTimeWait( |
- header.public_header.connection_id)) { |
+ !time_wait_list_manager_->IsConnectionIdInTimeWait(connection_id)) { |
// Add this connection_id to the time-wait state, to safely reject |
// future packets. |
DVLOG(1) << "Adding connection ID " << connection_id |
@@ -350,12 +364,10 @@ bool QuicDispatcher::OnUnauthenticatedHeader(const QuicPacketHeader& header) { |
connection_id, framer_.version(), |
/*connection_rejected_statelessly=*/false, nullptr); |
} |
- DCHECK(time_wait_list_manager_->IsConnectionIdInTimeWait( |
- header.public_header.connection_id)); |
+ DCHECK(time_wait_list_manager_->IsConnectionIdInTimeWait(connection_id)); |
time_wait_list_manager_->ProcessPacket( |
- current_server_address_, current_client_address_, |
- header.public_header.connection_id, header.packet_number, |
- *current_packet_); |
+ current_server_address_, current_client_address_, connection_id, |
+ packet_number, *current_packet_); |
break; |
case kFateBuffer: |
// This packet is a non-CHLO packet which has arrived out of order. |
@@ -366,8 +378,6 @@ bool QuicDispatcher::OnUnauthenticatedHeader(const QuicPacketHeader& header) { |
// Do nothing with the packet. |
break; |
} |
- |
- return false; |
} |
QuicDispatcher::QuicPacketFate QuicDispatcher::ValidityChecks( |
@@ -757,9 +767,29 @@ bool QuicDispatcher::OnUnauthenticatedUnknownPublicHeader( |
return true; |
} |
-QuicDispatcher::QuicPacketFate QuicDispatcher::MaybeRejectStatelessly( |
- QuicConnectionId connection_id, |
- const QuicPacketHeader& header) { |
+class StatelessRejectorProcessDoneCallback |
+ : public StatelessRejector::ProcessDoneCallback { |
+ public: |
+ StatelessRejectorProcessDoneCallback(QuicDispatcher* dispatcher, |
+ QuicPacketNumber packet_number, |
+ QuicVersion first_version) |
+ : dispatcher_(dispatcher), |
+ packet_number_(packet_number), |
+ first_version_(first_version) {} |
+ |
+ void Run(std::unique_ptr<StatelessRejector> rejector) override { |
+ dispatcher_->OnStatelessRejectorProcessDone(std::move(rejector), |
+ packet_number_, first_version_); |
+ } |
+ |
+ private: |
+ QuicDispatcher* dispatcher_; |
+ QuicPacketNumber packet_number_; |
+ QuicVersion first_version_; |
+}; |
+ |
+void QuicDispatcher::MaybeRejectStatelessly(QuicConnectionId connection_id, |
+ const QuicPacketHeader& header) { |
// TODO(rch): This logic should probably live completely inside the rejector. |
if (!FLAGS_quic_use_cheap_stateless_rejects || |
!FLAGS_enable_quic_stateless_reject_support || |
@@ -770,18 +800,22 @@ QuicDispatcher::QuicPacketFate QuicDispatcher::MaybeRejectStatelessly( |
!ChloExtractor::Extract(*current_packet_, GetSupportedVersions(), |
nullptr)) { |
// Buffer non-CHLO packets. |
- return kFateBuffer; |
+ ProcessUnauthenticatedHeaderFate(kFateBuffer, connection_id, |
+ header.packet_number); |
+ return; |
} |
- return kFateProcess; |
+ ProcessUnauthenticatedHeaderFate(kFateProcess, connection_id, |
+ header.packet_number); |
+ return; |
} |
- StatelessRejector rejector( |
+ std::unique_ptr<StatelessRejector> rejector(new StatelessRejector( |
header.public_header.versions.front(), GetSupportedVersions(), |
crypto_config_, &compressed_certs_cache_, helper()->GetClock(), |
helper()->GetRandomGenerator(), current_packet_->length(), |
- current_client_address_, current_server_address_); |
+ current_client_address_, current_server_address_)); |
ChloValidator validator(session_helper_.get(), current_server_address_, |
- &rejector); |
+ rejector.get()); |
if (!ChloExtractor::Extract(*current_packet_, GetSupportedVersions(), |
&validator)) { |
if (!FLAGS_quic_buffer_packet_till_chlo) { |
@@ -790,9 +824,13 @@ QuicDispatcher::QuicPacketFate QuicDispatcher::MaybeRejectStatelessly( |
"not supported while trying to do stateless reject. " |
"--gfe2_reloadable_flag_quic_buffer_packet_till_chlo false" |
" --gfe2_reloadable_flag_quic_use_cheap_stateless_rejects true"; |
- return kFateDrop; |
+ ProcessUnauthenticatedHeaderFate(kFateDrop, connection_id, |
+ header.packet_number); |
+ return; |
} |
- return kFateBuffer; |
+ ProcessUnauthenticatedHeaderFate(kFateBuffer, connection_id, |
+ header.packet_number); |
+ return; |
} |
if (!validator.can_accept()) { |
@@ -802,40 +840,63 @@ QuicDispatcher::QuicPacketFate QuicDispatcher::MaybeRejectStatelessly( |
terminator.CloseConnection(QUIC_HANDSHAKE_FAILED, |
validator.error_details()); |
OnConnectionClosedStatelessly(QUIC_HANDSHAKE_FAILED); |
- return kFateTimeWait; |
+ ProcessUnauthenticatedHeaderFate(kFateTimeWait, connection_id, |
+ header.packet_number); |
+ return; |
} |
- // This packet included a CHLO. See if it can be rejected statelessly. |
- switch (rejector.state()) { |
+ // Continue stateless rejector processing |
+ std::unique_ptr<StatelessRejectorProcessDoneCallback> cb( |
+ new StatelessRejectorProcessDoneCallback( |
+ this, header.packet_number, header.public_header.versions.front())); |
+ StatelessRejector::Process(std::move(rejector), std::move(cb)); |
+} |
+ |
+void QuicDispatcher::OnStatelessRejectorProcessDone( |
+ std::unique_ptr<StatelessRejector> rejector, |
+ QuicPacketNumber packet_number, |
+ QuicVersion first_version) { |
+ QuicPacketFate fate; |
+ switch (rejector->state()) { |
case StatelessRejector::FAILED: { |
// There was an error processing the client hello. |
- StatelessConnectionTerminator terminator( |
- connection_id, &framer_, helper(), time_wait_list_manager_.get()); |
- terminator.CloseConnection(rejector.error(), rejector.error_details()); |
- return kFateTimeWait; |
+ StatelessConnectionTerminator terminator(rejector->connection_id(), |
+ &framer_, helper(), |
+ time_wait_list_manager_.get()); |
+ terminator.CloseConnection(rejector->error(), rejector->error_details()); |
+ fate = kFateTimeWait; |
+ break; |
} |
case StatelessRejector::UNSUPPORTED: |
// Cheap stateless rejects are not supported so process the packet. |
- return kFateProcess; |
+ fate = kFateProcess; |
+ break; |
case StatelessRejector::ACCEPTED: |
// Contains a valid CHLO, so process the packet and create a connection. |
- return kFateProcess; |
+ fate = kFateProcess; |
+ break; |
case StatelessRejector::REJECTED: { |
- DCHECK_EQ(framer_.version(), header.public_header.versions.front()); |
- StatelessConnectionTerminator terminator( |
- connection_id, &framer_, helper(), time_wait_list_manager_.get()); |
+ DCHECK_EQ(framer_.version(), first_version); |
+ StatelessConnectionTerminator terminator(rejector->connection_id(), |
+ &framer_, helper(), |
+ time_wait_list_manager_.get()); |
terminator.RejectConnection( |
- rejector.reply().GetSerialized().AsStringPiece()); |
+ rejector->reply().GetSerialized().AsStringPiece()); |
OnConnectionRejectedStatelessly(); |
- return kFateTimeWait; |
+ fate = kFateTimeWait; |
+ break; |
} |
- } |
- QUIC_BUG << "Rejector has unknown invalid state."; |
- return kFateDrop; |
+ default: |
+ QUIC_BUG << "Rejector has invalid state " << rejector->state(); |
+ fate = kFateDrop; |
+ break; |
+ } |
+ ProcessUnauthenticatedHeaderFate(fate, rejector->connection_id(), |
+ packet_number); |
} |
const QuicVersionVector& QuicDispatcher::GetSupportedVersions() { |