gfe-relnote: Remove stateless reject from QUIC. This deprecates two flags in the false position: --gfe2_reloadable_flag_enable_quic_stateless_reject_support and --gfe2_reloadable_flag_quic_use_cheap_stateless_rejects.

PiperOrigin-RevId: 250347964
Change-Id: I50e150f91e76b672160eadc04a379b529a4f602d
diff --git a/quic/core/quic_dispatcher.cc b/quic/core/quic_dispatcher.cc
index 609c6b6..796b2dc 100644
--- a/quic/core/quic_dispatcher.cc
+++ b/quic/core/quic_dispatcher.cc
@@ -14,7 +14,6 @@
 #include "net/third_party/quiche/src/quic/core/quic_time_wait_list_manager.h"
 #include "net/third_party/quiche/src/quic/core/quic_types.h"
 #include "net/third_party/quiche/src/quic/core/quic_utils.h"
-#include "net/third_party/quiche/src/quic/core/stateless_rejector.h"
 #include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
 #include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
 #include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
@@ -229,55 +228,6 @@
   std::string alpn_;
 };
 
-// Class which sits between the ChloExtractor and the StatelessRejector
-// to give the QuicDispatcher a chance to apply policy checks to the CHLO.
-class ChloValidator : public ChloAlpnExtractor {
- public:
-  ChloValidator(QuicCryptoServerStream::Helper* helper,
-                const QuicSocketAddress& client_address,
-                const QuicSocketAddress& peer_address,
-                const QuicSocketAddress& self_address,
-                StatelessRejector* rejector)
-      : helper_(helper),
-        client_address_(client_address),
-        peer_address_(peer_address),
-        self_address_(self_address),
-        rejector_(rejector),
-        can_accept_(false),
-        error_details_("CHLO not processed") {}
-
-  // ChloExtractor::Delegate implementation.
-  void OnChlo(QuicTransportVersion version,
-              QuicConnectionId server_connection_id,
-              const CryptoHandshakeMessage& chlo) override {
-    // Extract the ALPN
-    ChloAlpnExtractor::OnChlo(version, server_connection_id, chlo);
-    if (helper_->CanAcceptClientHello(chlo, client_address_, peer_address_,
-                                      self_address_, &error_details_)) {
-      can_accept_ = true;
-      rejector_->OnChlo(
-          version, server_connection_id,
-          helper_->GenerateConnectionIdForReject(version, server_connection_id),
-          chlo);
-    }
-  }
-
-  bool can_accept() const { return can_accept_; }
-
-  const std::string& error_details() const { return error_details_; }
-
- private:
-  QuicCryptoServerStream::Helper* helper_;  // Unowned.
-  // client_address_ and peer_address_ could be different values for proxy
-  // connections.
-  QuicSocketAddress client_address_;
-  QuicSocketAddress peer_address_;
-  QuicSocketAddress self_address_;
-  StatelessRejector* rejector_;  // Unowned.
-  bool can_accept_;
-  std::string error_details_;
-};
-
 }  // namespace
 
 QuicDispatcher::QuicDispatcher(
@@ -551,10 +501,8 @@
   // Packet's connection ID is unknown.  Apply the validity checks.
   QuicPacketFate fate = ValidityChecks(header);
   if (fate == kFateProcess) {
-    // Execute stateless rejection logic to determine the packet fate, then
-    // invoke ProcessUnauthenticatedHeaderFate.
-    MaybeRejectStatelessly(server_connection_id, header.form,
-                           header.version_flag, header.version);
+    ProcessOrBufferPacket(server_connection_id, header.form,
+                          header.version_flag, header.version);
   } else {
     // If the fate is already known, process it without executing stateless
     // rejection logic.
@@ -575,21 +523,16 @@
       break;
     }
     case kFateTimeWait:
-      // MaybeRejectStatelessly or OnExpiredPackets might have already added the
-      // connection to time wait, in which case it should not be added again.
-      if (!GetQuicReloadableFlag(quic_use_cheap_stateless_rejects) ||
-          !time_wait_list_manager_->IsConnectionIdInTimeWait(
-              server_connection_id)) {
-        // Add this connection_id to the time-wait state, to safely reject
-        // future packets.
-        QUIC_DLOG(INFO) << "Adding connection ID " << server_connection_id
-                        << " to time-wait list.";
-        QUIC_CODE_COUNT(quic_reject_fate_time_wait);
-        StatelesslyTerminateConnection(
-            server_connection_id, form, version_flag, version,
-            QUIC_HANDSHAKE_FAILED, "Reject connection",
-            quic::QuicTimeWaitListManager::SEND_STATELESS_RESET);
-      }
+      // Add this connection_id to the time-wait state, to safely reject
+      // future packets.
+      QUIC_DLOG(INFO) << "Adding connection ID " << server_connection_id
+                      << " to time-wait list.";
+      QUIC_CODE_COUNT(quic_reject_fate_time_wait);
+      StatelesslyTerminateConnection(
+          server_connection_id, form, version_flag, version,
+          QUIC_HANDSHAKE_FAILED, "Reject connection",
+          quic::QuicTimeWaitListManager::SEND_STATELESS_RESET);
+
       DCHECK(time_wait_list_manager_->IsConnectionIdInTimeWait(
           server_connection_id));
       time_wait_list_manager_->ProcessPacket(
@@ -1167,10 +1110,6 @@
                   << server_connection_id << " because of " << result;
 }
 
-bool QuicDispatcher::ShouldAttemptCheapStatelessRejection() {
-  return true;
-}
-
 QuicTimeWaitListManager* QuicDispatcher::CreateQuicTimeWaitListManager() {
   return new QuicTimeWaitListManager(writer_.get(), this, helper_->GetClock(),
                                      alarm_factory_.get());
@@ -1274,49 +1213,7 @@
   return true;
 }
 
-class StatelessRejectorProcessDoneCallback
-    : public StatelessRejector::ProcessDoneCallback {
- public:
-  StatelessRejectorProcessDoneCallback(QuicDispatcher* dispatcher,
-                                       ParsedQuicVersion first_version,
-                                       PacketHeaderFormat form,
-                                       bool version_flag)
-      : dispatcher_(dispatcher),
-        current_client_address_(dispatcher->current_client_address_),
-        current_peer_address_(dispatcher->current_peer_address_),
-        current_self_address_(dispatcher->current_self_address_),
-        additional_context_(dispatcher->GetPerPacketContext()),
-        current_packet_(
-            dispatcher->current_packet_->Clone()),  // Note: copies the packet
-        first_version_(first_version),
-        current_packet_format_(form),
-        current_version_flag_(version_flag) {}
-
-  void Run(std::unique_ptr<StatelessRejector> rejector) override {
-    if (additional_context_ != nullptr) {
-      dispatcher_->RestorePerPacketContext(std::move(additional_context_));
-    }
-    dispatcher_->OnStatelessRejectorProcessDone(
-        std::move(rejector), current_client_address_, current_peer_address_,
-        current_self_address_, std::move(current_packet_), first_version_,
-        current_packet_format_, current_version_flag_);
-  }
-
- private:
-  QuicDispatcher* dispatcher_;
-  QuicSocketAddress current_client_address_;
-  QuicSocketAddress current_peer_address_;
-  QuicSocketAddress current_self_address_;
-  // TODO(wub): Wrap all current_* variables into PerPacketContext. And rename
-  // |additional_context_| to |context_|.
-  std::unique_ptr<QuicPerPacketContext> additional_context_;
-  std::unique_ptr<QuicReceivedPacket> current_packet_;
-  ParsedQuicVersion first_version_;
-  const PacketHeaderFormat current_packet_format_;
-  bool current_version_flag_;
-};
-
-void QuicDispatcher::MaybeRejectStatelessly(
+void QuicDispatcher::ProcessOrBufferPacket(
     QuicConnectionId server_connection_id,
     PacketHeaderFormat form,
     bool version_flag,
@@ -1327,179 +1224,20 @@
     return;
     // TODO(nharper): Support buffering non-ClientHello packets when using TLS.
   }
-  // TODO(rch): This logic should probably live completely inside the rejector.
-  if (!FLAGS_quic_allow_chlo_buffering ||
-      !GetQuicReloadableFlag(quic_use_cheap_stateless_rejects) ||
-      !GetQuicReloadableFlag(enable_quic_stateless_reject_support) ||
-      !ShouldAttemptCheapStatelessRejection()) {
-    // Not use cheap stateless reject.
-    ChloAlpnExtractor alpn_extractor;
-    if (FLAGS_quic_allow_chlo_buffering &&
-        !ChloExtractor::Extract(*current_packet_, GetSupportedVersions(),
-                                config_->create_session_tag_indicators(),
-                                &alpn_extractor,
-                                server_connection_id.length())) {
-      // Buffer non-CHLO packets.
-      ProcessUnauthenticatedHeaderFate(kFateBuffer, server_connection_id, form,
-                                       version_flag, version);
-      return;
-    }
-    current_alpn_ = alpn_extractor.ConsumeAlpn();
-    ProcessUnauthenticatedHeaderFate(kFateProcess, server_connection_id, form,
-                                     version_flag, version);
-    return;
-  }
 
-  std::unique_ptr<StatelessRejector> rejector(new StatelessRejector(
-      version, GetSupportedVersions(), crypto_config_, &compressed_certs_cache_,
-      helper()->GetClock(), helper()->GetRandomGenerator(),
-      current_packet_->length(), current_client_address_,
-      current_self_address_));
-  ChloValidator validator(session_helper_.get(), current_client_address_,
-                          current_peer_address_, current_self_address_,
-                          rejector.get());
-  if (!ChloExtractor::Extract(*current_packet_, GetSupportedVersions(),
+  ChloAlpnExtractor alpn_extractor;
+  if (FLAGS_quic_allow_chlo_buffering &&
+      !ChloExtractor::Extract(*current_packet_, GetSupportedVersions(),
                               config_->create_session_tag_indicators(),
-                              &validator, server_connection_id.length())) {
+                              &alpn_extractor, server_connection_id.length())) {
+    // Buffer non-CHLO packets.
     ProcessUnauthenticatedHeaderFate(kFateBuffer, server_connection_id, form,
                                      version_flag, version);
     return;
   }
-  current_alpn_ = validator.ConsumeAlpn();
-
-  if (!validator.can_accept()) {
-    // This CHLO is prohibited by policy.
-    QUIC_CODE_COUNT(quic_reject_cant_accept_chlo);
-    StatelessConnectionTerminator terminator(
-        server_connection_id, version, helper(), time_wait_list_manager_.get());
-    terminator.CloseConnection(QUIC_HANDSHAKE_FAILED, validator.error_details(),
-                               form != GOOGLE_QUIC_PACKET);
-    QuicSession::RecordConnectionCloseAtServer(
-        QUIC_HANDSHAKE_FAILED, ConnectionCloseSource::FROM_SELF);
-    ProcessUnauthenticatedHeaderFate(kFateTimeWait, server_connection_id, form,
-                                     version_flag, version);
-    return;
-  }
-
-  // If we were able to make a decision about this CHLO based purely on the
-  // information available in OnChlo, just invoke the done callback immediately.
-  if (rejector->state() != StatelessRejector::UNKNOWN) {
-    ProcessStatelessRejectorState(std::move(rejector), version, form,
-                                  version_flag);
-    return;
-  }
-
-  // Insert into set of connection IDs to buffer
-  const bool ok =
-      temporarily_buffered_connections_.insert(server_connection_id).second;
-  QUIC_BUG_IF(!ok)
-      << "Processing multiple stateless rejections for connection ID "
-      << server_connection_id;
-
-  // Continue stateless rejector processing
-  std::unique_ptr<StatelessRejectorProcessDoneCallback> cb(
-      new StatelessRejectorProcessDoneCallback(this, version, form,
-                                               version_flag));
-  StatelessRejector::Process(std::move(rejector), std::move(cb));
-}
-
-void QuicDispatcher::OnStatelessRejectorProcessDone(
-    std::unique_ptr<StatelessRejector> rejector,
-    const QuicSocketAddress& current_client_address,
-    const QuicSocketAddress& current_peer_address,
-    const QuicSocketAddress& current_self_address,
-    std::unique_ptr<QuicReceivedPacket> current_packet,
-    ParsedQuicVersion first_version,
-    PacketHeaderFormat current_packet_format,
-    bool current_version_flag) {
-  // Reset current_* to correspond to the packet which initiated the stateless
-  // reject logic.
-  current_client_address_ = current_client_address;
-  current_peer_address_ = current_peer_address;
-  current_self_address_ = current_self_address;
-  current_packet_ = current_packet.get();
-  current_server_connection_id_ = rejector->connection_id();
-  if (!no_framer_) {
-    framer_.set_version(first_version);
-  }
-
-  // Stop buffering packets on this connection
-  const auto num_erased =
-      temporarily_buffered_connections_.erase(rejector->connection_id());
-  QUIC_BUG_IF(num_erased != 1) << "Completing stateless rejection logic for "
-                                  "non-buffered connection ID "
-                               << rejector->connection_id();
-
-  // If this connection has gone into time-wait during the async processing,
-  // don't proceed.
-  if (time_wait_list_manager_->IsConnectionIdInTimeWait(
-          rejector->connection_id())) {
-    time_wait_list_manager_->ProcessPacket(
-        current_self_address, current_peer_address, rejector->connection_id(),
-        current_packet_format, GetPerPacketContext());
-    return;
-  }
-
-  ProcessStatelessRejectorState(std::move(rejector), first_version,
-                                current_packet_format, current_version_flag);
-}
-
-void QuicDispatcher::ProcessStatelessRejectorState(
-    std::unique_ptr<StatelessRejector> rejector,
-    ParsedQuicVersion first_version,
-    PacketHeaderFormat form,
-    bool version_flag) {
-  QuicPacketFate fate;
-  switch (rejector->state()) {
-    case StatelessRejector::FAILED: {
-      // There was an error processing the client hello.
-      QUIC_CODE_COUNT(quic_reject_error_processing_chlo);
-      StatelessConnectionTerminator terminator(rejector->connection_id(),
-                                               first_version, helper(),
-                                               time_wait_list_manager_.get());
-      terminator.CloseConnection(rejector->error(), rejector->error_details(),
-                                 form != GOOGLE_QUIC_PACKET);
-      fate = kFateTimeWait;
-      break;
-    }
-
-    case StatelessRejector::UNSUPPORTED:
-      // Cheap stateless rejects are not supported so process the packet.
-      fate = kFateProcess;
-      break;
-
-    case StatelessRejector::ACCEPTED:
-      // Contains a valid CHLO, so process the packet and create a connection.
-      fate = kFateProcess;
-      break;
-
-    case StatelessRejector::REJECTED: {
-      QUIC_BUG_IF(!no_framer_ && first_version != framer_.version())
-          << "SREJ: Client's version: "
-          << QuicVersionToString(first_version.transport_version)
-          << " is different from current dispatcher framer's version: "
-          << QuicVersionToString(framer_.transport_version());
-      StatelessConnectionTerminator terminator(rejector->connection_id(),
-                                               first_version, helper(),
-                                               time_wait_list_manager_.get());
-      terminator.RejectConnection(
-          rejector->reply().GetSerialized().AsStringPiece(),
-          form != GOOGLE_QUIC_PACKET);
-      QuicSession::RecordConnectionCloseAtServer(
-          QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT,
-          ConnectionCloseSource::FROM_SELF);
-      OnConnectionRejectedStatelessly();
-      fate = kFateTimeWait;
-      break;
-    }
-
-    default:
-      QUIC_BUG << "Rejector has invalid state " << rejector->state();
-      fate = kFateDrop;
-      break;
-  }
-  ProcessUnauthenticatedHeaderFate(fate, rejector->connection_id(), form,
-                                   version_flag, rejector->version());
+  current_alpn_ = alpn_extractor.ConsumeAlpn();
+  ProcessUnauthenticatedHeaderFate(kFateProcess, server_connection_id, form,
+                                   version_flag, version);
 }
 
 const QuicTransportVersionVector&