gfe-relnote: In QuicPacketReader, change the use of QuicSocketUtils to QuicUdpSocketApi. Protected by --gfe2_restart_flag_quic_remove_quic_socket_utils_from_packet_reader.

PiperOrigin-RevId: 291783340
Change-Id: I66bf260d8d963a8b362f5ffefd96b7a16f7c6c24
diff --git a/quic/core/quic_packet_reader.cc b/quic/core/quic_packet_reader.cc
index 81d2a7d..95cc4e4 100644
--- a/quic/core/quic_packet_reader.cc
+++ b/quic/core/quic_packet_reader.cc
@@ -17,10 +17,10 @@
 #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"
+#include "net/third_party/quiche/src/quic/platform/api/quic_ip_address.h"
 #include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
 #include "net/third_party/quiche/src/quic/platform/api/quic_server_stats.h"
 #include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
-#include "net/quic/platform/impl/quic_socket_utils.h"
 #include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
 
 #ifndef SO_RXQ_OVFL
@@ -29,8 +29,26 @@
 
 namespace quic {
 
-QuicPacketReader::QuicPacketReader() {
-  Initialize();
+QuicPacketReader::QuicPacketReader()
+    : read_buffers_(kNumPacketsPerReadMmsgCall),
+      read_results_(kNumPacketsPerReadMmsgCall) {
+  if (!remove_quic_socket_utils_from_packet_reader_) {
+    Initialize();
+    return;
+  }
+
+  QUIC_RESTART_FLAG_COUNT_N(quic_remove_quic_socket_utils_from_packet_reader, 1,
+                            5);
+  DCHECK_EQ(read_buffers_.size(), read_results_.size());
+  for (size_t i = 0; i < read_results_.size(); ++i) {
+    read_results_[i].packet_buffer.buffer = read_buffers_[i].packet_buffer;
+    read_results_[i].packet_buffer.buffer_len =
+        sizeof(read_buffers_[i].packet_buffer);
+
+    read_results_[i].control_buffer.buffer = read_buffers_[i].control_buffer;
+    read_results_[i].control_buffer.buffer_len =
+        sizeof(read_buffers_[i].control_buffer);
+  }
 }
 
 void QuicPacketReader::Initialize() {
@@ -65,13 +83,114 @@
     const QuicClock& clock,
     ProcessPacketInterface* processor,
     QuicPacketCount* packets_dropped) {
+  if (!remove_quic_socket_utils_from_packet_reader_) {
 #if MMSG_MORE_NO_ANDROID
-  return ReadAndDispatchManyPackets(fd, port, clock, processor,
-                                    packets_dropped);
+    return ReadAndDispatchManyPackets(fd, port, clock, processor,
+                                      packets_dropped);
 #else
-  return ReadAndDispatchSinglePacket(fd, port, clock, processor,
-                                     packets_dropped);
+    return ReadAndDispatchSinglePacket(fd, port, clock, processor,
+                                       packets_dropped);
 #endif
+  }
+
+  // Reset all read_results for reuse.
+  for (size_t i = 0; i < read_results_.size(); ++i) {
+    read_results_[i].Reset(
+        /*packet_buffer_length=*/sizeof(read_buffers_[i].packet_buffer));
+  }
+  QuicWallTime wallnow = clock.WallNow();
+  size_t packets_read = socket_api_.ReadMultiplePackets(
+      fd,
+      BitMask64(QuicUdpPacketInfoBit::DROPPED_PACKETS,
+                QuicUdpPacketInfoBit::PEER_ADDRESS,
+                QuicUdpPacketInfoBit::V4_SELF_IP,
+                QuicUdpPacketInfoBit::V6_SELF_IP,
+                QuicUdpPacketInfoBit::RECV_TIMESTAMP, QuicUdpPacketInfoBit::TTL,
+                QuicUdpPacketInfoBit::GOOGLE_PACKET_HEADER),
+      &read_results_);
+  for (size_t i = 0; i < packets_read; ++i) {
+    auto& result = read_results_[i];
+    if (!result.ok) {
+      QUIC_RESTART_FLAG_COUNT_N(
+          quic_remove_quic_socket_utils_from_packet_reader, 2, 5);
+      continue;
+    }
+
+    if (!result.packet_info.HasValue(QuicUdpPacketInfoBit::PEER_ADDRESS)) {
+      QUIC_BUG << "Unable to get peer socket address.";
+      continue;
+    }
+
+    QuicSocketAddress peer_address =
+        result.packet_info.peer_address().Normalized();
+
+    QuicIpAddress self_ip = GetSelfIpFromPacketInfo(
+        result.packet_info, peer_address.host().IsIPv6());
+    if (!self_ip.IsInitialized()) {
+      QUIC_BUG << "Unable to get self IP address.";
+      continue;
+    }
+
+    QuicWallTime walltimestamp =
+        result.packet_info.HasValue(QuicUdpPacketInfoBit::RECV_TIMESTAMP)
+            ? result.packet_info.receive_timestamp()
+            : wallnow;
+    if (!result.packet_info.HasValue(QuicUdpPacketInfoBit::RECV_TIMESTAMP)) {
+      QUIC_RESTART_FLAG_COUNT_N(
+          quic_remove_quic_socket_utils_from_packet_reader, 3, 5);
+    }
+
+    bool has_ttl = result.packet_info.HasValue(QuicUdpPacketInfoBit::TTL);
+    int ttl = has_ttl ? result.packet_info.ttl() : 0;
+    if (!has_ttl) {
+      QUIC_RESTART_FLAG_COUNT_N(
+          quic_remove_quic_socket_utils_from_packet_reader, 4, 5);
+    }
+
+    char* headers = nullptr;
+    size_t headers_length = 0;
+    if (result.packet_info.HasValue(
+            QuicUdpPacketInfoBit::GOOGLE_PACKET_HEADER)) {
+      headers = result.packet_info.google_packet_headers().buffer;
+      headers_length = result.packet_info.google_packet_headers().buffer_len;
+    } else {
+      QUIC_RESTART_FLAG_COUNT_N(
+          quic_remove_quic_socket_utils_from_packet_reader, 5, 5);
+    }
+
+    QuicReceivedPacket packet(
+        result.packet_buffer.buffer, result.packet_buffer.buffer_len,
+        clock.ConvertWallTimeToQuicTime(walltimestamp), /*owns_buffer=*/false,
+        ttl, has_ttl, headers, headers_length, /*owns_header_buffer=*/false);
+
+    QuicSocketAddress self_address(self_ip, port);
+    processor->ProcessPacket(self_address, peer_address, packet);
+  }
+
+  // We may not have read all of the packets available on the socket.
+  return packets_read == kNumPacketsPerReadMmsgCall;
+}
+
+// static
+QuicIpAddress QuicPacketReader::GetSelfIpFromPacketInfo(
+    const QuicUdpPacketInfo& packet_info,
+    bool prefer_v6_ip) {
+  if (prefer_v6_ip) {
+    if (packet_info.HasValue(QuicUdpPacketInfoBit::V6_SELF_IP)) {
+      return packet_info.self_v6_ip();
+    }
+    if (packet_info.HasValue(QuicUdpPacketInfoBit::V4_SELF_IP)) {
+      return packet_info.self_v4_ip();
+    }
+  } else {
+    if (packet_info.HasValue(QuicUdpPacketInfoBit::V4_SELF_IP)) {
+      return packet_info.self_v4_ip();
+    }
+    if (packet_info.HasValue(QuicUdpPacketInfoBit::V6_SELF_IP)) {
+      return packet_info.self_v6_ip();
+    }
+  }
+  return QuicIpAddress();
 }
 
 bool QuicPacketReader::ReadAndDispatchManyPackets(
@@ -80,6 +199,7 @@
     const QuicClock& clock,
     ProcessPacketInterface* processor,
     QuicPacketCount* packets_dropped) {
+  DCHECK(!remove_quic_socket_utils_from_packet_reader_);
 #if MMSG_MORE_NO_ANDROID
   // Re-set the length fields in case recvmmsg has changed them.
   for (int i = 0; i < kNumPacketsPerReadMmsgCall; ++i) {
@@ -196,6 +316,7 @@
     const QuicClock& clock,
     ProcessPacketInterface* processor,
     QuicPacketCount* packets_dropped) {
+  DCHECK(!GetQuicRestartFlag(quic_remove_quic_socket_utils_from_packet_reader));
   char buf[kMaxV4PacketSize];
 
   QuicSocketAddress peer_address;
diff --git a/quic/core/quic_packet_reader.h b/quic/core/quic_packet_reader.h
index 1e644aa..3c6d928 100644
--- a/quic/core/quic_packet_reader.h
+++ b/quic/core/quic_packet_reader.h
@@ -14,7 +14,10 @@
 
 #include "net/third_party/quiche/src/quic/core/quic_packets.h"
 #include "net/third_party/quiche/src/quic/core/quic_process_packet_interface.h"
+#include "net/third_party/quiche/src/quic/core/quic_udp_socket.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_aligned.h"
 #include "net/third_party/quiche/src/quic/platform/api/quic_clock.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
 #include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
 #include "net/quic/platform/impl/quic_socket_utils.h"
 
@@ -64,6 +67,14 @@
                                           ProcessPacketInterface* processor,
                                           QuicPacketCount* packets_dropped);
 
+  // Return the self ip from |packet_info|.
+  // For dual stack sockets, |packet_info| may contain both a v4 and a v6 ip, in
+  // that case, |prefer_v6_ip| is used to determine which one is used as the
+  // return value. If neither v4 nor v6 ip exists, return an uninitialized ip.
+  static QuicIpAddress GetSelfIpFromPacketInfo(
+      const QuicUdpPacketInfo& packet_info,
+      bool prefer_v6_ip);
+
 #if MMSG_MORE
   // Storage only used when recvmmsg is available.
   // TODO(danzh): change it to be a pointer to avoid the allocation on the stack
@@ -83,6 +94,17 @@
   PacketData packets_[kNumPacketsPerReadMmsgCall];
   mmsghdr mmsg_hdr_[kNumPacketsPerReadMmsgCall];
 #endif
+  struct QUIC_EXPORT_PRIVATE ReadBuffer {
+    QUIC_CACHELINE_ALIGNED char
+        control_buffer[kCmsgSpaceForReadPacket];  // For ancillary data.
+    QUIC_CACHELINE_ALIGNED char packet_buffer[kMaxIncomingPacketSize];
+  };
+  // Latched value of --quic_remove_quic_socket_utils_from_packet_reader.
+  const bool remove_quic_socket_utils_from_packet_reader_ =
+      GetQuicRestartFlag(quic_remove_quic_socket_utils_from_packet_reader);
+  QuicUdpSocketApi socket_api_;
+  std::vector<ReadBuffer> read_buffers_;
+  QuicUdpSocketApi::ReadPacketResults read_results_;
 };
 
 }  // namespace quic
diff --git a/quic/core/quic_udp_socket.h b/quic/core/quic_udp_socket.h
index b60386f..8be9e57 100644
--- a/quic/core/quic_udp_socket.h
+++ b/quic/core/quic_udp_socket.h
@@ -59,6 +59,8 @@
  public:
   BitMask64 bitmask() const { return bitmask_; }
 
+  void Reset() { bitmask_.ClearAll(); }
+
   bool HasValue(QuicUdpPacketInfoBit bit) const { return bitmask_.IsSet(bit); }
 
   QuicPacketCount dropped_packets() const {
@@ -129,6 +131,11 @@
     bitmask_.Set(QuicUdpPacketInfoBit::TTL);
   }
 
+  BufferSpan google_packet_headers() const {
+    DCHECK(HasValue(QuicUdpPacketInfoBit::GOOGLE_PACKET_HEADER));
+    return google_packet_headers_;
+  }
+
   void SetGooglePacketHeaders(BufferSpan google_packet_headers) {
     google_packet_headers_ = google_packet_headers;
     bitmask_.Set(QuicUdpPacketInfoBit::GOOGLE_PACKET_HEADER);
@@ -183,15 +190,26 @@
     QuicUdpPacketInfo packet_info;
     BufferSpan packet_buffer;
     BufferSpan control_buffer;
+
+    void Reset(size_t packet_buffer_length) {
+      ok = false;
+      packet_info.Reset();
+      packet_buffer.buffer_len = packet_buffer_length;
+    }
   };
   // Read a packet from |fd|:
   // packet_info_interested: Bitmask indicating what information caller wants to
   //                         receive into |result->packet_info|.
   // result->packet_info:    Received per packet information.
   // result->packet_buffer:  The packet buffer, to be filled with packet data.
+  //                         |result->packet_buffer.buffer_len| is set to the
+  //                         packet length on a successful return.
   // result->control_buffer: The control buffer, used by ReadPacket internally.
   //                         It is recommended to be at least 512 bytes.
   // result->ok:             True iff a packet is successfully received.
+  //
+  // If |*result| is reused for subsequent ReadPacket() calls, caller needs to
+  // call result->Reset() before each ReadPacket().
   void ReadPacket(QuicUdpSocketFd fd,
                   BitMask64 packet_info_interested,
                   ReadPacketResult* result);
diff --git a/quic/core/quic_udp_socket_test.cc b/quic/core/quic_udp_socket_test.cc
index eaa9f4c..e43fb10 100644
--- a/quic/core/quic_udp_socket_test.cc
+++ b/quic/core/quic_udp_socket_test.cc
@@ -123,6 +123,20 @@
   char server_control_buffer_[512] = {0};
 };
 
