• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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