Send QUIC GOAWAY after given time even if connection not idle.

Note that in HTTP/2, timeout is checked each time a request is terminated.
However, I chose to use a timer for QUIC instead.  This will allow GOAWAY frame
to be sent even if the only active request is hanging for a long time.

Protected by FLAGS_quic_reloadable_flag_quic_max_age_send_goaway.

PiperOrigin-RevId: 341853883
Change-Id: I0644e7e17637fdf9c6694073d5d388632c90337a
diff --git a/quic/core/quic_error_codes.cc b/quic/core/quic_error_codes.cc
index a57ded8..9abde9f 100644
--- a/quic/core/quic_error_codes.cc
+++ b/quic/core/quic_error_codes.cc
@@ -255,6 +255,7 @@
     RETURN_STRING_LITERAL(QUIC_MISSING_WRITE_KEYS);
     RETURN_STRING_LITERAL(QUIC_KEY_UPDATE_ERROR);
     RETURN_STRING_LITERAL(QUIC_AEAD_LIMIT_REACHED);
+    RETURN_STRING_LITERAL(QUIC_MAX_AGE_TIMEOUT);
 
     RETURN_STRING_LITERAL(QUIC_LAST_ERROR);
     // Intentionally have no default case, so we'll break the build
@@ -713,6 +714,8 @@
       return {true, static_cast<uint64_t>(KEY_UPDATE_ERROR)};
     case QUIC_AEAD_LIMIT_REACHED:
       return {true, static_cast<uint64_t>(AEAD_LIMIT_REACHED)};
+    case QUIC_MAX_AGE_TIMEOUT:
+      return {false, static_cast<uint64_t>(QuicHttp3ErrorCode::INTERNAL_ERROR)};
     case QUIC_LAST_ERROR:
       return {false, static_cast<uint64_t>(QUIC_LAST_ERROR)};
   }
diff --git a/quic/core/quic_error_codes.h b/quic/core/quic_error_codes.h
index 74ab936..a1cd7a6 100644
--- a/quic/core/quic_error_codes.h
+++ b/quic/core/quic_error_codes.h
@@ -556,8 +556,15 @@
   // AEAD algorithm used by the given connection.
   QUIC_AEAD_LIMIT_REACHED = 173,
 
+  // Connection reached maximum age (regardless of activity), no new requests
+  // are accepted.  This error code is sent in transport layer GOAWAY frame when
+  // using gQUIC, and only used internally when using HTTP/3.  Active requests
+  // are still served, after which connection will be closed due to idle
+  // timeout.
+  QUIC_MAX_AGE_TIMEOUT = 191,
+
   // No error. Used as bound while iterating.
-  QUIC_LAST_ERROR = 191,
+  QUIC_LAST_ERROR = 192,
 };
 // QuicErrorCodes is encoded as four octets on-the-wire when doing Google QUIC,
 // or a varint62 when doing IETF QUIC. Ensure that its value does not exceed
diff --git a/quic/core/quic_flags_list.h b/quic/core/quic_flags_list.h
index ca6a3e1..e6ce646 100644
--- a/quic/core/quic_flags_list.h
+++ b/quic/core/quic_flags_list.h
@@ -60,6 +60,7 @@
 QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_granular_qpack_error_codes, false)
 QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_key_update_supported, true)
 QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_let_connection_handle_pings, true)
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_max_age_send_goaway, false)
 QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_new_priority_update_frame, true)
 QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_process_undecryptable_packets_after_async_decrypt_callback, true)
 QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_record_received_min_ack_delay, true)