1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "quiche/quic/test_tools/quic_test_client.h"
6
7 #include <memory>
8 #include <utility>
9 #include <vector>
10
11 #include "absl/strings/match.h"
12 #include "absl/strings/string_view.h"
13 #include "openssl/x509.h"
14 #include "quiche/quic/core/crypto/proof_verifier.h"
15 #include "quiche/quic/core/http/quic_spdy_client_stream.h"
16 #include "quiche/quic/core/http/spdy_utils.h"
17 #include "quiche/quic/core/io/quic_default_event_loop.h"
18 #include "quiche/quic/core/quic_default_clock.h"
19 #include "quiche/quic/core/quic_packet_writer_wrapper.h"
20 #include "quiche/quic/core/quic_server_id.h"
21 #include "quiche/quic/core/quic_stream_priority.h"
22 #include "quiche/quic/core/quic_utils.h"
23 #include "quiche/quic/platform/api/quic_flags.h"
24 #include "quiche/quic/platform/api/quic_logging.h"
25 #include "quiche/quic/platform/api/quic_stack_trace.h"
26 #include "quiche/quic/test_tools/crypto_test_utils.h"
27 #include "quiche/quic/test_tools/quic_connection_peer.h"
28 #include "quiche/quic/test_tools/quic_spdy_session_peer.h"
29 #include "quiche/quic/test_tools/quic_spdy_stream_peer.h"
30 #include "quiche/quic/test_tools/quic_test_utils.h"
31 #include "quiche/quic/tools/quic_url.h"
32 #include "quiche/common/quiche_text_utils.h"
33
34 namespace quic {
35 namespace test {
36 namespace {
37
38 // RecordingProofVerifier accepts any certificate chain and records the common
39 // name of the leaf and then delegates the actual verification to an actual
40 // verifier. If no optional verifier is provided, then VerifyProof will return
41 // success.
42 class RecordingProofVerifier : public ProofVerifier {
43 public:
RecordingProofVerifier(std::unique_ptr<ProofVerifier> verifier)44 explicit RecordingProofVerifier(std::unique_ptr<ProofVerifier> verifier)
45 : verifier_(std::move(verifier)) {}
46
47 // ProofVerifier interface.
VerifyProof(const std::string & hostname,const uint16_t port,const std::string & server_config,QuicTransportVersion transport_version,absl::string_view chlo_hash,const std::vector<std::string> & certs,const std::string & cert_sct,const std::string & signature,const ProofVerifyContext * context,std::string * error_details,std::unique_ptr<ProofVerifyDetails> * details,std::unique_ptr<ProofVerifierCallback> callback)48 QuicAsyncStatus VerifyProof(
49 const std::string& hostname, const uint16_t port,
50 const std::string& server_config, QuicTransportVersion transport_version,
51 absl::string_view chlo_hash, const std::vector<std::string>& certs,
52 const std::string& cert_sct, const std::string& signature,
53 const ProofVerifyContext* context, std::string* error_details,
54 std::unique_ptr<ProofVerifyDetails>* details,
55 std::unique_ptr<ProofVerifierCallback> callback) override {
56 QuicAsyncStatus process_certs_result = ProcessCerts(certs, cert_sct);
57 if (process_certs_result != QUIC_SUCCESS) {
58 return process_certs_result;
59 }
60
61 if (!verifier_) {
62 return QUIC_SUCCESS;
63 }
64
65 return verifier_->VerifyProof(hostname, port, server_config,
66 transport_version, chlo_hash, certs, cert_sct,
67 signature, context, error_details, details,
68 std::move(callback));
69 }
70
VerifyCertChain(const std::string &,const uint16_t,const std::vector<std::string> & certs,const std::string &,const std::string & cert_sct,const ProofVerifyContext *,std::string *,std::unique_ptr<ProofVerifyDetails> *,uint8_t *,std::unique_ptr<ProofVerifierCallback>)71 QuicAsyncStatus VerifyCertChain(
72 const std::string& /*hostname*/, const uint16_t /*port*/,
73 const std::vector<std::string>& certs,
74 const std::string& /*ocsp_response*/, const std::string& cert_sct,
75 const ProofVerifyContext* /*context*/, std::string* /*error_details*/,
76 std::unique_ptr<ProofVerifyDetails>* /*details*/, uint8_t* /*out_alert*/,
77 std::unique_ptr<ProofVerifierCallback> /*callback*/) override {
78 return ProcessCerts(certs, cert_sct);
79 }
80
CreateDefaultContext()81 std::unique_ptr<ProofVerifyContext> CreateDefaultContext() override {
82 return verifier_ != nullptr ? verifier_->CreateDefaultContext() : nullptr;
83 }
84
common_name() const85 const std::string& common_name() const { return common_name_; }
86
cert_sct() const87 const std::string& cert_sct() const { return cert_sct_; }
88
89 private:
ProcessCerts(const std::vector<std::string> & certs,const std::string & cert_sct)90 QuicAsyncStatus ProcessCerts(const std::vector<std::string>& certs,
91 const std::string& cert_sct) {
92 common_name_.clear();
93 if (certs.empty()) {
94 return QUIC_FAILURE;
95 }
96
97 // Parse the cert into an X509 structure.
98 const uint8_t* data;
99 data = reinterpret_cast<const uint8_t*>(certs[0].data());
100 bssl::UniquePtr<X509> cert(d2i_X509(nullptr, &data, certs[0].size()));
101 if (!cert.get()) {
102 return QUIC_FAILURE;
103 }
104
105 // Extract the CN field
106 X509_NAME* subject = X509_get_subject_name(cert.get());
107 const int index = X509_NAME_get_index_by_NID(subject, NID_commonName, -1);
108 if (index < 0) {
109 return QUIC_FAILURE;
110 }
111 ASN1_STRING* name_data =
112 X509_NAME_ENTRY_get_data(X509_NAME_get_entry(subject, index));
113 if (name_data == nullptr) {
114 return QUIC_FAILURE;
115 }
116
117 // Convert the CN to UTF8, in case the cert represents it in a different
118 // format.
119 unsigned char* buf = nullptr;
120 const int len = ASN1_STRING_to_UTF8(&buf, name_data);
121 if (len <= 0) {
122 return QUIC_FAILURE;
123 }
124 bssl::UniquePtr<unsigned char> deleter(buf);
125
126 common_name_.assign(reinterpret_cast<const char*>(buf), len);
127 cert_sct_ = cert_sct;
128 return QUIC_SUCCESS;
129 }
130
131 std::unique_ptr<ProofVerifier> verifier_;
132 std::string common_name_;
133 std::string cert_sct_;
134 };
135 } // namespace
136
137 class MockableQuicClientDefaultNetworkHelper
138 : public QuicClientDefaultNetworkHelper {
139 public:
140 using QuicClientDefaultNetworkHelper::QuicClientDefaultNetworkHelper;
141 ~MockableQuicClientDefaultNetworkHelper() override = default;
142
ProcessPacket(const QuicSocketAddress & self_address,const QuicSocketAddress & peer_address,const QuicReceivedPacket & packet)143 void ProcessPacket(const QuicSocketAddress& self_address,
144 const QuicSocketAddress& peer_address,
145 const QuicReceivedPacket& packet) override {
146 QuicClientDefaultNetworkHelper::ProcessPacket(self_address, peer_address,
147 packet);
148 if (track_last_incoming_packet_) {
149 last_incoming_packet_ = packet.Clone();
150 }
151 }
152
CreateQuicPacketWriter()153 QuicPacketWriter* CreateQuicPacketWriter() override {
154 QuicPacketWriter* writer =
155 QuicClientDefaultNetworkHelper::CreateQuicPacketWriter();
156 if (!test_writer_) {
157 return writer;
158 }
159 test_writer_->set_writer(writer);
160 return test_writer_;
161 }
162
last_incoming_packet()163 const QuicReceivedPacket* last_incoming_packet() {
164 return last_incoming_packet_.get();
165 }
166
set_track_last_incoming_packet(bool track)167 void set_track_last_incoming_packet(bool track) {
168 track_last_incoming_packet_ = track;
169 }
170
UseWriter(QuicPacketWriterWrapper * writer)171 void UseWriter(QuicPacketWriterWrapper* writer) {
172 QUICHE_CHECK(test_writer_ == nullptr);
173 test_writer_ = writer;
174 }
175
set_peer_address(const QuicSocketAddress & address)176 void set_peer_address(const QuicSocketAddress& address) {
177 QUICHE_CHECK(test_writer_ != nullptr);
178 test_writer_->set_peer_address(address);
179 }
180
181 private:
182 QuicPacketWriterWrapper* test_writer_ = nullptr;
183 // The last incoming packet, iff |track_last_incoming_packet_| is true.
184 std::unique_ptr<QuicReceivedPacket> last_incoming_packet_;
185 // If true, copy each packet from ProcessPacket into |last_incoming_packet_|
186 bool track_last_incoming_packet_ = false;
187 };
188
MockableQuicClient(QuicSocketAddress server_address,const QuicServerId & server_id,const ParsedQuicVersionVector & supported_versions,QuicEventLoop * event_loop)189 MockableQuicClient::MockableQuicClient(
190 QuicSocketAddress server_address, const QuicServerId& server_id,
191 const ParsedQuicVersionVector& supported_versions,
192 QuicEventLoop* event_loop)
193 : MockableQuicClient(server_address, server_id, QuicConfig(),
194 supported_versions, event_loop) {}
195
MockableQuicClient(QuicSocketAddress server_address,const QuicServerId & server_id,const QuicConfig & config,const ParsedQuicVersionVector & supported_versions,QuicEventLoop * event_loop)196 MockableQuicClient::MockableQuicClient(
197 QuicSocketAddress server_address, const QuicServerId& server_id,
198 const QuicConfig& config, const ParsedQuicVersionVector& supported_versions,
199 QuicEventLoop* event_loop)
200 : MockableQuicClient(server_address, server_id, config, supported_versions,
201 event_loop, nullptr) {}
202
MockableQuicClient(QuicSocketAddress server_address,const QuicServerId & server_id,const QuicConfig & config,const ParsedQuicVersionVector & supported_versions,QuicEventLoop * event_loop,std::unique_ptr<ProofVerifier> proof_verifier)203 MockableQuicClient::MockableQuicClient(
204 QuicSocketAddress server_address, const QuicServerId& server_id,
205 const QuicConfig& config, const ParsedQuicVersionVector& supported_versions,
206 QuicEventLoop* event_loop, std::unique_ptr<ProofVerifier> proof_verifier)
207 : MockableQuicClient(server_address, server_id, config, supported_versions,
208 event_loop, std::move(proof_verifier), nullptr) {}
209
MockableQuicClient(QuicSocketAddress server_address,const QuicServerId & server_id,const QuicConfig & config,const ParsedQuicVersionVector & supported_versions,QuicEventLoop * event_loop,std::unique_ptr<ProofVerifier> proof_verifier,std::unique_ptr<SessionCache> session_cache)210 MockableQuicClient::MockableQuicClient(
211 QuicSocketAddress server_address, const QuicServerId& server_id,
212 const QuicConfig& config, const ParsedQuicVersionVector& supported_versions,
213 QuicEventLoop* event_loop, std::unique_ptr<ProofVerifier> proof_verifier,
214 std::unique_ptr<SessionCache> session_cache)
215 : QuicDefaultClient(
216 server_address, server_id, supported_versions, config, event_loop,
217 std::make_unique<MockableQuicClientDefaultNetworkHelper>(event_loop,
218 this),
219 std::make_unique<RecordingProofVerifier>(std::move(proof_verifier)),
220 std::move(session_cache)),
221 override_client_connection_id_(EmptyQuicConnectionId()),
222 client_connection_id_overridden_(false) {}
223
~MockableQuicClient()224 MockableQuicClient::~MockableQuicClient() {
225 if (connected()) {
226 Disconnect();
227 }
228 }
229
230 MockableQuicClientDefaultNetworkHelper*
mockable_network_helper()231 MockableQuicClient::mockable_network_helper() {
232 return static_cast<MockableQuicClientDefaultNetworkHelper*>(
233 default_network_helper());
234 }
235
236 const MockableQuicClientDefaultNetworkHelper*
mockable_network_helper() const237 MockableQuicClient::mockable_network_helper() const {
238 return static_cast<const MockableQuicClientDefaultNetworkHelper*>(
239 default_network_helper());
240 }
241
GetClientConnectionId()242 QuicConnectionId MockableQuicClient::GetClientConnectionId() {
243 if (client_connection_id_overridden_) {
244 return override_client_connection_id_;
245 }
246 if (override_client_connection_id_length_ >= 0) {
247 return QuicUtils::CreateRandomConnectionId(
248 override_client_connection_id_length_);
249 }
250 return QuicDefaultClient::GetClientConnectionId();
251 }
252
UseClientConnectionId(QuicConnectionId client_connection_id)253 void MockableQuicClient::UseClientConnectionId(
254 QuicConnectionId client_connection_id) {
255 client_connection_id_overridden_ = true;
256 override_client_connection_id_ = client_connection_id;
257 }
258
UseClientConnectionIdLength(int client_connection_id_length)259 void MockableQuicClient::UseClientConnectionIdLength(
260 int client_connection_id_length) {
261 override_client_connection_id_length_ = client_connection_id_length;
262 }
263
UseWriter(QuicPacketWriterWrapper * writer)264 void MockableQuicClient::UseWriter(QuicPacketWriterWrapper* writer) {
265 mockable_network_helper()->UseWriter(writer);
266 }
267
set_peer_address(const QuicSocketAddress & address)268 void MockableQuicClient::set_peer_address(const QuicSocketAddress& address) {
269 mockable_network_helper()->set_peer_address(address);
270 if (client_session() != nullptr) {
271 client_session()->connection()->AddKnownServerAddress(address);
272 }
273 }
274
last_incoming_packet()275 const QuicReceivedPacket* MockableQuicClient::last_incoming_packet() {
276 return mockable_network_helper()->last_incoming_packet();
277 }
278
set_track_last_incoming_packet(bool track)279 void MockableQuicClient::set_track_last_incoming_packet(bool track) {
280 mockable_network_helper()->set_track_last_incoming_packet(track);
281 }
282
QuicTestClient(QuicSocketAddress server_address,const std::string & server_hostname,const ParsedQuicVersionVector & supported_versions)283 QuicTestClient::QuicTestClient(
284 QuicSocketAddress server_address, const std::string& server_hostname,
285 const ParsedQuicVersionVector& supported_versions)
286 : QuicTestClient(server_address, server_hostname, QuicConfig(),
287 supported_versions) {}
288
QuicTestClient(QuicSocketAddress server_address,const std::string & server_hostname,const QuicConfig & config,const ParsedQuicVersionVector & supported_versions)289 QuicTestClient::QuicTestClient(
290 QuicSocketAddress server_address, const std::string& server_hostname,
291 const QuicConfig& config, const ParsedQuicVersionVector& supported_versions)
292 : event_loop_(GetDefaultEventLoop()->Create(QuicDefaultClock::Get())),
293 client_(new MockableQuicClient(
294 server_address,
295 QuicServerId(server_hostname, server_address.port(), false), config,
296 supported_versions, event_loop_.get())) {
297 Initialize();
298 }
299
QuicTestClient(QuicSocketAddress server_address,const std::string & server_hostname,const QuicConfig & config,const ParsedQuicVersionVector & supported_versions,std::unique_ptr<ProofVerifier> proof_verifier)300 QuicTestClient::QuicTestClient(
301 QuicSocketAddress server_address, const std::string& server_hostname,
302 const QuicConfig& config, const ParsedQuicVersionVector& supported_versions,
303 std::unique_ptr<ProofVerifier> proof_verifier)
304 : event_loop_(GetDefaultEventLoop()->Create(QuicDefaultClock::Get())),
305 client_(new MockableQuicClient(
306 server_address,
307 QuicServerId(server_hostname, server_address.port(), false), config,
308 supported_versions, event_loop_.get(), std::move(proof_verifier))) {
309 Initialize();
310 }
311
QuicTestClient(QuicSocketAddress server_address,const std::string & server_hostname,const QuicConfig & config,const ParsedQuicVersionVector & supported_versions,std::unique_ptr<ProofVerifier> proof_verifier,std::unique_ptr<SessionCache> session_cache)312 QuicTestClient::QuicTestClient(
313 QuicSocketAddress server_address, const std::string& server_hostname,
314 const QuicConfig& config, const ParsedQuicVersionVector& supported_versions,
315 std::unique_ptr<ProofVerifier> proof_verifier,
316 std::unique_ptr<SessionCache> session_cache)
317 : event_loop_(GetDefaultEventLoop()->Create(QuicDefaultClock::Get())),
318 client_(new MockableQuicClient(
319 server_address,
320 QuicServerId(server_hostname, server_address.port(), false), config,
321 supported_versions, event_loop_.get(), std::move(proof_verifier),
322 std::move(session_cache))) {
323 Initialize();
324 }
325
QuicTestClient(QuicSocketAddress server_address,const std::string & server_hostname,const QuicConfig & config,const ParsedQuicVersionVector & supported_versions,std::unique_ptr<ProofVerifier> proof_verifier,std::unique_ptr<SessionCache> session_cache,std::unique_ptr<QuicEventLoop> event_loop)326 QuicTestClient::QuicTestClient(
327 QuicSocketAddress server_address, const std::string& server_hostname,
328 const QuicConfig& config, const ParsedQuicVersionVector& supported_versions,
329 std::unique_ptr<ProofVerifier> proof_verifier,
330 std::unique_ptr<SessionCache> session_cache,
331 std::unique_ptr<QuicEventLoop> event_loop)
332 : event_loop_(std::move(event_loop)),
333 client_(new MockableQuicClient(
334 server_address,
335 QuicServerId(server_hostname, server_address.port(), false), config,
336 supported_versions, event_loop_.get(), std::move(proof_verifier),
337 std::move(session_cache))) {
338 Initialize();
339 }
340
341 QuicTestClient::QuicTestClient() = default;
342
~QuicTestClient()343 QuicTestClient::~QuicTestClient() {
344 for (std::pair<QuicStreamId, QuicSpdyClientStream*> stream : open_streams_) {
345 stream.second->set_visitor(nullptr);
346 }
347 }
348
Initialize()349 void QuicTestClient::Initialize() {
350 priority_ = 3;
351 connect_attempted_ = false;
352 auto_reconnect_ = false;
353 buffer_body_ = true;
354 num_requests_ = 0;
355 num_responses_ = 0;
356 ClearPerConnectionState();
357 // As chrome will generally do this, we want it to be the default when it's
358 // not overridden.
359 if (!client_->config()->HasSetBytesForConnectionIdToSend()) {
360 client_->config()->SetBytesForConnectionIdToSend(0);
361 }
362 }
363
SetUserAgentID(const std::string & user_agent_id)364 void QuicTestClient::SetUserAgentID(const std::string& user_agent_id) {
365 client_->SetUserAgentID(user_agent_id);
366 }
367
SendRequest(const std::string & uri)368 ssize_t QuicTestClient::SendRequest(const std::string& uri) {
369 spdy::Http2HeaderBlock headers;
370 if (!PopulateHeaderBlockFromUrl(uri, &headers)) {
371 return 0;
372 }
373 return SendMessage(headers, "");
374 }
375
SendRequestAndRstTogether(const std::string & uri)376 ssize_t QuicTestClient::SendRequestAndRstTogether(const std::string& uri) {
377 spdy::Http2HeaderBlock headers;
378 if (!PopulateHeaderBlockFromUrl(uri, &headers)) {
379 return 0;
380 }
381
382 QuicSpdyClientSession* session = client()->client_session();
383 QuicConnection::ScopedPacketFlusher flusher(session->connection());
384 ssize_t ret = SendMessage(headers, "", /*fin=*/true, /*flush=*/false);
385
386 QuicStreamId stream_id = GetNthClientInitiatedBidirectionalStreamId(
387 session->transport_version(), 0);
388 session->ResetStream(stream_id, QUIC_STREAM_CANCELLED);
389 return ret;
390 }
391
SendRequestsAndWaitForResponses(const std::vector<std::string> & url_list)392 void QuicTestClient::SendRequestsAndWaitForResponses(
393 const std::vector<std::string>& url_list) {
394 for (const std::string& url : url_list) {
395 SendRequest(url);
396 }
397 while (client()->WaitForEvents()) {
398 }
399 }
400
GetOrCreateStreamAndSendRequest(const spdy::Http2HeaderBlock * headers,absl::string_view body,bool fin,quiche::QuicheReferenceCountedPointer<QuicAckListenerInterface> ack_listener)401 ssize_t QuicTestClient::GetOrCreateStreamAndSendRequest(
402 const spdy::Http2HeaderBlock* headers, absl::string_view body, bool fin,
403 quiche::QuicheReferenceCountedPointer<QuicAckListenerInterface>
404 ack_listener) {
405 if (headers) {
406 QuicClientPushPromiseIndex::TryHandle* handle;
407 QuicAsyncStatus rv =
408 client()->push_promise_index()->Try(*headers, this, &handle);
409 if (rv == QUIC_SUCCESS) return 1;
410 if (rv == QUIC_PENDING) {
411 // May need to retry request if asynchronous rendezvous fails.
412 std::unique_ptr<spdy::Http2HeaderBlock> new_headers(
413 new spdy::Http2HeaderBlock(headers->Clone()));
414 push_promise_data_to_resend_ = std::make_unique<TestClientDataToResend>(
415 std::move(new_headers), body, fin, this, std::move(ack_listener));
416 return 1;
417 }
418 }
419
420 // Maybe it's better just to overload this. it's just that we need
421 // for the GetOrCreateStream function to call something else...which
422 // is icky and complicated, but maybe not worse than this.
423 QuicSpdyClientStream* stream = GetOrCreateStream();
424 if (stream == nullptr) {
425 return 0;
426 }
427 QuicSpdyStreamPeer::set_ack_listener(stream, ack_listener);
428
429 ssize_t ret = 0;
430 if (headers != nullptr) {
431 spdy::Http2HeaderBlock spdy_headers(headers->Clone());
432 if (spdy_headers[":authority"].as_string().empty()) {
433 spdy_headers[":authority"] = client_->server_id().host();
434 }
435 ret = stream->SendRequest(std::move(spdy_headers), body, fin);
436 ++num_requests_;
437 } else {
438 stream->WriteOrBufferBody(std::string(body), fin);
439 ret = body.length();
440 }
441 return ret;
442 }
443
SendMessage(const spdy::Http2HeaderBlock & headers,absl::string_view body)444 ssize_t QuicTestClient::SendMessage(const spdy::Http2HeaderBlock& headers,
445 absl::string_view body) {
446 return SendMessage(headers, body, /*fin=*/true);
447 }
448
SendMessage(const spdy::Http2HeaderBlock & headers,absl::string_view body,bool fin)449 ssize_t QuicTestClient::SendMessage(const spdy::Http2HeaderBlock& headers,
450 absl::string_view body, bool fin) {
451 return SendMessage(headers, body, fin, /*flush=*/true);
452 }
453
SendMessage(const spdy::Http2HeaderBlock & headers,absl::string_view body,bool fin,bool flush)454 ssize_t QuicTestClient::SendMessage(const spdy::Http2HeaderBlock& headers,
455 absl::string_view body, bool fin,
456 bool flush) {
457 // Always force creation of a stream for SendMessage.
458 latest_created_stream_ = nullptr;
459
460 ssize_t ret = GetOrCreateStreamAndSendRequest(&headers, body, fin, nullptr);
461
462 if (flush) {
463 WaitForWriteToFlush();
464 }
465 return ret;
466 }
467
SendData(const std::string & data,bool last_data)468 ssize_t QuicTestClient::SendData(const std::string& data, bool last_data) {
469 return SendData(data, last_data, nullptr);
470 }
471
SendData(const std::string & data,bool last_data,quiche::QuicheReferenceCountedPointer<QuicAckListenerInterface> ack_listener)472 ssize_t QuicTestClient::SendData(
473 const std::string& data, bool last_data,
474 quiche::QuicheReferenceCountedPointer<QuicAckListenerInterface>
475 ack_listener) {
476 return GetOrCreateStreamAndSendRequest(nullptr, absl::string_view(data),
477 last_data, std::move(ack_listener));
478 }
479
response_complete() const480 bool QuicTestClient::response_complete() const { return response_complete_; }
481
response_body_size() const482 int64_t QuicTestClient::response_body_size() const {
483 return response_body_size_;
484 }
485
buffer_body() const486 bool QuicTestClient::buffer_body() const { return buffer_body_; }
487
set_buffer_body(bool buffer_body)488 void QuicTestClient::set_buffer_body(bool buffer_body) {
489 buffer_body_ = buffer_body;
490 }
491
response_body() const492 const std::string& QuicTestClient::response_body() const { return response_; }
493
SendCustomSynchronousRequest(const spdy::Http2HeaderBlock & headers,const std::string & body)494 std::string QuicTestClient::SendCustomSynchronousRequest(
495 const spdy::Http2HeaderBlock& headers, const std::string& body) {
496 // Clear connection state here and only track this synchronous request.
497 ClearPerConnectionState();
498 if (SendMessage(headers, body) == 0) {
499 QUIC_DLOG(ERROR) << "Failed the request for: " << headers.DebugString();
500 // Set the response_ explicitly. Otherwise response_ will contain the
501 // response from the previously successful request.
502 response_ = "";
503 } else {
504 WaitForResponse();
505 }
506 return response_;
507 }
508
SendSynchronousRequest(const std::string & uri)509 std::string QuicTestClient::SendSynchronousRequest(const std::string& uri) {
510 spdy::Http2HeaderBlock headers;
511 if (!PopulateHeaderBlockFromUrl(uri, &headers)) {
512 return "";
513 }
514 return SendCustomSynchronousRequest(headers, "");
515 }
516
SendConnectivityProbing()517 void QuicTestClient::SendConnectivityProbing() {
518 QuicConnection* connection = client()->client_session()->connection();
519 connection->SendConnectivityProbingPacket(connection->writer(),
520 connection->peer_address());
521 }
522
SetLatestCreatedStream(QuicSpdyClientStream * stream)523 void QuicTestClient::SetLatestCreatedStream(QuicSpdyClientStream* stream) {
524 latest_created_stream_ = stream;
525 if (latest_created_stream_ != nullptr) {
526 open_streams_[stream->id()] = stream;
527 stream->set_visitor(this);
528 }
529 }
530
GetOrCreateStream()531 QuicSpdyClientStream* QuicTestClient::GetOrCreateStream() {
532 if (!connect_attempted_ || auto_reconnect_) {
533 if (!connected()) {
534 Connect();
535 }
536 if (!connected()) {
537 return nullptr;
538 }
539 }
540 if (open_streams_.empty()) {
541 ClearPerConnectionState();
542 }
543 if (!latest_created_stream_) {
544 SetLatestCreatedStream(client_->CreateClientStream());
545 if (latest_created_stream_) {
546 latest_created_stream_->SetPriority(QuicStreamPriority(
547 HttpStreamPriority{priority_, /* incremental = */ false}));
548 }
549 }
550
551 return latest_created_stream_;
552 }
553
connection_error() const554 QuicErrorCode QuicTestClient::connection_error() const {
555 return client()->connection_error();
556 }
557
cert_common_name() const558 const std::string& QuicTestClient::cert_common_name() const {
559 return reinterpret_cast<RecordingProofVerifier*>(client_->proof_verifier())
560 ->common_name();
561 }
562
cert_sct() const563 const std::string& QuicTestClient::cert_sct() const {
564 return reinterpret_cast<RecordingProofVerifier*>(client_->proof_verifier())
565 ->cert_sct();
566 }
567
GetServerConfig() const568 const QuicTagValueMap& QuicTestClient::GetServerConfig() const {
569 QuicCryptoClientConfig* config = client_->crypto_config();
570 const QuicCryptoClientConfig::CachedState* state =
571 config->LookupOrCreate(client_->server_id());
572 const CryptoHandshakeMessage* handshake_msg = state->GetServerConfig();
573 return handshake_msg->tag_value_map();
574 }
575
connected() const576 bool QuicTestClient::connected() const { return client_->connected(); }
577
Connect()578 void QuicTestClient::Connect() {
579 if (connected()) {
580 QUIC_BUG(quic_bug_10133_1) << "Cannot connect already-connected client";
581 return;
582 }
583 if (!connect_attempted_) {
584 client_->Initialize();
585 }
586
587 // If we've been asked to override SNI, set it now
588 if (override_sni_set_) {
589 client_->set_server_id(
590 QuicServerId(override_sni_, address().port(), false));
591 }
592
593 client_->Connect();
594 connect_attempted_ = true;
595 }
596
ResetConnection()597 void QuicTestClient::ResetConnection() {
598 Disconnect();
599 Connect();
600 }
601
Disconnect()602 void QuicTestClient::Disconnect() {
603 ClearPerConnectionState();
604 if (client_->initialized()) {
605 client_->Disconnect();
606 }
607 connect_attempted_ = false;
608 }
609
local_address() const610 QuicSocketAddress QuicTestClient::local_address() const {
611 return client_->network_helper()->GetLatestClientAddress();
612 }
613
ClearPerRequestState()614 void QuicTestClient::ClearPerRequestState() {
615 stream_error_ = QUIC_STREAM_NO_ERROR;
616 response_ = "";
617 response_complete_ = false;
618 response_headers_complete_ = false;
619 preliminary_headers_.clear();
620 response_headers_.clear();
621 response_trailers_.clear();
622 bytes_read_ = 0;
623 bytes_written_ = 0;
624 response_body_size_ = 0;
625 }
626
HaveActiveStream()627 bool QuicTestClient::HaveActiveStream() {
628 return push_promise_data_to_resend_.get() || !open_streams_.empty();
629 }
630
WaitUntil(int timeout_ms,std::function<bool ()> trigger)631 bool QuicTestClient::WaitUntil(int timeout_ms, std::function<bool()> trigger) {
632 QuicTime::Delta timeout = QuicTime::Delta::FromMilliseconds(timeout_ms);
633 const QuicClock* clock = client()->session()->connection()->clock();
634 QuicTime end_waiting_time = clock->Now() + timeout;
635 while (connected() && !(trigger && trigger()) &&
636 (timeout_ms < 0 || clock->Now() < end_waiting_time)) {
637 event_loop_->RunEventLoopOnce(timeout);
638 client_->WaitForEventsPostprocessing();
639 }
640 ReadNextResponse();
641 if (trigger && !trigger()) {
642 QUIC_VLOG(1) << "Client WaitUntil returning with trigger returning false.";
643 return false;
644 }
645 return true;
646 }
647
Send(absl::string_view data)648 ssize_t QuicTestClient::Send(absl::string_view data) {
649 return SendData(std::string(data), false);
650 }
651
response_headers_complete() const652 bool QuicTestClient::response_headers_complete() const {
653 for (std::pair<QuicStreamId, QuicSpdyClientStream*> stream : open_streams_) {
654 if (stream.second->headers_decompressed()) {
655 return true;
656 }
657 }
658 return response_headers_complete_;
659 }
660
response_headers() const661 const spdy::Http2HeaderBlock* QuicTestClient::response_headers() const {
662 for (std::pair<QuicStreamId, QuicSpdyClientStream*> stream : open_streams_) {
663 if (stream.second->headers_decompressed()) {
664 response_headers_ = stream.second->response_headers().Clone();
665 break;
666 }
667 }
668 return &response_headers_;
669 }
670
preliminary_headers() const671 const spdy::Http2HeaderBlock* QuicTestClient::preliminary_headers() const {
672 for (std::pair<QuicStreamId, QuicSpdyClientStream*> stream : open_streams_) {
673 size_t bytes_read =
674 stream.second->stream_bytes_read() + stream.second->header_bytes_read();
675 if (bytes_read > 0) {
676 preliminary_headers_ = stream.second->preliminary_headers().Clone();
677 break;
678 }
679 }
680 return &preliminary_headers_;
681 }
682
response_trailers() const683 const spdy::Http2HeaderBlock& QuicTestClient::response_trailers() const {
684 return response_trailers_;
685 }
686
response_size() const687 int64_t QuicTestClient::response_size() const { return bytes_read(); }
688
bytes_read() const689 size_t QuicTestClient::bytes_read() const {
690 for (std::pair<QuicStreamId, QuicSpdyClientStream*> stream : open_streams_) {
691 size_t bytes_read = stream.second->total_body_bytes_read() +
692 stream.second->header_bytes_read();
693 if (bytes_read > 0) {
694 return bytes_read;
695 }
696 }
697 return bytes_read_;
698 }
699
bytes_written() const700 size_t QuicTestClient::bytes_written() const {
701 for (std::pair<QuicStreamId, QuicSpdyClientStream*> stream : open_streams_) {
702 size_t bytes_written = stream.second->stream_bytes_written() +
703 stream.second->header_bytes_written();
704 if (bytes_written > 0) {
705 return bytes_written;
706 }
707 }
708 return bytes_written_;
709 }
710
partial_response_body() const711 absl::string_view QuicTestClient::partial_response_body() const {
712 return latest_created_stream_ == nullptr ? ""
713 : latest_created_stream_->data();
714 }
715
OnClose(QuicSpdyStream * stream)716 void QuicTestClient::OnClose(QuicSpdyStream* stream) {
717 if (stream == nullptr) {
718 return;
719 }
720 // Always close the stream, regardless of whether it was the last stream
721 // written.
722 client()->OnClose(stream);
723 ++num_responses_;
724 if (open_streams_.find(stream->id()) == open_streams_.end()) {
725 return;
726 }
727 if (latest_created_stream_ == stream) {
728 latest_created_stream_ = nullptr;
729 }
730 QuicSpdyClientStream* client_stream =
731 static_cast<QuicSpdyClientStream*>(stream);
732 QuicStreamId id = client_stream->id();
733 closed_stream_states_.insert(std::make_pair(
734 id,
735 PerStreamState(
736 // Set response_complete to true iff stream is closed while connected.
737 client_stream->stream_error(), connected(),
738 client_stream->headers_decompressed(),
739 client_stream->response_headers(),
740 client_stream->preliminary_headers(),
741 (buffer_body() ? std::string(client_stream->data()) : ""),
742 client_stream->received_trailers(),
743 // Use NumBytesConsumed to avoid counting retransmitted stream frames.
744 client_stream->total_body_bytes_read() +
745 client_stream->header_bytes_read(),
746 client_stream->stream_bytes_written() +
747 client_stream->header_bytes_written(),
748 client_stream->data().size())));
749 open_streams_.erase(id);
750 }
751
CheckVary(const spdy::Http2HeaderBlock &,const spdy::Http2HeaderBlock &,const spdy::Http2HeaderBlock &)752 bool QuicTestClient::CheckVary(
753 const spdy::Http2HeaderBlock& /*client_request*/,
754 const spdy::Http2HeaderBlock& /*promise_request*/,
755 const spdy::Http2HeaderBlock& /*promise_response*/) {
756 return true;
757 }
758
OnRendezvousResult(QuicSpdyStream * stream)759 void QuicTestClient::OnRendezvousResult(QuicSpdyStream* stream) {
760 std::unique_ptr<TestClientDataToResend> data_to_resend =
761 std::move(push_promise_data_to_resend_);
762 SetLatestCreatedStream(static_cast<QuicSpdyClientStream*>(stream));
763 if (stream) {
764 stream->OnBodyAvailable();
765 } else if (data_to_resend) {
766 data_to_resend->Resend();
767 }
768 }
769
UseWriter(QuicPacketWriterWrapper * writer)770 void QuicTestClient::UseWriter(QuicPacketWriterWrapper* writer) {
771 client_->UseWriter(writer);
772 }
773
UseConnectionId(QuicConnectionId server_connection_id)774 void QuicTestClient::UseConnectionId(QuicConnectionId server_connection_id) {
775 QUICHE_DCHECK(!connected());
776 client_->set_server_connection_id_override(server_connection_id);
777 }
778
UseConnectionIdLength(uint8_t server_connection_id_length)779 void QuicTestClient::UseConnectionIdLength(
780 uint8_t server_connection_id_length) {
781 QUICHE_DCHECK(!connected());
782 client_->set_server_connection_id_length(server_connection_id_length);
783 }
784
UseClientConnectionId(QuicConnectionId client_connection_id)785 void QuicTestClient::UseClientConnectionId(
786 QuicConnectionId client_connection_id) {
787 QUICHE_DCHECK(!connected());
788 client_->UseClientConnectionId(client_connection_id);
789 }
790
UseClientConnectionIdLength(uint8_t client_connection_id_length)791 void QuicTestClient::UseClientConnectionIdLength(
792 uint8_t client_connection_id_length) {
793 QUICHE_DCHECK(!connected());
794 client_->UseClientConnectionIdLength(client_connection_id_length);
795 }
796
MigrateSocket(const QuicIpAddress & new_host)797 bool QuicTestClient::MigrateSocket(const QuicIpAddress& new_host) {
798 return client_->MigrateSocket(new_host);
799 }
800
MigrateSocketWithSpecifiedPort(const QuicIpAddress & new_host,int port)801 bool QuicTestClient::MigrateSocketWithSpecifiedPort(
802 const QuicIpAddress& new_host, int port) {
803 client_->set_local_port(port);
804 return client_->MigrateSocket(new_host);
805 }
806
bind_to_address() const807 QuicIpAddress QuicTestClient::bind_to_address() const {
808 return client_->bind_to_address();
809 }
810
set_bind_to_address(QuicIpAddress address)811 void QuicTestClient::set_bind_to_address(QuicIpAddress address) {
812 client_->set_bind_to_address(address);
813 }
814
address() const815 const QuicSocketAddress& QuicTestClient::address() const {
816 return client_->server_address();
817 }
818
WaitForWriteToFlush()819 void QuicTestClient::WaitForWriteToFlush() {
820 while (connected() && client()->session()->HasDataToWrite()) {
821 client_->WaitForEvents();
822 }
823 }
824
TestClientDataToResend(std::unique_ptr<spdy::Http2HeaderBlock> headers,absl::string_view body,bool fin,QuicTestClient * test_client,quiche::QuicheReferenceCountedPointer<QuicAckListenerInterface> ack_listener)825 QuicTestClient::TestClientDataToResend::TestClientDataToResend(
826 std::unique_ptr<spdy::Http2HeaderBlock> headers, absl::string_view body,
827 bool fin, QuicTestClient* test_client,
828 quiche::QuicheReferenceCountedPointer<QuicAckListenerInterface>
829 ack_listener)
830 : QuicDefaultClient::QuicDataToResend(std::move(headers), body, fin),
831 test_client_(test_client),
832 ack_listener_(std::move(ack_listener)) {}
833
834 QuicTestClient::TestClientDataToResend::~TestClientDataToResend() = default;
835
Resend()836 void QuicTestClient::TestClientDataToResend::Resend() {
837 test_client_->GetOrCreateStreamAndSendRequest(headers_.get(), body_, fin_,
838 ack_listener_);
839 headers_.reset();
840 }
841
PerStreamState(const PerStreamState & other)842 QuicTestClient::PerStreamState::PerStreamState(const PerStreamState& other)
843 : stream_error(other.stream_error),
844 response_complete(other.response_complete),
845 response_headers_complete(other.response_headers_complete),
846 response_headers(other.response_headers.Clone()),
847 preliminary_headers(other.preliminary_headers.Clone()),
848 response(other.response),
849 response_trailers(other.response_trailers.Clone()),
850 bytes_read(other.bytes_read),
851 bytes_written(other.bytes_written),
852 response_body_size(other.response_body_size) {}
853
PerStreamState(QuicRstStreamErrorCode stream_error,bool response_complete,bool response_headers_complete,const spdy::Http2HeaderBlock & response_headers,const spdy::Http2HeaderBlock & preliminary_headers,const std::string & response,const spdy::Http2HeaderBlock & response_trailers,uint64_t bytes_read,uint64_t bytes_written,int64_t response_body_size)854 QuicTestClient::PerStreamState::PerStreamState(
855 QuicRstStreamErrorCode stream_error, bool response_complete,
856 bool response_headers_complete,
857 const spdy::Http2HeaderBlock& response_headers,
858 const spdy::Http2HeaderBlock& preliminary_headers,
859 const std::string& response,
860 const spdy::Http2HeaderBlock& response_trailers, uint64_t bytes_read,
861 uint64_t bytes_written, int64_t response_body_size)
862 : stream_error(stream_error),
863 response_complete(response_complete),
864 response_headers_complete(response_headers_complete),
865 response_headers(response_headers.Clone()),
866 preliminary_headers(preliminary_headers.Clone()),
867 response(response),
868 response_trailers(response_trailers.Clone()),
869 bytes_read(bytes_read),
870 bytes_written(bytes_written),
871 response_body_size(response_body_size) {}
872
873 QuicTestClient::PerStreamState::~PerStreamState() = default;
874
PopulateHeaderBlockFromUrl(const std::string & uri,spdy::Http2HeaderBlock * headers)875 bool QuicTestClient::PopulateHeaderBlockFromUrl(
876 const std::string& uri, spdy::Http2HeaderBlock* headers) {
877 std::string url;
878 if (absl::StartsWith(uri, "https://") || absl::StartsWith(uri, "http://")) {
879 url = uri;
880 } else if (uri[0] == '/') {
881 url = "https://" + client_->server_id().host() + uri;
882 } else {
883 url = "https://" + uri;
884 }
885 return SpdyUtils::PopulateHeaderBlockFromUrl(url, headers);
886 }
887
ReadNextResponse()888 void QuicTestClient::ReadNextResponse() {
889 if (closed_stream_states_.empty()) {
890 return;
891 }
892
893 PerStreamState state(closed_stream_states_.front().second);
894
895 stream_error_ = state.stream_error;
896 response_ = state.response;
897 response_complete_ = state.response_complete;
898 response_headers_complete_ = state.response_headers_complete;
899 preliminary_headers_ = state.preliminary_headers.Clone();
900 response_headers_ = state.response_headers.Clone();
901 response_trailers_ = state.response_trailers.Clone();
902 bytes_read_ = state.bytes_read;
903 bytes_written_ = state.bytes_written;
904 response_body_size_ = state.response_body_size;
905
906 closed_stream_states_.pop_front();
907 }
908
ClearPerConnectionState()909 void QuicTestClient::ClearPerConnectionState() {
910 ClearPerRequestState();
911 open_streams_.clear();
912 closed_stream_states_.clear();
913 latest_created_stream_ = nullptr;
914 }
915
WaitForDelayedAcks()916 void QuicTestClient::WaitForDelayedAcks() {
917 // kWaitDuration is a period of time that is long enough for all delayed
918 // acks to be sent and received on the other end.
919 const QuicTime::Delta kWaitDuration =
920 4 * QuicTime::Delta::FromMilliseconds(kDefaultDelayedAckTimeMs);
921
922 const QuicClock* clock = client()->client_session()->connection()->clock();
923
924 QuicTime wait_until = clock->ApproximateNow() + kWaitDuration;
925 while (connected() && clock->ApproximateNow() < wait_until) {
926 // This waits for up to 50 ms.
927 client()->WaitForEvents();
928 }
929 }
930
931 } // namespace test
932 } // namespace quic
933