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