Let TlsClientHandshaker handle connection close during config negotiation.

Client side change only. not protected.

PiperOrigin-RevId: 310978120
Change-Id: I0f373ffe0874a09c3bbf15901dd8de6ad938a264
diff --git a/quic/core/tls_client_handshaker.cc b/quic/core/tls_client_handshaker.cc
index a6aee11..d7fa95b 100644
--- a/quic/core/tls_client_handshaker.cc
+++ b/quic/core/tls_client_handshaker.cc
@@ -248,6 +248,11 @@
   }
 
   session()->OnConfigNegotiated();
+  if (state_ == STATE_CONNECTION_CLOSED) {
+    *error_details =
+        "Session closed the connection when parsing negotiated config.";
+    return false;
+  }
   return true;
 }
 
diff --git a/quic/core/tls_client_handshaker_test.cc b/quic/core/tls_client_handshaker_test.cc
index 2629bd4..85492b8 100644
--- a/quic/core/tls_client_handshaker_test.cc
+++ b/quic/core/tls_client_handshaker_test.cc
@@ -12,8 +12,10 @@
 #include "net/third_party/quiche/src/quic/core/quic_server_id.h"
 #include "net/third_party/quiche/src/quic/core/quic_utils.h"
 #include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
 #include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
 #include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h"
+#include "net/third_party/quiche/src/quic/test_tools/quic_session_peer.h"
 #include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
 #include "net/third_party/quiche/src/quic/test_tools/simple_session_cache.h"
 #include "net/third_party/quiche/src/quic/tools/fake_proof_verifier.h"
@@ -167,6 +169,7 @@
         server_compressed_certs_cache_(
             QuicCompressedCertsCache::kQuicCompressedCertsCacheSize) {
     SetQuicReloadableFlag(quic_enable_tls_resumption, true);
+    SetQuicReloadableFlag(quic_enable_zero_rtt_for_tls, true);
     server_crypto_config_ = crypto_test_utils::CryptoServerConfigForTesting();
     CreateConnection();
   }
@@ -412,6 +415,37 @@
   EXPECT_EQ(server_stream()->crypto_negotiated_params().sni, "");
 }
 
+TEST_P(TlsClientHandshakerTest, BadTransportParams) {
+  if (!connection_->version().UsesHttp3()) {
+    return;
+  }
+  SetQuicReloadableFlag(quic_notify_handshaker_on_connection_close, true);
+  // Finish establishing the first connection:
+  CompleteCryptoHandshake();
+
+  // Create a second connection
+  CreateConnection();
+
+  stream()->CryptoConnect();
+  auto* id_manager = QuicSessionPeer::v99_streamid_manager(session_.get());
+  EXPECT_EQ(kDefaultMaxStreamsPerConnection,
+            id_manager->max_outgoing_bidirectional_streams());
+  QuicConfig config;
+  config.SetMaxBidirectionalStreamsToSend(
+      config.GetMaxBidirectionalStreamsToSend() - 1);
+
+  EXPECT_CALL(*connection_, CloseConnection(QUIC_MAX_STREAMS_ERROR, _, _))
+      .WillOnce(testing::Invoke(connection_,
+                                &MockQuicConnection::ReallyCloseConnection));
+  // Close connection will be called again in the handshaker, but this will be
+  // no-op as the connection is already closed.
+  EXPECT_CALL(*connection_, CloseConnection(QUIC_HANDSHAKE_FAILED, _, _));
+
+  crypto_test_utils::HandshakeWithFakeServer(
+      &config, server_crypto_config_.get(), &server_helper_, &alarm_factory_,
+      connection_, stream(), AlpnForVersion(connection_->version()));
+}
+
 }  // namespace
 }  // namespace test
 }  // namespace quic
diff --git a/quic/test_tools/crypto_test_utils.cc b/quic/test_tools/crypto_test_utils.cc
index 0694e7d..4864441 100644
--- a/quic/test_tools/crypto_test_utils.cc
+++ b/quic/test_tools/crypto_test_utils.cc
@@ -262,7 +262,9 @@
 
   CommunicateHandshakeMessages(client_conn, client, server_conn,
                                server_session.GetMutableCryptoStream());
-  CompareClientAndServerKeys(client, server_session.GetMutableCryptoStream());
+  if (client_conn->connected() && server_conn->connected()) {
+    CompareClientAndServerKeys(client, server_session.GetMutableCryptoStream());
+  }
 
   return client->num_sent_client_hellos();
 }
@@ -364,8 +366,9 @@
                                   PacketSavingConnection* server_conn,
                                   QuicCryptoStream* server) {
   size_t client_i = 0, server_i = 0;
-  while (!client->one_rtt_keys_available() ||
-         !server->one_rtt_keys_available()) {
+  while (client_conn->connected() && server_conn->connected() &&
+         (!client->one_rtt_keys_available() ||
+          !server->one_rtt_keys_available())) {
     ASSERT_GT(client_conn->encrypted_packets_.size(), client_i);
     QUIC_LOG(INFO) << "Processing "
                    << client_conn->encrypted_packets_.size() - client_i