Refactor quic's RawPacketComposer to share more code for CMSG with GfeQuicGsoBatchWriter using the QuicMsgHdr class.

(Requested in cl/641013411 to address duplicate logic added in that CL.)

PiperOrigin-RevId: 642736478
diff --git a/quiche/quic/core/batch_writer/quic_gso_batch_writer.h b/quiche/quic/core/batch_writer/quic_gso_batch_writer.h
index b409bf5..d9f0cb6 100644
--- a/quiche/quic/core/batch_writer/quic_gso_batch_writer.h
+++ b/quiche/quic/core/batch_writer/quic_gso_batch_writer.h
@@ -5,7 +5,10 @@
 #ifndef QUICHE_QUIC_CORE_BATCH_WRITER_QUIC_GSO_BATCH_WRITER_H_
 #define QUICHE_QUIC_CORE_BATCH_WRITER_QUIC_GSO_BATCH_WRITER_H_
 
+#include <cstddef>
+
 #include "quiche/quic/core/batch_writer/quic_batch_writer_base.h"
+#include "quiche/quic/core/quic_linux_socket_utils.h"
 
 namespace quic {
 
@@ -71,11 +74,12 @@
                               /*num_packets_sent=*/0, /*bytes_written=*/0};
     WriteResult& write_result = result.write_result;
 
-    int total_bytes = batch_buffer().SizeInUse();
+    size_t total_bytes = batch_buffer().SizeInUse();
     const BufferedWrite& first = buffered_writes().front();
     char cbuf[CmsgSpace];
