Refactor quic_client_interop to avoid dropping letters gfe-relnote: n/a, test-only PiperOrigin-RevId: 275510992 Change-Id: I997d1dccf444b370af2f51f39cac93d4a456f656
diff --git a/quic/tools/quic_client_interop_test_bin.cc b/quic/tools/quic_client_interop_test_bin.cc index 278a22e..be65979 100644 --- a/quic/tools/quic_client_interop_test_bin.cc +++ b/quic/tools/quic_client_interop_test_bin.cc
@@ -70,8 +70,14 @@ std::set<Feature> AttemptRequest(QuicSocketAddress addr, std::string authority, QuicServerId server_id, - ParsedQuicVersionVector versions, + 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>(); QuicEpollServer epoll_server; @@ -79,18 +85,28 @@ auto client = std::make_unique<QuicClient>( addr, server_id, versions, &epoll_server, std::move(proof_verifier)); if (!client->Initialize()) { + QUIC_LOG(ERROR) << "Failed to initialize client"; return features; } - if (!client->Connect()) { - QuicErrorCode error = client->session()->error(); - if (error == QUIC_INVALID_VERSION) { - // QuicFramer::ProcessPacket returns RaiseError(QUIC_INVALID_VERSION) if - // it receives a packet containing a version in the header that is not our - // version. It might be possible that we didn't actually process a VN - // packet here. - features.insert(Feature::kVersionNegotiation); - return features; + 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); } + if (test_version_negotiation && connection->version() == version) { + features.insert(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; } if (!client->session()->IsCryptoHandshakeConfirmed()) { @@ -109,19 +125,17 @@ const QuicTime request_start_time = epoll_clock.Now(); static const auto request_timeout = QuicTime::Delta::FromSeconds(20); + bool request_timed_out = false; while (client->WaitForEvents()) { if (epoll_clock.Now() - request_start_time >= request_timeout) { QUIC_LOG(ERROR) << "Timed out waiting for HTTP response"; - return features; + request_timed_out = true; + break; } } - QuicConnection* connection = client->session()->connection(); if (connection != nullptr) { QuicConnectionStats client_stats = connection->GetStats(); - if (client_stats.retry_packet_processed) { - features.insert(Feature::kRetry); - } QuicSentPacketManager* sent_packet_manager = test::QuicConnectionPeer::GetSentPacketManager(connection); const bool received_forward_secure_ack = @@ -133,7 +147,7 @@ } } - if (!client->connected()) { + if (request_timed_out || !client->connected()) { return features; } @@ -150,8 +164,12 @@ if (epoll_clock.Now() - second_request_start_time >= request_timeout) { // Rebinding does not work, retry without attempting it. - return AttemptRequest(addr, authority, server_id, versions, - /*attempt_rebind=*/false); + 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; } } features.insert(Feature::kRebinding); @@ -187,31 +205,22 @@ } std::set<Feature> ServerSupport(std::string host, int port) { - // Configure version list. + // Enable IETF version support. QuicVersionInitializeSupportForIetfDraft(); - ParsedQuicVersion version = - ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_99); - ParsedQuicVersionVector versions = {version}; - QuicEnableVersion(version); + QuicEnableVersion(ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_99)); // Build the client, and try to connect. QuicSocketAddress addr = tools::LookupAddress(host, QuicStrCat(port)); + if (!addr.IsInitialized()) { + QUIC_LOG(ERROR) << "Failed to resolve " << host; + return std::set<Feature>(); + } QuicServerId server_id(host, port, false); std::string authority = QuicStrCat(host, ":", port); - ParsedQuicVersionVector versions_with_negotiation = versions; - versions_with_negotiation.insert(versions_with_negotiation.begin(), - QuicVersionReservedForNegotiation()); - auto supported_features = - AttemptRequest(addr, authority, server_id, versions_with_negotiation, - /*attempt_rebind=*/true); - if (!supported_features.empty()) { - supported_features.insert(Feature::kVersionNegotiation); - } else { - supported_features = AttemptRequest(addr, authority, server_id, versions, - /*attempt_rebind=*/true); - } - return supported_features; + return AttemptRequest(addr, authority, server_id, + /*test_version_negotiation=*/true, + /*attempt_rebind=*/true); } } // namespace quic