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