gfe-relnote: In QUIC, do not use framer object in QuicDispatcher. Protected by gfe2_restart_flag_quic_no_framer_object_in_dispatcher.

Also, dispatcher does not parse and validate packet number anymore.

PiperOrigin-RevId: 247959538
Change-Id: Ia0f7901428537f392b05ffd6beb2984bffd00232
diff --git a/quic/core/quic_dispatcher.cc b/quic/core/quic_dispatcher.cc
index a9c6c4a..fa6fda7 100644
--- a/quic/core/quic_dispatcher.cc
+++ b/quic/core/quic_dispatcher.cc
@@ -10,6 +10,7 @@
 #include "net/third_party/quiche/src/quic/core/chlo_extractor.h"
 #include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
 #include "net/third_party/quiche/src/quic/core/crypto/quic_random.h"
+#include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
 #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"
@@ -303,8 +304,14 @@
       last_error_(QUIC_NO_ERROR),
       new_sessions_allowed_per_event_loop_(0u),
       accept_new_connections_(true),
-      allow_short_initial_connection_ids_(false) {
-  framer_.set_visitor(this);
+      allow_short_initial_connection_ids_(false),
+      last_version_label_(0),
+      expected_connection_id_length_(expected_connection_id_length),
+      should_update_expected_connection_id_length_(false),
+      no_framer_(GetQuicRestartFlag(quic_no_framer_object_in_dispatcher)) {
+  if (!no_framer_) {
+    framer_.set_visitor(this);
+  }
 }
 
 QuicDispatcher::~QuicDispatcher() {
@@ -326,21 +333,60 @@
   // GetClientAddress must be called after current_peer_address_ is set.
   current_client_address_ = GetClientAddress();
   current_packet_ = &packet;
-  // ProcessPacket will cause the packet to be dispatched in
-  // OnUnauthenticatedPublicHeader, or sent to the time wait list manager
-  // in OnUnauthenticatedHeader.
-  framer_.ProcessPacket(packet);
-  // TODO(rjshade): Return a status describing if/why a packet was dropped,
-  //                and log somehow.  Maybe expose as a varz.
-  // TODO(wub): Consider invalidate the current_* variables so processing of the
-  //            next packet does not use them incorrectly.
+  if (!no_framer_) {
+    // ProcessPacket will cause the packet to be dispatched in
+    // OnUnauthenticatedPublicHeader, or sent to the time wait list manager
+    // in OnUnauthenticatedHeader.
+    framer_.ProcessPacket(packet);
+    // TODO(rjshade): Return a status describing if/why a packet was dropped,
+    //                and log somehow.  Maybe expose as a varz.
+    return;
+  }
+  QUIC_RESTART_FLAG_COUNT(quic_no_framer_object_in_dispatcher);
+  QuicPacketHeader header;
+  uint8_t destination_connection_id_length;
+  string detailed_error;
+  const QuicErrorCode error = QuicFramer::ProcessPacketDispatcher(
+      packet, expected_connection_id_length_, &header.form,
+      &header.version_flag, &last_version_label_,
+      &destination_connection_id_length, &header.destination_connection_id,
+      &detailed_error);
+  if (error != QUIC_NO_ERROR) {
+    // Packet has framing error.
+    SetLastError(error);
+    QUIC_DLOG(ERROR) << detailed_error;
+    return;
+  }
+  header.version = ParseQuicVersionLabel(last_version_label_);
+  if (destination_connection_id_length != expected_connection_id_length_ &&
+      !should_update_expected_connection_id_length_ &&
+      !QuicUtils::VariableLengthConnectionIdAllowedForVersion(
+          header.version.transport_version)) {
+    SetLastError(QUIC_INVALID_PACKET_HEADER);
+    QUIC_DLOG(ERROR) << "Invalid Connection Id Length";
+    return;
+  }
+  if (should_update_expected_connection_id_length_) {
+    expected_connection_id_length_ = destination_connection_id_length;
+  }
+  // TODO(fayang): Instead of passing in QuicPacketHeader, pass format,
+  // version_flag, version and destination_connection_id. Combine
+  // OnUnauthenticatedPublicHeader and OnUnauthenticatedHeader to a single
+  // function when deprecating quic_no_framer_object_in_dispatcher.
+  if (!OnUnauthenticatedPublicHeader(header)) {
+    return;
+  }
+  OnUnauthenticatedHeader(header);
+  // TODO(wub): Consider invalidate the current_* variables so processing of
+  //            the next packet does not use them incorrectly.
 }
 
 QuicConnectionId QuicDispatcher::MaybeReplaceConnectionId(
     QuicConnectionId connection_id,
     ParsedQuicVersion version) {
   const uint8_t expected_connection_id_length =
-      framer_.GetExpectedConnectionIdLength();
+      no_framer_ ? expected_connection_id_length_
+                 : framer_.GetExpectedConnectionIdLength();
   if (connection_id.length() == expected_connection_id_length) {
     return connection_id;
   }
@@ -383,16 +429,18 @@
   // connection ID, the dispatcher picks a new one of its expected length.
   // Therefore we should never receive a connection ID that is smaller
   // than 64 bits and smaller than what we expect.
+  const uint8_t expected_connection_id_length =
+      no_framer_ ? expected_connection_id_length_
+                 : framer_.GetExpectedConnectionIdLength();
   if (connection_id.length() < kQuicMinimumInitialConnectionIdLength &&
-      connection_id.length() < framer_.GetExpectedConnectionIdLength() &&
+      connection_id.length() < expected_connection_id_length &&
       !allow_short_initial_connection_ids_) {
     DCHECK(header.version_flag);
     DCHECK(QuicUtils::VariableLengthConnectionIdAllowedForVersion(
         header.version.transport_version));
     QUIC_DLOG(INFO) << "Packet with short destination connection ID "
                     << connection_id << " expected "
-                    << static_cast<int>(
-                           framer_.GetExpectedConnectionIdLength());
+                    << static_cast<int>(expected_connection_id_length);
     ProcessUnauthenticatedHeaderFate(kFateTimeWait, connection_id, header.form,
                                      header.version_flag, header.version);
     return false;
@@ -449,12 +497,14 @@
   ParsedQuicVersion version = GetSupportedVersions().front();
   if (header.version_flag) {
     ParsedQuicVersion packet_version = header.version;
-    if (framer_.supported_versions() != GetSupportedVersions()) {
+    if (!no_framer_ && framer_.supported_versions() != GetSupportedVersions()) {
       // Reset framer's version if version flags change in flight.
       framer_.SetSupportedVersions(GetSupportedVersions());
     }
-    if (!framer_.IsSupportedVersion(packet_version)) {
-      if (ShouldCreateSessionForUnknownVersion(framer_.last_version_label())) {
+    if (!IsSupportedVersion(packet_version)) {
+      if (ShouldCreateSessionForUnknownVersion(
+              no_framer_ ? last_version_label_
+                         : framer_.last_version_label())) {
         return true;
       }
       if (!crypto_config()->validate_chlo_size() ||
@@ -470,8 +520,10 @@
     }
     version = packet_version;
   }
-  // Set the framer's version and continue processing.
-  framer_.set_version(version);
+  if (!no_framer_) {
+    // Set the framer's version and continue processing.
+    framer_.set_version(version);
+  }
 
   if (version.HasHeaderProtection()) {
     ProcessHeader(header);
@@ -573,6 +625,11 @@
     return kFateTimeWait;
   }
 
+  if (no_framer_) {
+    // Let the connection parse and validate packet number.
+    return kFateProcess;
+  }
+
   // initial packet number of 0 is always invalid.
   if (!framer_.version().HasHeaderProtection()) {
     if (!header.packet_number.IsInitialized()) {
@@ -797,7 +854,7 @@
   }
 
   // If the version is known and supported by framer, send a connection close.
-  if (framer_.IsSupportedVersion(version)) {
+  if (IsSupportedVersion(version)) {
     QUIC_DVLOG(1)
         << "Statelessly terminating " << connection_id
         << " based on an ietf-long packet, which has a supported version:"
@@ -852,6 +909,7 @@
 bool QuicDispatcher::OnProtocolVersionMismatch(
     ParsedQuicVersion /*received_version*/,
     PacketHeaderFormat /*form*/) {
+  DCHECK(!no_framer_);
   QUIC_BUG_IF(
       !time_wait_list_manager_->IsConnectionIdInTimeWait(
           current_connection_id_) &&
@@ -1146,7 +1204,7 @@
     EnqueuePacketResult rs = buffered_packets_.EnqueuePacket(
         current_connection_id_, form != GOOGLE_QUIC_PACKET, *current_packet_,
         current_self_address_, current_peer_address_,
-        /*is_chlo=*/true, current_alpn_, framer_.version());
+        /*is_chlo=*/true, current_alpn_, version);
     if (rs != EnqueuePacketResult::SUCCESS) {
       OnBufferPacketFailure(rs, current_connection_id_);
     }
@@ -1155,11 +1213,10 @@
 
   QuicConnectionId original_connection_id = current_connection_id_;
   current_connection_id_ =
-      MaybeReplaceConnectionId(current_connection_id_, framer_.version());
+      MaybeReplaceConnectionId(current_connection_id_, version);
   // Creates a new session and process all buffered packets for this connection.
-  QuicSession* session =
-      CreateQuicSession(current_connection_id_, current_peer_address_,
-                        current_alpn_, framer_.version());
+  QuicSession* session = CreateQuicSession(
+      current_connection_id_, current_peer_address_, current_alpn_, version);
   if (original_connection_id != current_connection_id_) {
     session->connection()->AddIncomingConnectionId(original_connection_id);
   }
@@ -1338,7 +1395,9 @@
   current_self_address_ = current_self_address;
   current_packet_ = current_packet.get();
   current_connection_id_ = rejector->connection_id();
-  framer_.set_version(first_version);
+  if (!no_framer_) {
+    framer_.set_version(first_version);
+  }
 
   // Stop buffering packets on this connection
   const auto num_erased =
@@ -1391,7 +1450,7 @@
       break;
 
     case StatelessRejector::REJECTED: {
-      QUIC_BUG_IF(first_version != framer_.version())
+      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: "
@@ -1438,7 +1497,22 @@
 }
 
 void QuicDispatcher::DisableFlagValidation() {
-  framer_.set_validate_flags(false);
+  if (!no_framer_) {
+    framer_.set_validate_flags(false);
+  }
+}
+
+bool QuicDispatcher::IsSupportedVersion(const ParsedQuicVersion version) {
+  if (!no_framer_) {
+    return framer_.IsSupportedVersion(version);
+  }
+  for (const ParsedQuicVersion& supported_version :
+       version_manager_->GetSupportedVersions()) {
+    if (version == supported_version) {
+      return true;
+    }
+  }
+  return false;
 }
 
 }  // namespace quic