blob: b76d1cfce204ded52e609cd540194aecef020b2a [file] [log] [blame]
// 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_