Verify receipt of connection_close in quic_client_interop This CL also changes QuicFramer::MaybeExtractQuicErrorCode to map NO_IETF_QUIC_ERROR to QUIC_NO_ERROR. gfe-relnote: change mapping of NO_IETF_QUIC_ERROR, not flag-protected PiperOrigin-RevId: 274704993 Change-Id: If3e7f98dd6a2435a477ee318b44fce78e6ab6e30
diff --git a/quic/core/quic_framer.cc b/quic/core/quic_framer.cc index a759adb..2d4d4a5 100644 --- a/quic/core/quic_framer.cc +++ b/quic/core/quic_framer.cc
@@ -6603,7 +6603,12 @@ uint64_t extracted_error_code; if (ed.size() < 2 || !QuicTextUtils::IsAllDigits(ed[0]) || !QuicTextUtils::StringToUint64(ed[0], &extracted_error_code)) { - frame->extracted_error_code = QUIC_IETF_GQUIC_ERROR_MISSING; + if (frame->close_type == IETF_QUIC_TRANSPORT_CONNECTION_CLOSE && + frame->transport_error_code == NO_IETF_QUIC_ERROR) { + frame->extracted_error_code = QUIC_NO_ERROR; + } else { + frame->extracted_error_code = QUIC_IETF_GQUIC_ERROR_MISSING; + } return; } // Return the error code (numeric) and the error details string without the
diff --git a/quic/test_tools/quic_connection_peer.cc b/quic/test_tools/quic_connection_peer.cc index 8b99730..02775ca 100644 --- a/quic/test_tools/quic_connection_peer.cc +++ b/quic/test_tools/quic_connection_peer.cc
@@ -357,5 +357,12 @@ connection->address_validated_ = true; } +// static +void QuicConnectionPeer::SendConnectionClosePacket(QuicConnection* connection, + QuicErrorCode error, + const std::string& details) { + connection->SendConnectionClosePacket(error, details); +} + } // namespace test } // namespace quic
diff --git a/quic/test_tools/quic_connection_peer.h b/quic/test_tools/quic_connection_peer.h index 5b97ae6..c5c972f 100644 --- a/quic/test_tools/quic_connection_peer.h +++ b/quic/test_tools/quic_connection_peer.h
@@ -139,6 +139,10 @@ PacketHeaderFormat format); static void AddBytesReceived(QuicConnection* connection, size_t length); static void SetAddressValidated(QuicConnection* connection); + + static void SendConnectionClosePacket(QuicConnection* connection, + QuicErrorCode error, + const std::string& details); }; } // namespace test
diff --git a/quic/tools/quic_client_interop_test_bin.cc b/quic/tools/quic_client_interop_test_bin.cc index 20a4699..2511141 100644 --- a/quic/tools/quic_client_interop_test_bin.cc +++ b/quic/tools/quic_client_interop_test_bin.cc
@@ -11,6 +11,7 @@ #include "net/third_party/quiche/src/quic/core/quic_versions.h" #include "net/third_party/quiche/src/quic/platform/api/quic_epoll.h" #include "net/third_party/quiche/src/quic/platform/api/quic_system_event_loop.h" +#include "net/quic/platform/impl/quic_epoll_clock.h" #include "net/third_party/quiche/src/quic/test_tools/quic_connection_peer.h" #include "net/third_party/quiche/src/quic/tools/fake_proof_verifier.h" #include "net/third_party/quiche/src/quic/tools/quic_client.h" @@ -34,10 +35,10 @@ kStreamData, // The connection close procedcure completes with a zero error code. kConnectionClose, - // An H3 transaction succeeded. - kHttp3, // A RETRY packet was successfully processed. kRetry, + // An H3 transaction succeeded. + kHttp3, }; char MatrixLetter(Feature f) { @@ -64,6 +65,7 @@ std::set<Feature> features; auto proof_verifier = std::make_unique<FakeProofVerifier>(); QuicEpollServer epoll_server; + QuicEpollClock epoll_clock(&epoll_server); auto client = std::make_unique<QuicClient>( addr, server_id, versions, &epoll_server, std::move(proof_verifier)); if (!client->Initialize()) { @@ -95,9 +97,13 @@ client->set_store_response(true); client->SendRequest(header_block, "", /*fin=*/true); - // TODO(nharper): After some period of time, time out and don't report - // success. + const QuicTime request_start_time = epoll_clock.Now(); + static const auto request_timeout = QuicTime::Delta::FromSeconds(20); while (client->WaitForEvents()) { + if (epoll_clock.Now() - request_start_time >= request_timeout) { + QUIC_LOG(ERROR) << "Timed out waiting for HTTP response"; + return features; + } } QuicConnection* connection = client->session()->connection(); @@ -125,9 +131,28 @@ features.insert(Feature::kHttp3); } - // TODO(nharper): Check that we sent/received (which one?) a CONNECTION_CLOSE - // with error code 0. - features.insert(Feature::kConnectionClose); + if (connection != nullptr && connection->connected()) { + test::QuicConnectionPeer::SendConnectionClosePacket( + connection, QUIC_NO_ERROR, "Graceful close"); + const QuicTime close_start_time = epoll_clock.Now(); + static const auto close_timeout = QuicTime::Delta::FromSeconds(10); + while (client->connected()) { + client->epoll_network_helper()->RunEventLoop(); + if (epoll_clock.Now() - close_start_time >= close_timeout) { + QUIC_LOG(ERROR) << "Timed out waiting for connection close"; + return features; + } + } + const QuicErrorCode received_error = client->session()->error(); + if (received_error == QUIC_NO_ERROR || + received_error == QUIC_PUBLIC_RESET) { + features.insert(Feature::kConnectionClose); + } else { + QUIC_LOG(ERROR) << "Received error " << client->session()->error() << " " + << client->session()->error_details(); + } + } + return features; }