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 #ifndef QUICHE_QUIC_TEST_TOOLS_QUIC_TEST_CLIENT_H_ 6 #define QUICHE_QUIC_TEST_TOOLS_QUIC_TEST_CLIENT_H_ 7 8 #include <cstdint> 9 #include <memory> 10 #include <string> 11 12 #include "absl/strings/string_view.h" 13 #include "quiche/quic/core/io/quic_event_loop.h" 14 #include "quiche/quic/core/proto/cached_network_parameters_proto.h" 15 #include "quiche/quic/core/quic_framer.h" 16 #include "quiche/quic/core/quic_packet_creator.h" 17 #include "quiche/quic/core/quic_packets.h" 18 #include "quiche/quic/platform/api/quic_test.h" 19 #include "quiche/quic/tools/quic_default_client.h" 20 #include "quiche/common/quiche_linked_hash_map.h" 21 #include "quiche/spdy/core/http2_header_block.h" 22 23 namespace quic { 24 25 class ProofVerifier; 26 class QuicPacketWriterWrapper; 27 28 namespace test { 29 30 class MockableQuicClientDefaultNetworkHelper; 31 32 // A quic client which allows mocking out reads and writes. 33 class MockableQuicClient : public QuicDefaultClient { 34 public: 35 MockableQuicClient(QuicSocketAddress server_address, 36 const QuicServerId& server_id, 37 const ParsedQuicVersionVector& supported_versions, 38 QuicEventLoop* event_loop); 39 40 MockableQuicClient(QuicSocketAddress server_address, 41 const QuicServerId& server_id, const QuicConfig& config, 42 const ParsedQuicVersionVector& supported_versions, 43 QuicEventLoop* event_loop); 44 45 MockableQuicClient(QuicSocketAddress server_address, 46 const QuicServerId& server_id, const QuicConfig& config, 47 const ParsedQuicVersionVector& supported_versions, 48 QuicEventLoop* event_loop, 49 std::unique_ptr<ProofVerifier> proof_verifier); 50 51 MockableQuicClient(QuicSocketAddress server_address, 52 const QuicServerId& server_id, const QuicConfig& config, 53 const ParsedQuicVersionVector& supported_versions, 54 QuicEventLoop* event_loop, 55 std::unique_ptr<ProofVerifier> proof_verifier, 56 std::unique_ptr<SessionCache> session_cache); 57 MockableQuicClient(const MockableQuicClient&) = delete; 58 MockableQuicClient& operator=(const MockableQuicClient&) = delete; 59 60 ~MockableQuicClient() override; 61 62 QuicConnectionId GetClientConnectionId() override; 63 void UseClientConnectionId(QuicConnectionId client_connection_id); 64 void UseClientConnectionIdLength(int client_connection_id_length); 65 66 void UseWriter(QuicPacketWriterWrapper* writer); 67 void set_peer_address(const QuicSocketAddress& address); 68 // The last incoming packet, iff |track_last_incoming_packet| is true. 69 const QuicReceivedPacket* last_incoming_packet(); 70 // If true, copy each packet from ProcessPacket into |last_incoming_packet| 71 void set_track_last_incoming_packet(bool track); 72 73 // Casts the network helper to a MockableQuicClientDefaultNetworkHelper. 74 MockableQuicClientDefaultNetworkHelper* mockable_network_helper(); 75 const MockableQuicClientDefaultNetworkHelper* mockable_network_helper() const; 76 77 private: 78 // Client connection ID to use, if client_connection_id_overridden_. 79 // TODO(wub): Move client_connection_id_(length_) overrides to QuicClientBase. 80 QuicConnectionId override_client_connection_id_; 81 bool client_connection_id_overridden_; 82 int override_client_connection_id_length_ = -1; 83 CachedNetworkParameters cached_network_paramaters_; 84 }; 85 86 // A toy QUIC client used for testing. 87 class QuicTestClient : public QuicSpdyStream::Visitor, 88 public QuicClientPushPromiseIndex::Delegate { 89 public: 90 QuicTestClient(QuicSocketAddress server_address, 91 const std::string& server_hostname, 92 const ParsedQuicVersionVector& supported_versions); 93 QuicTestClient(QuicSocketAddress server_address, 94 const std::string& server_hostname, const QuicConfig& config, 95 const ParsedQuicVersionVector& supported_versions); 96 QuicTestClient(QuicSocketAddress server_address, 97 const std::string& server_hostname, const QuicConfig& config, 98 const ParsedQuicVersionVector& supported_versions, 99 std::unique_ptr<ProofVerifier> proof_verifier); 100 QuicTestClient(QuicSocketAddress server_address, 101 const std::string& server_hostname, const QuicConfig& config, 102 const ParsedQuicVersionVector& supported_versions, 103 std::unique_ptr<ProofVerifier> proof_verifier, 104 std::unique_ptr<SessionCache> session_cache); 105 QuicTestClient(QuicSocketAddress server_address, 106 const std::string& server_hostname, const QuicConfig& config, 107 const ParsedQuicVersionVector& supported_versions, 108 std::unique_ptr<ProofVerifier> proof_verifier, 109 std::unique_ptr<SessionCache> session_cache, 110 std::unique_ptr<QuicEventLoop> event_loop); 111 112 ~QuicTestClient() override; 113 114 // Sets the |user_agent_id| of the |client_|. 115 void SetUserAgentID(const std::string& user_agent_id); 116 117 // Wraps data in a quic packet and sends it. 118 ssize_t SendData(const std::string& data, bool last_data); 119 // As above, but |delegate| will be notified when |data| is ACKed. 120 ssize_t SendData( 121 const std::string& data, bool last_data, 122 quiche::QuicheReferenceCountedPointer<QuicAckListenerInterface> 123 ack_listener); 124 125 // Clears any outstanding state and sends a simple GET of 'uri' to the 126 // server. Returns 0 if the request failed and no bytes were written. 127 ssize_t SendRequest(const std::string& uri); 128 // Send a request R and a RST_FRAME which resets R, in the same packet. 129 ssize_t SendRequestAndRstTogether(const std::string& uri); 130 // Sends requests for all the urls and waits for the responses. To process 131 // the individual responses as they are returned, the caller should use the 132 // set the response_listener on the client(). 133 void SendRequestsAndWaitForResponses( 134 const std::vector<std::string>& url_list); 135 // Sends a request containing |headers| and |body| and returns the number of 136 // bytes sent (the size of the serialized request headers and body). 137 ssize_t SendMessage(const spdy::Http2HeaderBlock& headers, 138 absl::string_view body); 139 // Sends a request containing |headers| and |body| with the fin bit set to 140 // |fin| and returns the number of bytes sent (the size of the serialized 141 // request headers and body). 142 ssize_t SendMessage(const spdy::Http2HeaderBlock& headers, 143 absl::string_view body, bool fin); 144 // Sends a request containing |headers| and |body| with the fin bit set to 145 // |fin| and returns the number of bytes sent (the size of the serialized 146 // request headers and body). If |flush| is true, will wait for the message to 147 // be flushed before returning. 148 ssize_t SendMessage(const spdy::Http2HeaderBlock& headers, 149 absl::string_view body, bool fin, bool flush); 150 // Sends a request containing |headers| and |body|, waits for the response, 151 // and returns the response body. 152 std::string SendCustomSynchronousRequest( 153 const spdy::Http2HeaderBlock& headers, const std::string& body); 154 // Sends a GET request for |uri|, waits for the response, and returns the 155 // response body. 156 std::string SendSynchronousRequest(const std::string& uri); 157 void SendConnectivityProbing(); 158 void Connect(); 159 void ResetConnection(); 160 void Disconnect(); 161 QuicSocketAddress local_address() const; 162 void ClearPerRequestState(); 163 bool WaitUntil(int timeout_ms, std::function<bool()> trigger); 164 ssize_t Send(absl::string_view data); 165 bool connected() const; 166 bool buffer_body() const; 167 void set_buffer_body(bool buffer_body); 168 169 // Getters for stream state that only get updated once a complete response is 170 // received. 171 const spdy::Http2HeaderBlock& response_trailers() const; 172 bool response_complete() const; 173 int64_t response_body_size() const; 174 const std::string& response_body() const; 175 // Getters for stream state that return state of the oldest active stream that 176 // have received a partial response. 177 bool response_headers_complete() const; 178 const spdy::Http2HeaderBlock* response_headers() const; 179 const spdy::Http2HeaderBlock* preliminary_headers() const; 180 int64_t response_size() const; 181 size_t bytes_read() const; 182 size_t bytes_written() const; 183 184 // Returns response body received so far by the stream that has been most 185 // recently opened among currently open streams. To query response body 186 // received by a stream that is already closed, use `response_body()` instead. 187 absl::string_view partial_response_body() const; 188 189 // Returns once at least one complete response or a connection close has been 190 // received from the server. If responses are received for multiple (say 2) 191 // streams, next WaitForResponse will return immediately. WaitForResponse()192 void WaitForResponse() { WaitForResponseForMs(-1); } 193 194 // Returns once some data is received on any open streams or at least one 195 // complete response is received from the server. WaitForInitialResponse()196 void WaitForInitialResponse() { WaitForInitialResponseForMs(-1); } 197 198 // Returns once at least one complete response or a connection close has been 199 // received from the server, or once the timeout expires. 200 // Passing in a timeout value of -1 disables the timeout. If multiple 201 // responses are received while the client is waiting, subsequent calls to 202 // this function will return immediately. WaitForResponseForMs(int timeout_ms)203 void WaitForResponseForMs(int timeout_ms) { 204 WaitUntil(timeout_ms, [this]() { 205 return !HaveActiveStream() || !closed_stream_states_.empty(); 206 }); 207 if (response_complete()) { 208 QUIC_VLOG(1) << "Client received response:" 209 << response_headers()->DebugString() << response_body(); 210 } 211 } 212 213 // Returns once some data is received on any open streams or at least one 214 // complete response is received from the server, or once the timeout 215 // expires. -1 means no timeout. WaitForInitialResponseForMs(int timeout_ms)216 void WaitForInitialResponseForMs(int timeout_ms) { 217 WaitUntil(timeout_ms, 218 [this]() { return !HaveActiveStream() || response_size() != 0; }); 219 } 220 221 // Migrate local address to <|new_host|, a random port>. 222 // Return whether the migration succeeded. 223 bool MigrateSocket(const QuicIpAddress& new_host); 224 // Migrate local address to <|new_host|, |port|>. 225 // Return whether the migration succeeded. 226 bool MigrateSocketWithSpecifiedPort(const QuicIpAddress& new_host, int port); 227 QuicIpAddress bind_to_address() const; 228 void set_bind_to_address(QuicIpAddress address); 229 const QuicSocketAddress& address() const; 230 231 // From QuicSpdyStream::Visitor 232 void OnClose(QuicSpdyStream* stream) override; 233 234 // From QuicClientPushPromiseIndex::Delegate 235 bool CheckVary(const spdy::Http2HeaderBlock& client_request, 236 const spdy::Http2HeaderBlock& promise_request, 237 const spdy::Http2HeaderBlock& promise_response) override; 238 void OnRendezvousResult(QuicSpdyStream*) override; 239 240 // Configures client_ to take ownership of and use the writer. 241 // Must be called before initial connect. 242 void UseWriter(QuicPacketWriterWrapper* writer); 243 // Configures client_ to use a specific server connection ID instead of a 244 // random one. 245 void UseConnectionId(QuicConnectionId server_connection_id); 246 // Configures client_ to use a specific server connection ID length instead 247 // of the default of kQuicDefaultConnectionIdLength. 248 void UseConnectionIdLength(uint8_t server_connection_id_length); 249 // Configures client_ to use a specific client connection ID instead of an 250 // empty one. 251 void UseClientConnectionId(QuicConnectionId client_connection_id); 252 // Configures client_ to use a specific client connection ID length instead 253 // of the default of zero. 254 void UseClientConnectionIdLength(uint8_t client_connection_id_length); 255 256 // Returns nullptr if the maximum number of streams have already been created. 257 QuicSpdyClientStream* GetOrCreateStream(); 258 259 // Calls GetOrCreateStream(), sends the request on the stream, and 260 // stores the request in case it needs to be resent. If |headers| is 261 // null, only the body will be sent on the stream. 262 ssize_t GetOrCreateStreamAndSendRequest( 263 const spdy::Http2HeaderBlock* headers, absl::string_view body, bool fin, 264 quiche::QuicheReferenceCountedPointer<QuicAckListenerInterface> 265 ack_listener); 266 stream_error()267 QuicRstStreamErrorCode stream_error() { return stream_error_; } 268 QuicErrorCode connection_error() const; 269 client()270 MockableQuicClient* client() { return client_.get(); } client()271 const MockableQuicClient* client() const { return client_.get(); } 272 273 // cert_common_name returns the common name value of the server's certificate, 274 // or the empty std::string if no certificate was presented. 275 const std::string& cert_common_name() const; 276 277 // cert_sct returns the signed timestamp of the server's certificate, 278 // or the empty std::string if no signed timestamp was presented. 279 const std::string& cert_sct() const; 280 281 // Get the server config map. Server config must exist. 282 const QuicTagValueMap& GetServerConfig() const; 283 set_auto_reconnect(bool reconnect)284 void set_auto_reconnect(bool reconnect) { auto_reconnect_ = reconnect; } 285 set_priority(spdy::SpdyPriority priority)286 void set_priority(spdy::SpdyPriority priority) { priority_ = priority; } 287 288 void WaitForWriteToFlush(); 289 event_loop()290 QuicEventLoop* event_loop() { return event_loop_.get(); } 291 num_requests()292 size_t num_requests() const { return num_requests_; } 293 num_responses()294 size_t num_responses() const { return num_responses_; } 295 set_server_address(const QuicSocketAddress & server_address)296 void set_server_address(const QuicSocketAddress& server_address) { 297 client_->set_server_address(server_address); 298 } 299 set_peer_address(const QuicSocketAddress & address)300 void set_peer_address(const QuicSocketAddress& address) { 301 client_->set_peer_address(address); 302 } 303 304 // Explicitly set the SNI value for this client, overriding the default 305 // behavior which extracts the SNI value from the request URL. OverrideSni(const std::string & sni)306 void OverrideSni(const std::string& sni) { 307 override_sni_set_ = true; 308 override_sni_ = sni; 309 } 310 311 void Initialize(); 312 set_client(MockableQuicClient * client)313 void set_client(MockableQuicClient* client) { client_.reset(client); } 314 315 // Given |uri|, populates the fields in |headers| for a simple GET 316 // request. If |uri| is a relative URL, the QuicServerId will be 317 // use to specify the authority. 318 bool PopulateHeaderBlockFromUrl(const std::string& uri, 319 spdy::Http2HeaderBlock* headers); 320 321 // Waits for a period of time that is long enough to receive all delayed acks 322 // sent by peer. 323 void WaitForDelayedAcks(); 324 latest_created_stream()325 QuicSpdyClientStream* latest_created_stream() { 326 return latest_created_stream_; 327 } 328 329 protected: 330 QuicTestClient(); 331 QuicTestClient(const QuicTestClient&) = delete; 332 QuicTestClient(const QuicTestClient&&) = delete; 333 QuicTestClient& operator=(const QuicTestClient&) = delete; 334 QuicTestClient& operator=(const QuicTestClient&&) = delete; 335 336 private: 337 class TestClientDataToResend : public QuicDefaultClient::QuicDataToResend { 338 public: 339 TestClientDataToResend( 340 std::unique_ptr<spdy::Http2HeaderBlock> headers, absl::string_view body, 341 bool fin, QuicTestClient* test_client, 342 quiche::QuicheReferenceCountedPointer<QuicAckListenerInterface> 343 ack_listener); 344 345 ~TestClientDataToResend() override; 346 347 void Resend() override; 348 349 protected: 350 QuicTestClient* test_client_; 351 quiche::QuicheReferenceCountedPointer<QuicAckListenerInterface> 352 ack_listener_; 353 }; 354 355 // PerStreamState of a stream is updated when it is closed. 356 struct PerStreamState { 357 PerStreamState(const PerStreamState& other); 358 PerStreamState(QuicRstStreamErrorCode stream_error, bool response_complete, 359 bool response_headers_complete, 360 const spdy::Http2HeaderBlock& response_headers, 361 const spdy::Http2HeaderBlock& preliminary_headers, 362 const std::string& response, 363 const spdy::Http2HeaderBlock& response_trailers, 364 uint64_t bytes_read, uint64_t bytes_written, 365 int64_t response_body_size); 366 ~PerStreamState(); 367 368 QuicRstStreamErrorCode stream_error; 369 bool response_complete; 370 bool response_headers_complete; 371 spdy::Http2HeaderBlock response_headers; 372 spdy::Http2HeaderBlock preliminary_headers; 373 std::string response; 374 spdy::Http2HeaderBlock response_trailers; 375 uint64_t bytes_read; 376 uint64_t bytes_written; 377 int64_t response_body_size; 378 }; 379 380 bool HaveActiveStream(); 381 382 // Read oldest received response and remove it from closed_stream_states_. 383 void ReadNextResponse(); 384 385 // Clear open_streams_, closed_stream_states_ and reset 386 // latest_created_stream_. 387 void ClearPerConnectionState(); 388 389 // Update latest_created_stream_, add |stream| to open_streams_ and starts 390 // tracking its state. 391 void SetLatestCreatedStream(QuicSpdyClientStream* stream); 392 393 std::unique_ptr<QuicEventLoop> event_loop_; 394 std::unique_ptr<MockableQuicClient> client_; // The actual client 395 QuicSpdyClientStream* latest_created_stream_; 396 std::map<QuicStreamId, QuicSpdyClientStream*> open_streams_; 397 // Received responses of closed streams. 398 quiche::QuicheLinkedHashMap<QuicStreamId, PerStreamState> 399 closed_stream_states_; 400 401 QuicRstStreamErrorCode stream_error_; 402 403 bool response_complete_; 404 bool response_headers_complete_; 405 mutable spdy::Http2HeaderBlock preliminary_headers_; 406 mutable spdy::Http2HeaderBlock response_headers_; 407 408 // Parsed response trailers (if present), copied from the stream in OnClose. 409 spdy::Http2HeaderBlock response_trailers_; 410 411 spdy::SpdyPriority priority_; 412 std::string response_; 413 // bytes_read_ and bytes_written_ are updated only when stream_ is released; 414 // prefer bytes_read() and bytes_written() member functions. 415 uint64_t bytes_read_; 416 uint64_t bytes_written_; 417 // The number of HTTP body bytes received. 418 int64_t response_body_size_; 419 // True if we tried to connect already since the last call to Disconnect(). 420 bool connect_attempted_; 421 // The client will auto-connect exactly once before sending data. If 422 // something causes a connection reset, it will not automatically reconnect 423 // unless auto_reconnect_ is true. 424 bool auto_reconnect_; 425 // Should we buffer the response body? Defaults to true. 426 bool buffer_body_; 427 // For async push promise rendezvous, validation may fail in which 428 // case the request should be retried. 429 std::unique_ptr<TestClientDataToResend> push_promise_data_to_resend_; 430 // Number of requests/responses this client has sent/received. 431 size_t num_requests_; 432 size_t num_responses_; 433 434 // If set, this value is used for the connection SNI, overriding the usual 435 // logic which extracts the SNI from the request URL. 436 bool override_sni_set_ = false; 437 std::string override_sni_; 438 }; 439 440 } // namespace test 441 442 } // namespace quic 443 444 #endif // QUICHE_QUIC_TEST_TOOLS_QUIC_TEST_CLIENT_H_ 445