+TEST_F(QuicUdpSocketTest, ReadPacketResultReset) {
+  QuicUdpSocketApi::ReadPacketResult result;
+  result.packet_info.SetDroppedPackets(100);
+  result.packet_buffer.buffer_len = 100;
+  result.ok = true;
+
+  result.Reset(/*packet_buffer_length=*/200);
+
+  EXPECT_FALSE(result.ok);
+  EXPECT_FALSE(
+      result.packet_info.HasValue(QuicUdpPacketInfoBit::DROPPED_PACKETS));
+  EXPECT_EQ(200u, result.packet_buffer.buffer_len);
+}
+
 TEST_F(QuicUdpSocketTest, ReadPacketOnly) {
   const size_t kPacketSize = 512;
   memset(client_packet_buffer_, '-', kPacketSize);
diff --git a/quic/core/quic_utils.h b/quic/core/quic_utils.h
index a0e0452..04858f0 100644
--- a/quic/core/quic_utils.h
+++ b/quic/core/quic_utils.h
@@ -243,6 +243,8 @@
     return (MakeMask(bit) & mask_) != 0;
   }
 
+  void ClearAll() { mask_ = 0; }
+
   static constexpr size_t NumBits() { return 8 * sizeof(Mask); }
 
   friend bool operator==(const BitMask& lhs, const BitMask& rhs) {
diff --git a/quic/core/quic_utils_test.cc b/quic/core/quic_utils_test.cc
index aac0fd8..e6fe1a2 100644
--- a/quic/core/quic_utils_test.cc
+++ b/quic/core/quic_utils_test.cc
@@ -288,6 +288,11 @@
   EXPECT_TRUE(mask.IsSet(TestEnumClassBit::BIT_ZERO));
   EXPECT_FALSE(mask.IsSet(TestEnumClassBit::BIT_ONE));
   EXPECT_TRUE(mask.IsSet(TestEnumClassBit::BIT_TWO));
+
+  mask.ClearAll();
+  EXPECT_FALSE(mask.IsSet(TestEnumClassBit::BIT_ZERO));
+  EXPECT_FALSE(mask.IsSet(TestEnumClassBit::BIT_ONE));
+  EXPECT_FALSE(mask.IsSet(TestEnumClassBit::BIT_TWO));
 }
 
 TEST(QuicBitMaskTest, Enum) {
@@ -295,6 +300,11 @@
   EXPECT_FALSE(mask.IsSet(TEST_BIT_0));
   EXPECT_TRUE(mask.IsSet(TEST_BIT_1));
   EXPECT_TRUE(mask.IsSet(TEST_BIT_2));
+
+  mask.ClearAll();
+  EXPECT_FALSE(mask.IsSet(TEST_BIT_0));
+  EXPECT_FALSE(mask.IsSet(TEST_BIT_1));
+  EXPECT_FALSE(mask.IsSet(TEST_BIT_2));
 }
 
 TEST(QuicBitMaskTest, Integer) {