Internal QUICHE change

PiperOrigin-RevId: 243129330
Change-Id: If138c05a357c9db30160e31b0238a7d29992ff0f
diff --git a/quic/core/quic_dispatcher.cc b/quic/core/quic_dispatcher.cc
index c9f5fbf..57924ca 100644
--- a/quic/core/quic_dispatcher.cc
+++ b/quic/core/quic_dispatcher.cc
@@ -1066,10 +1066,6 @@
                   << " because of " << result;
 }
 
-void QuicDispatcher::OnConnectionRejectedStatelessly() {}
-
-void QuicDispatcher::OnConnectionClosedStatelessly(QuicErrorCode error) {}
-
 bool QuicDispatcher::ShouldAttemptCheapStatelessRejection() {
   return true;
 }
@@ -1267,7 +1263,8 @@
                                              time_wait_list_manager_.get());
     terminator.CloseConnection(QUIC_HANDSHAKE_FAILED, validator.error_details(),
                                form != GOOGLE_QUIC_PACKET);
-    OnConnectionClosedStatelessly(QUIC_HANDSHAKE_FAILED);
+    QuicSession::RecordConnectionCloseAtServer(
+        QUIC_HANDSHAKE_FAILED, ConnectionCloseSource::FROM_SELF);
     ProcessUnauthenticatedHeaderFate(kFateTimeWait, connection_id, form,
                                      version);
     return;
@@ -1372,6 +1369,9 @@
       terminator.RejectConnection(
           rejector->reply().GetSerialized().AsStringPiece(),
           form != GOOGLE_QUIC_PACKET);
+      QuicSession::RecordConnectionCloseAtServer(
+          QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT,
+          ConnectionCloseSource::FROM_SELF);
       OnConnectionRejectedStatelessly();
       fate = kFateTimeWait;
       break;
diff --git a/quic/core/quic_dispatcher.h b/quic/core/quic_dispatcher.h
index 3329405..62b7ebb 100644
--- a/quic/core/quic_dispatcher.h
+++ b/quic/core/quic_dispatcher.h
@@ -202,10 +202,7 @@
                                          const ParsedQuicVersion& version) = 0;
 
   // Called when a connection is rejected statelessly.
-  virtual void OnConnectionRejectedStatelessly();
-
-  // Called when a connection is closed statelessly.
-  virtual void OnConnectionClosedStatelessly(QuicErrorCode error);
+  virtual void OnConnectionRejectedStatelessly() {}
 
   // Returns true if cheap stateless rejection should be attempted.
   virtual bool ShouldAttemptCheapStatelessRejection();
diff --git a/quic/core/quic_error_codes.h b/quic/core/quic_error_codes.h
index 9954134..2004a08 100644
--- a/quic/core/quic_error_codes.h
+++ b/quic/core/quic_error_codes.h
@@ -7,6 +7,7 @@
 
 #include <cstdint>
 #include <limits>
+#include <string>
 
 #include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
 
@@ -349,6 +350,16 @@
 // Returns the name of the QuicErrorCode as a char*
 QUIC_EXPORT const char* QuicErrorCodeToString(QuicErrorCode error);
 
+QUIC_EXPORT_PRIVATE inline std::string HistogramEnumString(
+    QuicErrorCode enum_value) {
+  return QuicErrorCodeToString(enum_value);
+}
+
+QUIC_EXPORT_PRIVATE inline std::string HistogramEnumDescription(
+    QuicErrorCode dummy) {
+  return "cause";
+}
+
 }  // namespace quic
 
 #endif  // QUICHE_QUIC_CORE_QUIC_ERROR_CODES_H_
diff --git a/quic/core/quic_session.cc b/quic/core/quic_session.cc
index 01d6feb..d857572 100644
--- a/quic/core/quic_session.cc
+++ b/quic/core/quic_session.cc
@@ -16,6 +16,7 @@
 #include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
 #include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
 #include "net/third_party/quiche/src/quic/platform/api/quic_map_util.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_server_stats.h"
 #include "net/third_party/quiche/src/quic/platform/api/quic_stack_trace.h"
 #include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
 
@@ -288,10 +289,30 @@
                 << ", " << message;
 }
 
+// static
+void QuicSession::RecordConnectionCloseAtServer(QuicErrorCode error,
+                                                ConnectionCloseSource source) {
+  if (error != QUIC_NO_ERROR) {
+    if (source == ConnectionCloseSource::FROM_SELF) {
+      QUIC_SERVER_HISTOGRAM_ENUM(
+          "quic_server_connection_close_errors", error, QUIC_LAST_ERROR,
+          "QuicErrorCode for server-closed connections.");
+    } else {
+      QUIC_SERVER_HISTOGRAM_ENUM(
+          "quic_client_connection_close_errors", error, QUIC_LAST_ERROR,
+          "QuicErrorCode for client-closed connections.");
+    }
+  }
+}
+
 void QuicSession::OnConnectionClosed(QuicErrorCode error,
                                      const std::string& error_details,
                                      ConnectionCloseSource source) {
   DCHECK(!connection_->connected());
+  if (perspective() == Perspective::IS_SERVER) {
+    RecordConnectionCloseAtServer(error, source);
+  }
+
   if (error_ == QUIC_NO_ERROR) {
     error_ = error;
   }
diff --git a/quic/core/quic_session.h b/quic/core/quic_session.h
index b13f627..a9fb992 100644
--- a/quic/core/quic_session.h
+++ b/quic/core/quic_session.h
@@ -17,6 +17,7 @@
 #include "net/third_party/quiche/src/quic/core/quic_connection.h"
 #include "net/third_party/quiche/src/quic/core/quic_control_frame_manager.h"
 #include "net/third_party/quiche/src/quic/core/quic_crypto_stream.h"
+#include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
 #include "net/third_party/quiche/src/quic/core/quic_packet_creator.h"
 #include "net/third_party/quiche/src/quic/core/quic_packets.h"
 #include "net/third_party/quiche/src/quic/core/quic_stream.h"
@@ -401,6 +402,12 @@
                                   QuicStreamOffset bytes_written,
                                   bool close_write_side_only);
 
+  // Record errors when a connection is closed at the server side, should only
+  // be called from server's perspective.
+  // Noop if |error| is QUIC_NO_ERROR.
+  static void RecordConnectionCloseAtServer(QuicErrorCode error,
+                                            ConnectionCloseSource source);
+
  protected:
   using StaticStreamMap = QuicSmallMap<QuicStreamId, QuicStream*, 2>;