Add version-aware QuicConnectionCloseFrame constructor

Adds a version-aware constructor for QuicConnectionCloseFrames. Based
on the version, this constructor handles generation of the correct
close codes and frame types.

gfe-relnote: N/A moves around existing function (some version-99 protected)
PiperOrigin-RevId: 267647428
Change-Id: I24aabc9abc1b803610b34d9f8fac60133bd1368c
diff --git a/quic/core/frames/quic_connection_close_frame.cc b/quic/core/frames/quic_connection_close_frame.cc
index 63e0aee..8f1fe24 100644
--- a/quic/core/frames/quic_connection_close_frame.cc
+++ b/quic/core/frames/quic_connection_close_frame.cc
@@ -52,6 +52,33 @@
   DCHECK_LE(transport_error_code, kMaxIetfVarInt);
 }
 
+QuicConnectionCloseFrame::QuicConnectionCloseFrame(
+    QuicTransportVersion transport_version,
+    QuicErrorCode error_code,
+    std::string error_phrase,
+    uint64_t frame_type)
+    : extracted_error_code(error_code), error_details(error_phrase) {
+  if (!VersionHasIetfQuicFrames(transport_version)) {
+    close_type = GOOGLE_QUIC_CONNECTION_CLOSE;
+    quic_error_code = error_code;
+    transport_close_frame_type = 0;
+    return;
+  }
+  QuicErrorCodeToIetfMapping mapping =
+      QuicErrorCodeToTransportErrorCode(error_code);
+  if (mapping.is_transport_close_) {
+    // Maps to a transport close
+    close_type = IETF_QUIC_TRANSPORT_CONNECTION_CLOSE;
+    transport_error_code = mapping.transport_error_code_;
+    transport_close_frame_type = frame_type;
+    return;
+  }
+  // Maps to an application close.
+  close_type = IETF_QUIC_APPLICATION_CONNECTION_CLOSE;
+  application_error_code = mapping.application_error_code_;
+  transport_close_frame_type = 0;
+}
+
 std::ostream& operator<<(
     std::ostream& os,
     const QuicConnectionCloseFrame& connection_close_frame) {
diff --git a/quic/core/frames/quic_connection_close_frame.h b/quic/core/frames/quic_connection_close_frame.h
index b0cef45..9b6fdd4 100644
--- a/quic/core/frames/quic_connection_close_frame.h
+++ b/quic/core/frames/quic_connection_close_frame.h
@@ -10,6 +10,7 @@
 
 #include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
 #include "net/third_party/quiche/src/quic/core/quic_types.h"
+#include "net/third_party/quiche/src/quic/core/quic_versions.h"
 #include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
 
 namespace quic {
@@ -17,6 +18,15 @@
 struct QUIC_EXPORT_PRIVATE QuicConnectionCloseFrame {
   QuicConnectionCloseFrame();
 
+  // Builds a connection close frame based on the transport version
+  // and the mapping of error_code. THIS IS THE PREFERRED C'TOR
+  // TO USE IF YOU NEED TO CREATE A CONNECTION-CLOSE-FRAME AND
+  // HAVE IT BE CORRECT FOR THE VERSION AND CODE MAPPINGS.
+  QuicConnectionCloseFrame(QuicTransportVersion transport_version,
+                           QuicErrorCode error_code,
+                           std::string error_phrase,
+                           uint64_t transport_close_frame_type);
+
   // TODO(fkastenholz): After migration to supporting IETF QUIC, this probably
   // should be deprecated.
   QuicConnectionCloseFrame(QuicErrorCode error_code, std::string error_details);
diff --git a/quic/core/quic_connection.cc b/quic/core/quic_connection.cc
index 269fe7f..52b5f70 100644
--- a/quic/core/quic_connection.cc
+++ b/quic/core/quic_connection.cc
@@ -2858,21 +2858,9 @@
     SendAck();
   }
   QuicConnectionCloseFrame* frame;
-  if (VersionHasIetfQuicFrames(transport_version())) {
-    QuicErrorCodeToIetfMapping mapping =
-        QuicErrorCodeToTransportErrorCode(error);
-    if (mapping.is_transport_close_) {
-      frame = new QuicConnectionCloseFrame(
-          error, details, mapping.transport_error_code_,
-          framer_.current_received_frame_type());
-    } else {
-      // Maps to an application close.
-      frame = new QuicConnectionCloseFrame(error, details,
-                                           mapping.application_error_code_);
-    }
-  } else {
-    frame = new QuicConnectionCloseFrame(error, details);
-  }
+
+  frame = new QuicConnectionCloseFrame(transport_version(), error, details,
+                                       framer_.current_received_frame_type());
   packet_generator_.ConsumeRetransmittableControlFrame(QuicFrame(frame));
   packet_generator_.FlushAllQueuedFrames();
   if (GetQuicReloadableFlag(quic_clear_queued_packets_on_connection_close)) {
diff --git a/quic/core/quic_connection_test.cc b/quic/core/quic_connection_test.cc
index 9fc985f..6df0f7d 100644
--- a/quic/core/quic_connection_test.cc
+++ b/quic/core/quic_connection_test.cc
@@ -1457,27 +1457,9 @@
     header.packet_number = QuicPacketNumber(number);
 
     QuicErrorCode kQuicErrorCode = QUIC_PEER_GOING_AWAY;
-    // This QuicConnectionCloseFrame will default to being for a Google QUIC
-    // close. If doing IETF QUIC then set fields appropriately for CC/T or CC/A,
-    // depending on the mapping.
-    QuicConnectionCloseFrame qccf(kQuicErrorCode, "");
-    if (VersionHasIetfQuicFrames(peer_framer_.transport_version())) {
-      QuicErrorCodeToIetfMapping mapping =
-          QuicErrorCodeToTransportErrorCode(kQuicErrorCode);
-      if (mapping.is_transport_close_) {
-        // Maps to a transport close
-        qccf.close_type = IETF_QUIC_TRANSPORT_CONNECTION_CLOSE;
-        qccf.transport_error_code = mapping.transport_error_code_;
-        // Frame type is not important for the tests that invoke this method.
-        qccf.transport_close_frame_type = 0;
-      } else {
-        // Maps to an application close.
-        qccf.close_type = IETF_QUIC_APPLICATION_CONNECTION_CLOSE;
-        qccf.application_error_code = mapping.application_error_code_;
-      }
-      qccf.extracted_error_code = kQuicErrorCode;
-    }
-
+    QuicConnectionCloseFrame qccf(peer_framer_.transport_version(),
+                                  kQuicErrorCode, "",
+                                  /*transport_close_frame_type=*/0);
     QuicFrames frames;
     frames.push_back(QuicFrame(&qccf));
     return ConstructPacket(header, frames);
@@ -7020,25 +7002,9 @@
   // This QuicConnectionCloseFrame will default to being for a Google QUIC
   // close. If doing IETF QUIC then set fields appropriately for CC/T or CC/A,
   // depending on the mapping.
-  QuicConnectionCloseFrame qccf(kQuicErrorCode, "");
-  if (VersionHasIetfQuicFrames(peer_framer_.transport_version())) {
-    QuicErrorCodeToIetfMapping mapping =
-        QuicErrorCodeToTransportErrorCode(kQuicErrorCode);
-    if (mapping.is_transport_close_) {
-      // Maps to a transport close
-      qccf.close_type = IETF_QUIC_TRANSPORT_CONNECTION_CLOSE;
-      qccf.transport_error_code = mapping.transport_error_code_;
-      // TODO(fkastenholz) need to change "0" to get the frame type currently
-      // being processed so that it can be inserted into the frame.
-      qccf.transport_close_frame_type = 0;
-    } else {
-      // Maps to an application close.
-      qccf.close_type = IETF_QUIC_APPLICATION_CONNECTION_CLOSE;
-      qccf.application_error_code = mapping.application_error_code_;
-    }
-    //    qccf.extracted_error_code = kQuicErrorCode;
-  }
-
+  QuicConnectionCloseFrame qccf(peer_framer_.transport_version(),
+                                kQuicErrorCode, "",
+                                /*transport_close_frame_type=*/0);
   QuicFrames frames;
   frames.push_back(QuicFrame(frame1_));
   frames.push_back(QuicFrame(&qccf));
@@ -8699,25 +8665,10 @@
   EXPECT_EQ(Perspective::IS_CLIENT, connection_.perspective());
   const QuicErrorCode kErrorCode = QUIC_INTERNAL_ERROR;
   std::unique_ptr<QuicConnectionCloseFrame> connection_close_frame(
-      new QuicConnectionCloseFrame(kErrorCode, ""));
-  if (VersionHasIetfQuicFrames(connection_.transport_version())) {
-    QuicErrorCodeToIetfMapping mapping =
-        QuicErrorCodeToTransportErrorCode(kErrorCode);
-    if (mapping.is_transport_close_) {
-      // Maps to a transport close
-      connection_close_frame->close_type = IETF_QUIC_TRANSPORT_CONNECTION_CLOSE;
-      connection_close_frame->transport_error_code =
-          mapping.transport_error_code_;
-      connection_close_frame->transport_close_frame_type = 0;
-    } else {
-      // Maps to an application close.
-      connection_close_frame->close_type =
-          IETF_QUIC_APPLICATION_CONNECTION_CLOSE;
-      connection_close_frame->application_error_code =
-          mapping.application_error_code_;
-    }
-    connection_close_frame->extracted_error_code = kErrorCode;
-  }
+      new QuicConnectionCloseFrame(connection_.transport_version(), kErrorCode,
+                                   "",
+                                   /*transport_close_frame_type=*/0));
+
   // Received 2 packets.
   QuicFrame frame;
   if (QuicVersionUsesCryptoFrames(connection_.transport_version())) {
diff --git a/quic/core/quic_dispatcher.cc b/quic/core/quic_dispatcher.cc
index 94dc3bf..75524aa 100644
--- a/quic/core/quic_dispatcher.cc
+++ b/quic/core/quic_dispatcher.cc
@@ -133,25 +133,9 @@
   void CloseConnection(QuicErrorCode error_code,
                        const std::string& error_details,
                        bool ietf_quic) {
-    QuicConnectionCloseFrame* frame =
-        new QuicConnectionCloseFrame(error_code, error_details);
-    if (VersionHasIetfQuicFrames(framer_.transport_version())) {
-      QuicErrorCodeToIetfMapping mapping =
-          QuicErrorCodeToTransportErrorCode(error_code);
-      if (mapping.is_transport_close_) {
-        // Maps to a transport close
-        frame->close_type = IETF_QUIC_TRANSPORT_CONNECTION_CLOSE;
-        frame->transport_error_code = mapping.transport_error_code_;
-        // If closing the connection in the stateless terminator then there is
-        // no frame that is being processed.
-        frame->transport_close_frame_type = 0;
-      } else {
-        // Maps to an application close.
-        frame->close_type = IETF_QUIC_APPLICATION_CONNECTION_CLOSE;
-        frame->application_error_code = mapping.application_error_code_;
-      }
-      frame->extracted_error_code = error_code;
-    }
+    QuicConnectionCloseFrame* frame = new QuicConnectionCloseFrame(
+        framer_.transport_version(), error_code, error_details,
+        /*transport_close_frame_type=*/0);
 
     if (!creator_.AddSavedFrame(QuicFrame(frame), NOT_RETRANSMISSION)) {
       QUIC_BUG << "Unable to add frame to an empty packet";
diff --git a/quic/core/quic_packet_creator_test.cc b/quic/core/quic_packet_creator_test.cc
index ff9960f..1da89ba 100644
--- a/quic/core/quic_packet_creator_test.cc
+++ b/quic/core/quic_packet_creator_test.cc
@@ -576,10 +576,9 @@
 }
 
 TEST_P(QuicPacketCreatorTest, SerializeConnectionClose) {
-  QuicConnectionCloseFrame frame(QUIC_NO_ERROR, "error");
-  if (VersionHasIetfQuicFrames(GetParam().version.transport_version)) {
-    frame.close_type = IETF_QUIC_TRANSPORT_CONNECTION_CLOSE;
-  }
+  QuicConnectionCloseFrame frame(GetParam().version.transport_version,
+                                 QUIC_NO_ERROR, "error",
+                                 /*transport_close_frame_type=*/0);
 
   QuicFrames frames;
   frames.push_back(QuicFrame(&frame));
diff --git a/quic/core/quic_packet_generator_test.cc b/quic/core/quic_packet_generator_test.cc
index bd66cb1..c60bac2 100644
--- a/quic/core/quic_packet_generator_test.cc
+++ b/quic/core/quic_packet_generator_test.cc
@@ -1291,24 +1291,10 @@
   char buf[2000] = {};
   QuicStringPiece error_details(buf, 2000);
   const QuicErrorCode kQuicErrorCode = QUIC_PACKET_WRITE_ERROR;
-  QuicConnectionCloseFrame* frame =
-      new QuicConnectionCloseFrame(kQuicErrorCode, std::string(error_details));
-  if (VersionHasIetfQuicFrames(framer_.transport_version())) {
-    QuicErrorCodeToIetfMapping mapping =
-        QuicErrorCodeToTransportErrorCode(kQuicErrorCode);
-    if (mapping.is_transport_close_) {
-      // Maps to a transport close
-      frame->close_type = IETF_QUIC_TRANSPORT_CONNECTION_CLOSE;
-      frame->transport_error_code = mapping.transport_error_code_;
-      // Frame type is not important for the tests that invoke this method.
-      frame->transport_close_frame_type = 0;
-    } else {
-      // Maps to an application close.
-      frame->close_type = IETF_QUIC_APPLICATION_CONNECTION_CLOSE;
-      frame->application_error_code = mapping.application_error_code_;
-    }
-    frame->extracted_error_code = kQuicErrorCode;
-  }
+
+  QuicConnectionCloseFrame* frame = new QuicConnectionCloseFrame(
+      framer_.transport_version(), kQuicErrorCode, std::string(error_details),
+      /*transport_close_frame_type=*/0);
   generator_.ConsumeRetransmittableControlFrame(QuicFrame(frame),
                                                 /*bundle_ack=*/false);
   EXPECT_TRUE(generator_.HasPendingFrames());