-    QuicMsgHdr hdr(first.buffer, total_bytes, first.peer_address, cbuf,
-                   sizeof(cbuf));
+    iovec iov{const_cast<char*>(first.buffer), total_bytes};
+    QuicMsgHdr hdr(&iov, 1, cbuf, sizeof(cbuf));
+    hdr.SetPeerAddress(first.peer_address);
 
     uint16_t gso_size = buffered_writes().size() > 1 ? first.buf_len : 0;
     cmsg_builder(&hdr, first.self_address, gso_size, first.release_time,
diff --git a/quiche/quic/core/quic_linux_socket_utils.cc b/quiche/quic/core/quic_linux_socket_utils.cc
index 3dcc6a9..b10908e 100644
--- a/quiche/quic/core/quic_linux_socket_utils.cc
+++ b/quiche/quic/core/quic_linux_socket_utils.cc
@@ -7,6 +7,7 @@
 #include <linux/net_tstamp.h>
 #include <netinet/in.h>
 
+#include <cstddef>
 #include <cstdint>
 #include <string>
 
@@ -14,17 +15,24 @@
 #include "quiche/quic/platform/api/quic_ip_address.h"
 #include "quiche/quic/platform/api/quic_logging.h"
 #include "quiche/quic/platform/api/quic_socket_address.h"
+#include "quiche/common/platform/api/quiche_logging.h"
 
 namespace quic {
 
-QuicMsgHdr::QuicMsgHdr(const char* buffer, size_t buf_len,
-                       const QuicSocketAddress& peer_address, char* cbuf,
-                       size_t cbuf_size)
-    : iov_{const_cast<char*>(buffer), buf_len},
-      cbuf_(cbuf),
-      cbuf_size_(cbuf_size),
-      cmsg_(nullptr) {
-  // Only support unconnected sockets.
+QuicMsgHdr::QuicMsgHdr(iovec* iov, size_t iov_len, char* cbuf, size_t cbuf_size)
+    : cbuf_(cbuf), cbuf_size_(cbuf_size), cmsg_(nullptr) {
+  hdr_.msg_name = nullptr;
+  hdr_.msg_namelen = 0;
+
+  hdr_.msg_iov = iov;
+  hdr_.msg_iovlen = iov_len;
+  hdr_.msg_flags = 0;
+
+  hdr_.msg_control = nullptr;
+  hdr_.msg_controllen = 0;
+}
+
+void QuicMsgHdr::SetPeerAddress(const QuicSocketAddress& peer_address) {
   QUICHE_DCHECK(peer_address.IsInitialized());
 
   raw_peer_address_ = peer_address.generic_address();
@@ -32,13 +40,6 @@
   hdr_.msg_namelen = raw_peer_address_.ss_family == AF_INET
                          ? sizeof(sockaddr_in)
                          : sizeof(sockaddr_in6);
-
-  hdr_.msg_iov = &iov_;
-  hdr_.msg_iovlen = 1;
-  hdr_.msg_flags = 0;
-
-  hdr_.msg_control = nullptr;
-  hdr_.msg_controllen = 0;
 }
 
 void QuicMsgHdr::SetIpInNextCmsg(const QuicIpAddress& self_address) {
diff --git a/quiche/quic/core/quic_linux_socket_utils.h b/quiche/quic/core/quic_linux_socket_utils.h
index a0e338d..f125cba 100644
--- a/quiche/quic/core/quic_linux_socket_utils.h
+++ b/quiche/quic/core/quic_linux_socket_utils.h
@@ -24,6 +24,7 @@
 #include "quiche/quic/platform/api/quic_ip_address.h"
 #include "quiche/quic/platform/api/quic_logging.h"
 #include "quiche/quic/platform/api/quic_socket_address.h"
+#include "quiche/common/platform/api/quiche_export.h"
 #include "quiche/common/quiche_callbacks.h"
 
 #ifndef SOL_UDP
@@ -77,9 +78,12 @@
 //   QuicLinuxSocketUtils::WritePacket(fd, hdr);
 class QUICHE_EXPORT QuicMsgHdr {
  public:
-  QuicMsgHdr(const char* buffer, size_t buf_len,
-             const QuicSocketAddress& peer_address, char* cbuf,
-             size_t cbuf_size);
+  // Creates a QuicMsgHeader without setting the peer address in
+  // msghdr.msg_name. This can be set later with SetPeerAddress().
+  QuicMsgHdr(iovec* iov, size_t iov_len, char* cbuf, size_t cbuf_size);
+
+  // Sets the peer address in msghdr.msg_name.
+  void SetPeerAddress(const QuicSocketAddress& peer_address);
 
   // Set IP info in the next cmsg. Both IPv4 and IPv6 are supported.
   void SetIpInNextCmsg(const QuicIpAddress& self_address);
@@ -97,7 +101,6 @@
                                 size_t data_size);
 
   msghdr hdr_;
-  iovec iov_;
   sockaddr_storage raw_peer_address_;
   char* cbuf_;
   const size_t cbuf_size_;
diff --git a/quiche/quic/core/quic_linux_socket_utils_test.cc b/quiche/quic/core/quic_linux_socket_utils_test.cc
index cdf41c4..93ebf01 100644
--- a/quiche/quic/core/quic_linux_socket_utils_test.cc
+++ b/quiche/quic/core/quic_linux_socket_utils_test.cc
@@ -134,9 +134,11 @@
 TEST_F(QuicLinuxSocketUtilsTest, QuicMsgHdr) {
   QuicSocketAddress peer_addr(QuicIpAddress::Loopback4(), 1234);
   char packet_buf[1024];
+  iovec iov{packet_buf, sizeof(packet_buf)};
 
   {
-    QuicMsgHdr quic_hdr(packet_buf, sizeof(packet_buf), peer_addr, nullptr, 0);
+    QuicMsgHdr quic_hdr(&iov, 1, nullptr, 0);
+    quic_hdr.SetPeerAddress(peer_addr);
     CheckMsghdrWithoutCbuf(quic_hdr.hdr(), packet_buf, sizeof(packet_buf),
                            peer_addr);
   }
@@ -145,8 +147,8 @@
     QuicIpAddress self_addr =
         is_ipv4 ? QuicIpAddress::Loopback4() : QuicIpAddress::Loopback6();
     alignas(cmsghdr) char cbuf[kCmsgSpaceForIp + kCmsgSpaceForTTL];
-    QuicMsgHdr quic_hdr(packet_buf, sizeof(packet_buf), peer_addr, cbuf,
-                        sizeof(cbuf));
+    QuicMsgHdr quic_hdr(&iov, 1, cbuf, sizeof(cbuf));
+    quic_hdr.SetPeerAddress(peer_addr);
     msghdr* hdr = const_cast<msghdr*>(quic_hdr.hdr());
 
     EXPECT_EQ(nullptr, hdr->msg_control);