| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef NET_TOOLS_QUIC_TEST_TOOLS_QUIC_TEST_CLIENT_H_ |
| #define NET_TOOLS_QUIC_TEST_TOOLS_QUIC_TEST_CLIENT_H_ |
| |
| #include <stddef.h> |
| #include <stdint.h> |
| |
| #include <cstdint> |
| #include <memory> |
| #include <string> |
| |
| #include "base/macros.h" |
| #include "net/base/ip_address.h" |
| #include "net/base/ip_endpoint.h" |
| #include "net/quic/proto/cached_network_parameters.pb.h" |
| #include "net/quic/quic_framer.h" |
| #include "net/quic/quic_packet_creator.h" |
| #include "net/quic/quic_protocol.h" |
| #include "net/tools/balsa/balsa_frame.h" |
| #include "net/tools/epoll_server/epoll_server.h" |
| #include "net/tools/quic/quic_client.h" |
| #include "net/tools/quic/test_tools/simple_client.h" |
| |
| using base::StringPiece; |
| |
| namespace net { |
| |
| class ProofVerifier; |
| |
| class QuicPacketWriterWrapper; |
| |
| namespace test { |
| |
| class HTTPMessage; |
| class MockableQuicClient; |
| |
| // A quic client which allows mocking out writes. |
| class MockableQuicClient : public QuicClient { |
| public: |
| MockableQuicClient(IPEndPoint server_address, |
| const QuicServerId& server_id, |
| const QuicVersionVector& supported_versions, |
| EpollServer* epoll_server); |
| |
| MockableQuicClient(IPEndPoint server_address, |
| const QuicServerId& server_id, |
| const QuicConfig& config, |
| const QuicVersionVector& supported_versions, |
| EpollServer* epoll_server); |
| |
| ~MockableQuicClient() override; |
| QuicPacketWriter* CreateQuicPacketWriter() override; |
| QuicConnectionId GenerateNewConnectionId() override; |
| void UseWriter(QuicPacketWriterWrapper* writer); |
| void UseConnectionId(QuicConnectionId connection_id); |
| void SendCachedNetworkParamaters( |
| const CachedNetworkParameters& cached_network_params) { |
| cached_network_paramaters_ = cached_network_params; |
| } |
| |
| private: |
| QuicConnectionId override_connection_id_; // ConnectionId to use, if nonzero |
| QuicPacketWriterWrapper* test_writer_; |
| CachedNetworkParameters cached_network_paramaters_; |
| |
| DISALLOW_COPY_AND_ASSIGN(MockableQuicClient); |
| }; |
| |
| // A toy QUIC client used for testing, mostly following the SimpleClient APIs. |
| class QuicTestClient : public test::SimpleClient, |
| public QuicSpdyStream::Visitor, |
| public QuicClientPushPromiseIndex::Delegate { |
| public: |
| QuicTestClient(IPEndPoint server_address, |
| const std::string& server_hostname, |
| const QuicVersionVector& supported_versions); |
| QuicTestClient(IPEndPoint server_address, |
| const std::string& server_hostname, |
| const QuicConfig& config, |
| const QuicVersionVector& supported_versions); |
| |
| ~QuicTestClient() override; |
| |
| // Sets the |user_agent_id| of the |client_|. |
| void SetUserAgentID(const std::string& user_agent_id); |
| |
| // Wraps data in a quic packet and sends it. |
| ssize_t SendData(const std::string& data, bool last_data); |
| // As above, but |delegate| will be notified when |data| is ACKed. |
| ssize_t SendData(const std::string& data, |
| bool last_data, |
| QuicAckListenerInterface* delegate); |
| |
| // From SimpleClient |
| // Clears any outstanding state and sends a simple GET of 'uri' to the |
| // server. Returns 0 if the request failed and no bytes were written. |
| ssize_t SendRequest(const std::string& uri) override; |
| // Sends requests for all the urls and waits for the responses. To process |
| // the individual responses as they are returned, the caller should use the |
| // set the response_listener on the client(). |
| void SendRequestsAndWaitForResponses( |
| const std::vector<std::string>& url_list); |
| ssize_t SendMessage(const HTTPMessage& message) override; |
| std::string SendCustomSynchronousRequest(const HTTPMessage& message) override; |
| std::string SendSynchronousRequest(const std::string& uri) override; |
| void Connect() override; |
| void ResetConnection() override; |
| void Disconnect() override; |
| IPEndPoint local_address() const override; |
| void ClearPerRequestState() override; |
| void WaitForResponseForMs(int timeout_ms) override; |
| void WaitForInitialResponseForMs(int timeout_ms) override; |
| ssize_t Send(const void* buffer, size_t size) override; |
| bool response_complete() const override; |
| bool response_headers_complete() const override; |
| const BalsaHeaders* response_headers() const override; |
| int64_t response_size() const override; |
| int response_header_size() const override; |
| int64_t response_body_size() const override; |
| size_t bytes_read() const override; |
| size_t bytes_written() const override; |
| bool buffer_body() const override; |
| void set_buffer_body(bool buffer_body) override; |
| bool ServerInLameDuckMode() const override; |
| const std::string& response_body() override; |
| bool connected() const override; |
| // These functions are all unimplemented functions from SimpleClient, and log |
| // DFATAL if called by users of SimpleClient. |
| ssize_t SendAndWaitForResponse(const void* buffer, size_t size) override; |
| void Bind(IPEndPoint* local_address) override; |
| void MigrateSocket(const IPAddress& new_host) override; |
| std::string SerializeMessage(const HTTPMessage& message) override; |
| IPAddress bind_to_address() const override; |
| void set_bind_to_address(const IPAddress& address) override; |
| const IPEndPoint& address() const override; |
| size_t requests_sent() const override; |
| |
| // Returns the response trailers as received by the |stream_|. |
| const SpdyHeaderBlock& response_trailers() const; |
| |
| // From QuicSpdyStream::Visitor |
| void OnClose(QuicSpdyStream* stream) override; |
| |
| // From QuicClientPushPromiseIndex::Delegate |
| bool CheckVary(const SpdyHeaderBlock& client_request, |
| const SpdyHeaderBlock& promise_request, |
| const SpdyHeaderBlock& promise_response) override; |
| void OnRendezvousResult(QuicSpdyStream*) override; |
| |
| // Configures client_ to take ownership of and use the writer. |
| // Must be called before initial connect. |
| void UseWriter(QuicPacketWriterWrapper* writer); |
| // If the given ConnectionId is nonzero, configures client_ to use a specific |
| // ConnectionId instead of a random one. |
| void UseConnectionId(QuicConnectionId connection_id); |
| |
| // Returns nullptr if the maximum number of streams have already been created. |
| QuicSpdyClientStream* GetOrCreateStream(); |
| |
| // Calls GetOrCreateStream(), sends the request on the stream, and |
| // stores the request in case it needs to be resent. If |headers| is |
| // null, only the body will be sent on the stream. |
| ssize_t GetOrCreateStreamAndSendRequest(const BalsaHeaders* headers, |
| StringPiece body, |
| bool fin, |
| QuicAckListenerInterface* delegate); |
| |
| QuicRstStreamErrorCode stream_error() { return stream_error_; } |
| QuicErrorCode connection_error(); |
| |
| MockableQuicClient* client(); |
| |
| // cert_common_name returns the common name value of the server's certificate, |
| // or the empty string if no certificate was presented. |
| const std::string& cert_common_name() const; |
| |
| // cert_sct returns the signed timestamp of the server's certificate, |
| // or the empty string if no signed timestamp was presented. |
| const std::string& cert_sct() const; |
| |
| // Get the server config map. |
| QuicTagValueMap GetServerConfig() const; |
| |
| void set_auto_reconnect(bool reconnect) { auto_reconnect_ = reconnect; } |
| |
| void set_priority(SpdyPriority priority) { priority_ = priority; } |
| |
| void WaitForWriteToFlush(); |
| |
| EpollServer* epoll_server() { return &epoll_server_; } |
| |
| void set_allow_bidirectional_data(bool value) { |
| allow_bidirectional_data_ = value; |
| } |
| |
| bool allow_bidirectional_data() const { return allow_bidirectional_data_; } |
| |
| size_t num_requests() const { return num_requests_; } |
| |
| size_t num_responses() const { return num_responses_; } |
| |
| // Explicitly set the SNI value for this client, overriding the default |
| // behavior which extracts the SNI value from the request URL. |
| void OverrideSni(const std::string& sni) { |
| override_sni_set_ = true; |
| override_sni_ = sni; |
| } |
| |
| protected: |
| QuicTestClient(); |
| |
| void Initialize(); |
| |
| void set_client(MockableQuicClient* client) { client_.reset(client); } |
| |
| private: |
| class TestClientDataToResend : public QuicClient::QuicDataToResend { |
| public: |
| TestClientDataToResend(BalsaHeaders* headers, |
| StringPiece body, |
| bool fin, |
| QuicTestClient* test_client, |
| QuicAckListenerInterface* delegate) |
| : QuicClient::QuicDataToResend(headers, body, fin), |
| test_client_(test_client), |
| delegate_(delegate) {} |
| |
| ~TestClientDataToResend() override {} |
| |
| void Resend() override; |
| |
| protected: |
| QuicTestClient* test_client_; |
| QuicAckListenerInterface* delegate_; |
| }; |
| |
| // Given a uri, creates a simple HTTPMessage request message for testing. |
| static void FillInRequest(const std::string& uri, HTTPMessage* message); |
| |
| bool HaveActiveStream(); |
| |
| EpollServer epoll_server_; |
| std::unique_ptr<MockableQuicClient> client_; // The actual client |
| QuicSpdyClientStream* stream_; |
| |
| QuicRstStreamErrorCode stream_error_; |
| |
| bool response_complete_; |
| bool response_headers_complete_; |
| mutable BalsaHeaders response_headers_; |
| |
| // Parsed response trailers (if present), copied from the stream in OnClose. |
| SpdyHeaderBlock response_trailers_; |
| |
| SpdyPriority priority_; |
| std::string response_; |
| uint64_t bytes_read_; |
| uint64_t bytes_written_; |
| // The number of uncompressed HTTP header bytes received. |
| int response_header_size_; |
| // The number of HTTP body bytes received. |
| int64_t response_body_size_; |
| // True if we tried to connect already since the last call to Disconnect(). |
| bool connect_attempted_; |
| // The client will auto-connect exactly once before sending data. If |
| // something causes a connection reset, it will not automatically reconnect |
| // unless auto_reconnect_ is true. |
| bool auto_reconnect_; |
| // Should we buffer the response body? Defaults to true. |
| bool buffer_body_; |
| // When true allows the sending of a request to continue while the response is |
| // arriving. |
| bool allow_bidirectional_data_; |
| // For async push promise rendezvous, validation may fail in which |
| // case the request should be retried. |
| std::unique_ptr<TestClientDataToResend> push_promise_data_to_resend_; |
| // Number of requests/responses this client has sent/received. |
| size_t num_requests_; |
| size_t num_responses_; |
| |
| // If set, this value is used for the connection SNI, overriding the usual |
| // logic which extracts the SNI from the request URL. |
| bool override_sni_set_ = false; |
| std::string override_sni_; |
| |
| DISALLOW_COPY_AND_ASSIGN(QuicTestClient); |
| }; |
| |
| } // namespace test |
| |
| } // namespace net |
| |
| #endif // NET_TOOLS_QUIC_TEST_TOOLS_QUIC_TEST_CLIENT_H_ |