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