Adopt QuicConnectionDebugVisitor from quic_client_interop_test This CL refactors quic_client_interop_test into a class to allow adopting QuicConnectionDebugVisitor which improves the tool's reporting of the C and V letters. gfe-relnote: n/a, test-tool-only PiperOrigin-RevId: 293104152 Change-Id: I36c50bc44a7187ccb35437ec1b617b1d922faabc
diff --git a/quic/tools/quic_client_base.cc b/quic/tools/quic_client_base.cc index 798ed5f..9249ddc 100644 --- a/quic/tools/quic_client_base.cc +++ b/quic/tools/quic_client_base.cc
@@ -36,7 +36,8 @@ num_sent_client_hellos_(0), connection_error_(QUIC_NO_ERROR), connected_or_attempting_connect_(false), - network_helper_(std::move(network_helper)) {} + network_helper_(std::move(network_helper)), + connection_debug_visitor_(nullptr) {} QuicClientBase::~QuicClientBase() = default; @@ -114,6 +115,9 @@ can_reconnect_with_different_version ? ParsedQuicVersionVector{mutual_version} : supported_versions())); + if (connection_debug_visitor_ != nullptr) { + session()->connection()->set_debug_visitor(connection_debug_visitor_); + } session()->connection()->set_client_connection_id(GetClientConnectionId()); if (initial_max_packet_length_ != 0) { session()->connection()->SetMaxPacketLength(initial_max_packet_length_);
diff --git a/quic/tools/quic_client_base.h b/quic/tools/quic_client_base.h index 3160b74..91a9587 100644 --- a/quic/tools/quic_client_base.h +++ b/quic/tools/quic_client_base.h
@@ -213,6 +213,11 @@ crypto_config_.set_pre_shared_key(key); } + void set_connection_debug_visitor( + QuicConnectionDebugVisitor* connection_debug_visitor) { + connection_debug_visitor_ = connection_debug_visitor; + } + protected: // TODO(rch): Move GetNumSentClientHellosFromSession and // GetNumReceivedServerConfigUpdatesFromSession into a new/better @@ -331,6 +336,10 @@ // The network helper used to create sockets and manage the event loop. // Not owned by this class. std::unique_ptr<NetworkHelper> network_helper_; + + // The debug visitor set on the connection right after it is constructed. + // Not owned, must be valid for the lifetime of the QuicClientBase instance. + QuicConnectionDebugVisitor* connection_debug_visitor_; }; } // namespace quic
diff --git a/quic/tools/quic_client_interop_test_bin.cc b/quic/tools/quic_client_interop_test_bin.cc index b11065f..9638eb9 100644 --- a/quic/tools/quic_client_interop_test_bin.cc +++ b/quic/tools/quic_client_interop_test_bin.cc
@@ -79,10 +79,53 @@ } } -// Attempts a resumption using |client| by disconnecting and reconnecting. If -// resumption is successful, |features| is modified to add Feature::kResumption -// to it, otherwise it is left unmodified. -void AttemptResumption(QuicClient* client, std::set<Feature>* features) { +class QuicClientInteropRunner : QuicConnectionDebugVisitor { + public: + QuicClientInteropRunner() {} + + void InsertFeature(Feature feature) { features_.insert(feature); } + + std::set<Feature> features() const { return features_; } + + // Attempts a resumption using |client| by disconnecting and reconnecting. If + // resumption is successful, |features_| is modified to add + // Feature::kResumption to it, otherwise it is left unmodified. + void AttemptResumption(QuicClient* client); + + void AttemptRequest(QuicSocketAddress addr, + std::string authority, + QuicServerId server_id, + bool test_version_negotiation, + bool attempt_rebind); + + void OnConnectionCloseFrame(const QuicConnectionCloseFrame& frame) override { + switch (frame.close_type) { + case GOOGLE_QUIC_CONNECTION_CLOSE: + QUIC_LOG(ERROR) << "Received unexpected GoogleQUIC connection close"; + break; + case IETF_QUIC_TRANSPORT_CONNECTION_CLOSE: + if (frame.transport_error_code == NO_IETF_QUIC_ERROR) { + InsertFeature(Feature::kConnectionClose); + } + break; + case IETF_QUIC_APPLICATION_CONNECTION_CLOSE: + if (frame.application_error_code == 0) { + InsertFeature(Feature::kConnectionClose); + } + break; + } + } + + void OnVersionNegotiationPacket( + const QuicVersionNegotiationPacket& /*packet*/) override { + InsertFeature(Feature::kVersionNegotiation); + } + + private: + std::set<Feature> features_; +}; + +void QuicClientInteropRunner::AttemptResumption(QuicClient* client) { client->Disconnect(); if (!client->Initialize()) { QUIC_LOG(ERROR) << "Failed to reinitialize client"; @@ -94,22 +137,21 @@ if (static_cast<QuicCryptoClientStream*>( test::QuicSessionPeer::GetMutableCryptoStream(client->session())) ->IsResumption()) { - features->insert(Feature::kResumption); + InsertFeature(Feature::kResumption); } } -std::set<Feature> AttemptRequest(QuicSocketAddress addr, - std::string authority, - QuicServerId server_id, - bool test_version_negotiation, - bool attempt_rebind) { +void QuicClientInteropRunner::AttemptRequest(QuicSocketAddress addr, + std::string authority, + QuicServerId server_id, + bool test_version_negotiation, + bool attempt_rebind) { ParsedQuicVersion version(PROTOCOL_TLS1_3, QUIC_VERSION_99); ParsedQuicVersionVector versions = {version}; if (test_version_negotiation) { versions.insert(versions.begin(), QuicVersionReservedForNegotiation()); } - std::set<Feature> features; auto proof_verifier = std::make_unique<FakeProofVerifier>(); auto session_cache = std::make_unique<test::SimpleSessionCache>(); QuicEpollServer epoll_server; @@ -117,35 +159,32 @@ auto client = std::make_unique<QuicClient>( addr, server_id, versions, &epoll_server, std::move(proof_verifier), std::move(session_cache)); + client->set_connection_debug_visitor(this); if (!client->Initialize()) { QUIC_LOG(ERROR) << "Failed to initialize client"; - return features; + return; } const bool connect_result = client->Connect(); QuicConnection* connection = client->session()->connection(); if (connection != nullptr) { QuicConnectionStats client_stats = connection->GetStats(); if (client_stats.retry_packet_processed) { - features.insert(Feature::kRetry); + InsertFeature(Feature::kRetry); } if (test_version_negotiation && connection->version() == version) { - features.insert(Feature::kVersionNegotiation); + InsertFeature(Feature::kVersionNegotiation); } } if (test_version_negotiation && !connect_result) { // Failed to negotiate version, retry without version negotiation. - std::set<Feature> features_without_version_negotiation = - AttemptRequest(addr, authority, server_id, - /*test_version_negotiation=*/false, attempt_rebind); - - features.insert(features_without_version_negotiation.begin(), - features_without_version_negotiation.end()); - return features; + AttemptRequest(addr, authority, server_id, + /*test_version_negotiation=*/false, attempt_rebind); + return; } if (!client->session()->OneRttKeysAvailable()) { - return features; + return; } - features.insert(Feature::kHandshake); + InsertFeature(Feature::kHandshake); // Construct and send a request. spdy::SpdyHeaderBlock header_block; @@ -176,19 +215,19 @@ sent_packet_manager->GetLargestAckedPacket(ENCRYPTION_FORWARD_SECURE) .IsInitialized(); if (client_stats.stream_bytes_received > 0 && received_forward_secure_ack) { - features.insert(Feature::kStreamData); + InsertFeature(Feature::kStreamData); } } if (request_timed_out || !client->connected()) { - return features; + return; } if (client->latest_response_code() != -1) { - features.insert(Feature::kHttp3); + InsertFeature(Feature::kHttp3); if (client->client_session()->dynamic_table_entry_referenced()) { - features.insert(Feature::kDynamicEntryReferenced); + InsertFeature(Feature::kDynamicEntryReferenced); } if (attempt_rebind) { @@ -201,18 +240,15 @@ if (epoll_clock.Now() - second_request_start_time >= request_timeout) { // Rebinding does not work, retry without attempting it. - std::set<Feature> features_without_rebind = AttemptRequest( - addr, authority, server_id, test_version_negotiation, - /*attempt_rebind=*/false); - features.insert(features_without_rebind.begin(), - features_without_rebind.end()); - return features; + AttemptRequest(addr, authority, server_id, test_version_negotiation, + /*attempt_rebind=*/false); + return; } } - features.insert(Feature::kRebinding); + InsertFeature(Feature::kRebinding); if (client->client_session()->dynamic_table_entry_referenced()) { - features.insert(Feature::kDynamicEntryReferenced); + InsertFeature(Feature::kDynamicEntryReferenced); } } else { QUIC_LOG(ERROR) << "Failed to change ephemeral port"; @@ -229,22 +265,21 @@ client->epoll_network_helper()->RunEventLoop(); if (epoll_clock.Now() - close_start_time >= close_timeout) { QUIC_LOG(ERROR) << "Timed out waiting for connection close"; - AttemptResumption(client.get(), &features); - return features; + AttemptResumption(client.get()); + return; } } const QuicErrorCode received_error = client->session()->error(); if (received_error == QUIC_NO_ERROR || received_error == QUIC_PUBLIC_RESET) { - features.insert(Feature::kConnectionClose); + InsertFeature(Feature::kConnectionClose); } else { QUIC_LOG(ERROR) << "Received error " << client->session()->error() << " " << client->session()->error_details(); } } - AttemptResumption(client.get(), &features); - return features; + AttemptResumption(client.get()); } std::set<Feature> ServerSupport(std::string host, int port) { @@ -262,9 +297,13 @@ QuicServerId server_id(host, port, false); std::string authority = quiche::QuicheStrCat(host, ":", port); - return AttemptRequest(addr, authority, server_id, + QuicClientInteropRunner runner; + + runner.AttemptRequest(addr, authority, server_id, /*test_version_negotiation=*/true, /*attempt_rebind=*/true); + + return runner.features(); } } // namespace quic