QUIC - reorganize common code between quic_client and quic_simple_client
into quic_client_base.* files. R=rch@chromium.org Review URL: https://codereview.chromium.org/1297853002 Cr-Commit-Position: refs/heads/master@{#343810}
This commit is contained in:
@ -1248,6 +1248,8 @@ if (is_android || is_linux) {
|
||||
|
||||
source_set("simple_quic_tools") {
|
||||
sources = [
|
||||
"tools/quic/quic_client_base.cc",
|
||||
"tools/quic/quic_client_base.h",
|
||||
"tools/quic/quic_client_session.cc",
|
||||
"tools/quic/quic_client_session.h",
|
||||
"tools/quic/quic_dispatcher.cc",
|
||||
|
@ -821,6 +821,8 @@
|
||||
'net_quic_proto',
|
||||
],
|
||||
'sources': [
|
||||
'tools/quic/quic_client_base.cc',
|
||||
'tools/quic/quic_client_base.h',
|
||||
'tools/quic/quic_client_session.cc',
|
||||
'tools/quic/quic_client_session.h',
|
||||
'tools/quic/quic_dispatcher.cc',
|
||||
|
@ -15,16 +15,12 @@
|
||||
#include "net/base/net_util.h"
|
||||
#include "net/quic/crypto/quic_random.h"
|
||||
#include "net/quic/quic_connection.h"
|
||||
#include "net/quic/quic_crypto_client_stream.h"
|
||||
#include "net/quic/quic_data_reader.h"
|
||||
#include "net/quic/quic_flags.h"
|
||||
#include "net/quic/quic_protocol.h"
|
||||
#include "net/quic/quic_server_id.h"
|
||||
#include "net/tools/balsa/balsa_headers.h"
|
||||
#include "net/tools/epoll_server/epoll_server.h"
|
||||
#include "net/tools/quic/quic_epoll_connection_helper.h"
|
||||
#include "net/tools/quic/quic_socket_utils.h"
|
||||
#include "net/tools/quic/quic_spdy_client_stream.h"
|
||||
#include "net/tools/quic/spdy_balsa_utils.h"
|
||||
|
||||
#ifndef SO_RXQ_OVFL
|
||||
@ -60,9 +56,8 @@ QuicClient::QuicClient(IPEndPoint server_address,
|
||||
const QuicVersionVector& supported_versions,
|
||||
const QuicConfig& config,
|
||||
EpollServer* epoll_server)
|
||||
: server_address_(server_address),
|
||||
server_id_(server_id),
|
||||
config_(config),
|
||||
: QuicClientBase(server_id, supported_versions, config),
|
||||
server_address_(server_address),
|
||||
local_port_(0),
|
||||
epoll_server_(epoll_server),
|
||||
fd_(-1),
|
||||
@ -70,19 +65,14 @@ QuicClient::QuicClient(IPEndPoint server_address,
|
||||
initialized_(false),
|
||||
packets_dropped_(0),
|
||||
overflow_supported_(false),
|
||||
supported_versions_(supported_versions),
|
||||
store_response_(false),
|
||||
latest_response_code_(-1),
|
||||
initial_max_packet_length_(0),
|
||||
num_stateless_rejects_received_(0),
|
||||
num_sent_client_hellos_(0),
|
||||
connection_error_(QUIC_NO_ERROR),
|
||||
connected_or_attempting_connect_(false) {}
|
||||
latest_response_code_(-1) {}
|
||||
|
||||
QuicClient::~QuicClient() {
|
||||
if (connected()) {
|
||||
session()->connection()->SendConnectionClose(QUIC_PEER_GOING_AWAY);
|
||||
}
|
||||
|
||||
STLDeleteElements(&data_to_resend_on_connect_);
|
||||
STLDeleteElements(&data_sent_before_handshake_);
|
||||
|
||||
@ -90,24 +80,20 @@ QuicClient::~QuicClient() {
|
||||
}
|
||||
|
||||
bool QuicClient::Initialize() {
|
||||
DCHECK(!initialized_);
|
||||
|
||||
num_sent_client_hellos_ = 0;
|
||||
num_stateless_rejects_received_ = 0;
|
||||
connection_error_ = QUIC_NO_ERROR;
|
||||
connected_or_attempting_connect_ = false;
|
||||
QuicClientBase::Initialize();
|
||||
|
||||
// If an initial flow control window has not explicitly been set, then use the
|
||||
// same values that Chrome uses.
|
||||
const uint32 kSessionMaxRecvWindowSize = 15 * 1024 * 1024; // 15 MB
|
||||
const uint32 kStreamMaxRecvWindowSize = 6 * 1024 * 1024; // 6 MB
|
||||
if (config_.GetInitialStreamFlowControlWindowToSend() ==
|
||||
if (config()->GetInitialStreamFlowControlWindowToSend() ==
|
||||
kMinimumFlowControlSendWindow) {
|
||||
config_.SetInitialStreamFlowControlWindowToSend(kStreamMaxRecvWindowSize);
|
||||
config()->SetInitialStreamFlowControlWindowToSend(kStreamMaxRecvWindowSize);
|
||||
}
|
||||
if (config_.GetInitialSessionFlowControlWindowToSend() ==
|
||||
if (config()->GetInitialSessionFlowControlWindowToSend() ==
|
||||
kMinimumFlowControlSendWindow) {
|
||||
config_.SetInitialSessionFlowControlWindowToSend(kSessionMaxRecvWindowSize);
|
||||
config()->SetInitialSessionFlowControlWindowToSend(
|
||||
kSessionMaxRecvWindowSize);
|
||||
}
|
||||
|
||||
epoll_server_->set_timeout_in_us(50 * 1000);
|
||||
@ -121,17 +107,6 @@ bool QuicClient::Initialize() {
|
||||
return true;
|
||||
}
|
||||
|
||||
QuicClient::DummyPacketWriterFactory::DummyPacketWriterFactory(
|
||||
QuicPacketWriter* writer)
|
||||
: writer_(writer) {}
|
||||
|
||||
QuicClient::DummyPacketWriterFactory::~DummyPacketWriterFactory() {}
|
||||
|
||||
QuicPacketWriter* QuicClient::DummyPacketWriterFactory::Create(
|
||||
QuicConnection* /*connection*/) const {
|
||||
return writer_;
|
||||
}
|
||||
|
||||
QuicClient::QuicDataToResend::QuicDataToResend(BalsaHeaders* headers,
|
||||
StringPiece body,
|
||||
bool fin)
|
||||
@ -226,8 +201,8 @@ bool QuicClient::Connect() {
|
||||
}
|
||||
STLDeleteElements(&data_to_resend_on_connect_);
|
||||
}
|
||||
if (session_.get() != nullptr &&
|
||||
session_->error() != QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT) {
|
||||
if (session() != nullptr &&
|
||||
session()->error() != QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT) {
|
||||
// We've successfully created a session but we're not connected, and there
|
||||
// is no stateless reject to recover from. Give up trying.
|
||||
break;
|
||||
@ -235,20 +210,12 @@ bool QuicClient::Connect() {
|
||||
}
|
||||
if (!connected() &&
|
||||
GetNumSentClientHellos() > QuicCryptoClientStream::kMaxClientHellos &&
|
||||
session_ != nullptr &&
|
||||
session_->error() == QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT) {
|
||||
session() != nullptr &&
|
||||
session()->error() == QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT) {
|
||||
// The overall connection failed due too many stateless rejects.
|
||||
connection_error_ = QUIC_CRYPTO_TOO_MANY_REJECTS;
|
||||
set_connection_error(QUIC_CRYPTO_TOO_MANY_REJECTS);
|
||||
}
|
||||
return session_->connection()->connected();
|
||||
}
|
||||
|
||||
QuicClientSession* QuicClient::CreateQuicClientSession(
|
||||
const QuicConfig& config,
|
||||
QuicConnection* connection,
|
||||
const QuicServerId& server_id,
|
||||
QuicCryptoClientConfig* crypto_config) {
|
||||
return new QuicClientSession(config, connection, server_id_, &crypto_config_);
|
||||
return session()->connection()->connected();
|
||||
}
|
||||
|
||||
void QuicClient::StartConnect() {
|
||||
@ -259,45 +226,31 @@ void QuicClient::StartConnect() {
|
||||
|
||||
DummyPacketWriterFactory factory(writer);
|
||||
|
||||
if (connected_or_attempting_connect_) {
|
||||
if (connected_or_attempting_connect()) {
|
||||
// Before we destroy the last session and create a new one, gather its stats
|
||||
// and update the stats for the overall connection.
|
||||
num_sent_client_hellos_ += session_->GetNumSentClientHellos();
|
||||
if (session_->error() == QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT) {
|
||||
UpdateStats();
|
||||
if (session()->error() == QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT) {
|
||||
// If the last error was due to a stateless reject, queue up the data to
|
||||
// be resent on the next successful connection.
|
||||
// TODO(jokulik): I'm a little bit concerned about ordering here. Maybe
|
||||
// we should just maintain one queue?
|
||||
++num_stateless_rejects_received_;
|
||||
DCHECK(data_to_resend_on_connect_.empty());
|
||||
data_to_resend_on_connect_.swap(data_sent_before_handshake_);
|
||||
}
|
||||
}
|
||||
|
||||
session_.reset(CreateQuicClientSession(
|
||||
config_,
|
||||
new QuicConnection(GetNextConnectionId(), server_address_, helper_.get(),
|
||||
factory,
|
||||
/* owns_writer= */ false, Perspective::IS_CLIENT,
|
||||
server_id_.is_https(), supported_versions_),
|
||||
server_id_, &crypto_config_));
|
||||
if (initial_max_packet_length_ != 0) {
|
||||
session_->connection()->set_max_packet_length(initial_max_packet_length_);
|
||||
}
|
||||
CreateQuicClientSession(new QuicConnection(
|
||||
GetNextConnectionId(), server_address_, helper_.get(), factory,
|
||||
/* owns_writer= */ false, Perspective::IS_CLIENT, server_id().is_https(),
|
||||
supported_versions()));
|
||||
|
||||
// Reset |writer_| after |session_| so that the old writer outlives the old
|
||||
// Reset |writer_| after |session()| so that the old writer outlives the old
|
||||
// session.
|
||||
if (writer_.get() != writer) {
|
||||
writer_.reset(writer);
|
||||
}
|
||||
session_->Initialize();
|
||||
session_->CryptoConnect();
|
||||
connected_or_attempting_connect_ = true;
|
||||
}
|
||||
|
||||
bool QuicClient::EncryptionBeingEstablished() {
|
||||
return !session_->IsEncryptionEstablished() &&
|
||||
session_->connection()->connected();
|
||||
set_writer(writer);
|
||||
session()->Initialize();
|
||||
session()->CryptoConnect();
|
||||
set_connected_or_attempting_connect(true);
|
||||
}
|
||||
|
||||
void QuicClient::Disconnect() {
|
||||
@ -351,7 +304,7 @@ void QuicClient::SendRequest(const BalsaHeaders& headers,
|
||||
|
||||
void QuicClient::MaybeAddQuicDataToResend(QuicDataToResend* data_to_resend) {
|
||||
DCHECK(FLAGS_enable_quic_stateless_reject_support);
|
||||
if (session_->IsCryptoHandshakeConfirmed()) {
|
||||
if (session()->IsCryptoHandshakeConfirmed()) {
|
||||
// The handshake is confirmed. No need to continue saving requests to
|
||||
// resend.
|
||||
STLDeleteElements(&data_sent_before_handshake_);
|
||||
@ -382,45 +335,21 @@ void QuicClient::SendRequestsAndWaitForResponse(
|
||||
while (WaitForEvents()) {}
|
||||
}
|
||||
|
||||
QuicSpdyClientStream* QuicClient::CreateReliableClientStream() {
|
||||
if (!connected()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return session_->CreateOutgoingDynamicStream();
|
||||
}
|
||||
|
||||
void QuicClient::WaitForStreamToClose(QuicStreamId id) {
|
||||
DCHECK(connected());
|
||||
|
||||
while (connected() && !session_->IsClosedStream(id)) {
|
||||
WaitForEvents();
|
||||
}
|
||||
}
|
||||
|
||||
void QuicClient::WaitForCryptoHandshakeConfirmed() {
|
||||
DCHECK(connected());
|
||||
|
||||
while (connected() && !session_->IsCryptoHandshakeConfirmed()) {
|
||||
WaitForEvents();
|
||||
}
|
||||
}
|
||||
|
||||
bool QuicClient::WaitForEvents() {
|
||||
DCHECK(connected());
|
||||
|
||||
epoll_server_->WaitForEventsAndExecuteCallbacks();
|
||||
|
||||
DCHECK(session_ != nullptr);
|
||||
DCHECK(session() != nullptr);
|
||||
if (!connected() &&
|
||||
session_->error() == QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT) {
|
||||
session()->error() == QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT) {
|
||||
DCHECK(FLAGS_enable_quic_stateless_reject_support);
|
||||
DVLOG(1) << "Detected stateless reject while waiting for events. "
|
||||
<< "Attempting to reconnect.";
|
||||
Connect();
|
||||
}
|
||||
|
||||
return session_->num_active_requests() != 0;
|
||||
return session()->num_active_requests() != 0;
|
||||
}
|
||||
|
||||
bool QuicClient::MigrateSocket(const IPAddressNumber& new_host) {
|
||||
@ -436,14 +365,12 @@ bool QuicClient::MigrateSocket(const IPAddressNumber& new_host) {
|
||||
}
|
||||
|
||||
epoll_server_->RegisterFD(fd_, this, kEpollFlags);
|
||||
session_->connection()->SetSelfAddress(client_address_);
|
||||
session()->connection()->SetSelfAddress(client_address_);
|
||||
|
||||
QuicPacketWriter* writer = CreateQuicPacketWriter();
|
||||
DummyPacketWriterFactory factory(writer);
|
||||
if (writer_.get() != writer) {
|
||||
writer_.reset(writer);
|
||||
}
|
||||
session_->connection()->SetQuicPacketWriter(writer, false);
|
||||
set_writer(writer);
|
||||
session()->connection()->SetQuicPacketWriter(writer, false);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -456,8 +383,8 @@ void QuicClient::OnEvent(int fd, EpollEvent* event) {
|
||||
}
|
||||
}
|
||||
if (connected() && (event->in_events & EPOLLOUT)) {
|
||||
writer_->SetWritable();
|
||||
session_->connection()->OnCanWrite();
|
||||
writer()->SetWritable();
|
||||
session()->connection()->OnCanWrite();
|
||||
}
|
||||
if (event->in_events & EPOLLERR) {
|
||||
DVLOG(1) << "Epollerr";
|
||||
@ -485,15 +412,6 @@ void QuicClient::OnClose(QuicDataStream* stream) {
|
||||
}
|
||||
}
|
||||
|
||||
bool QuicClient::connected() const {
|
||||
return session_.get() && session_->connection() &&
|
||||
session_->connection()->connected();
|
||||
}
|
||||
|
||||
bool QuicClient::goaway_received() const {
|
||||
return session_ != nullptr && session_->goaway_received();
|
||||
}
|
||||
|
||||
size_t QuicClient::latest_response_code() const {
|
||||
LOG_IF(DFATAL, !store_response_) << "Response not stored!";
|
||||
return latest_response_code_;
|
||||
@ -509,49 +427,6 @@ const string& QuicClient::latest_response_body() const {
|
||||
return latest_response_body_;
|
||||
}
|
||||
|
||||
int QuicClient::GetNumSentClientHellos() {
|
||||
// If we are not actively attempting to connect, the session object
|
||||
// corresponds to the previous connection and should not be used.
|
||||
const int current_session_hellos = !connected_or_attempting_connect_
|
||||
? 0
|
||||
: session_->GetNumSentClientHellos();
|
||||
return num_sent_client_hellos_ + current_session_hellos;
|
||||
}
|
||||
|
||||
QuicErrorCode QuicClient::connection_error() const {
|
||||
// Return the high-level error if there was one. Otherwise, return the
|
||||
// connection error from the last session.
|
||||
if (connection_error_ != QUIC_NO_ERROR) {
|
||||
return connection_error_;
|
||||
}
|
||||
if (session_.get() == nullptr) {
|
||||
return QUIC_NO_ERROR;
|
||||
}
|
||||
return session_->error();
|
||||
}
|
||||
|
||||
QuicConnectionId QuicClient::GetNextConnectionId() {
|
||||
QuicConnectionId server_designated_id = GetNextServerDesignatedConnectionId();
|
||||
return server_designated_id ? server_designated_id
|
||||
: GenerateNewConnectionId();
|
||||
}
|
||||
|
||||
QuicConnectionId QuicClient::GetNextServerDesignatedConnectionId() {
|
||||
QuicCryptoClientConfig::CachedState* cached =
|
||||
crypto_config_.LookupOrCreate(server_id_);
|
||||
// If the cached state indicates that we should use a server-designated
|
||||
// connection ID, then return that connection ID.
|
||||
CHECK(cached != nullptr) << "QuicClientCryptoConfig::LookupOrCreate returned "
|
||||
<< "unexpected nullptr.";
|
||||
return cached->has_server_designated_connection_id()
|
||||
? cached->GetNextServerDesignatedConnectionId()
|
||||
: 0;
|
||||
}
|
||||
|
||||
QuicConnectionId QuicClient::GenerateNewConnectionId() {
|
||||
return QuicRandom::GetInstance()->RandUint64();
|
||||
}
|
||||
|
||||
QuicEpollConnectionHelper* QuicClient::CreateQuicConnectionHelper() {
|
||||
return new QuicEpollConnectionHelper(epoll_server_);
|
||||
}
|
||||
@ -587,8 +462,8 @@ bool QuicClient::ReadAndProcessPacket() {
|
||||
QuicEncryptedPacket packet(buf, bytes_read, false);
|
||||
|
||||
IPEndPoint client_address(client_ip, client_address_.port());
|
||||
session_->connection()->ProcessUdpPacket(
|
||||
client_address, server_address, packet);
|
||||
session()->connection()->ProcessUdpPacket(client_address, server_address,
|
||||
packet);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -15,18 +15,14 @@
|
||||
#include "base/memory/scoped_ptr.h"
|
||||
#include "base/strings/string_piece.h"
|
||||
#include "net/base/ip_endpoint.h"
|
||||
#include "net/quic/crypto/crypto_handshake.h"
|
||||
#include "net/quic/quic_config.h"
|
||||
#include "net/quic/quic_framer.h"
|
||||
#include "net/quic/quic_packet_creator.h"
|
||||
#include "net/quic/quic_data_stream.h"
|
||||
#include "net/tools/balsa/balsa_headers.h"
|
||||
#include "net/tools/epoll_server/epoll_server.h"
|
||||
#include "net/tools/quic/quic_client_session.h"
|
||||
#include "net/tools/quic/quic_spdy_client_stream.h"
|
||||
#include "net/tools/quic/quic_client_base.h"
|
||||
|
||||
namespace net {
|
||||
|
||||
class ProofVerifier;
|
||||
class QuicServerId;
|
||||
|
||||
namespace tools {
|
||||
@ -37,7 +33,8 @@ namespace test {
|
||||
class QuicClientPeer;
|
||||
} // namespace test
|
||||
|
||||
class QuicClient : public EpollCallbackInterface,
|
||||
class QuicClient : public QuicClientBase,
|
||||
public EpollCallbackInterface,
|
||||
public QuicDataStream::Visitor {
|
||||
public:
|
||||
class ResponseListener {
|
||||
@ -49,18 +46,6 @@ class QuicClient : public EpollCallbackInterface,
|
||||
const std::string& response_body) = 0;
|
||||
};
|
||||
|
||||
// A packet writer factory that always returns the same writer.
|
||||
class DummyPacketWriterFactory : public QuicConnection::PacketWriterFactory {
|
||||
public:
|
||||
explicit DummyPacketWriterFactory(QuicPacketWriter* writer);
|
||||
~DummyPacketWriterFactory() override;
|
||||
|
||||
QuicPacketWriter* Create(QuicConnection* connection) const override;
|
||||
|
||||
private:
|
||||
QuicPacketWriter* writer_;
|
||||
};
|
||||
|
||||
// The client uses these objects to keep track of any data to resend upon
|
||||
// receipt of a stateless reject. Recall that the client API allows callers
|
||||
// to optimistically send data to the server prior to handshake-confirmation.
|
||||
@ -103,10 +88,9 @@ class QuicClient : public EpollCallbackInterface,
|
||||
|
||||
~QuicClient() override;
|
||||
|
||||
// Initializes the client to create a connection. Should be called exactly
|
||||
// once before calling StartConnect or Connect. Returns true if the
|
||||
// initialization succeeds, false otherwise.
|
||||
bool Initialize();
|
||||
// From QuicClientBase
|
||||
bool Initialize() override;
|
||||
bool WaitForEvents() override;
|
||||
|
||||
// "Connect" to the QUIC server, including performing synchronous crypto
|
||||
// handshake.
|
||||
@ -117,11 +101,6 @@ class QuicClient : public EpollCallbackInterface,
|
||||
// completes.
|
||||
void StartConnect();
|
||||
|
||||
// Returns true if the crypto handshake has yet to establish encryption.
|
||||
// Returns false if encryption is active (even if the server hasn't confirmed
|
||||
// the handshake) or if the connection has been closed.
|
||||
bool EncryptionBeingEstablished();
|
||||
|
||||
// Disconnects from the QUIC server.
|
||||
void Disconnect();
|
||||
|
||||
@ -140,20 +119,6 @@ class QuicClient : public EpollCallbackInterface,
|
||||
void SendRequestsAndWaitForResponse(
|
||||
const std::vector<std::string>& url_list);
|
||||
|
||||
// Returns a newly created QuicSpdyClientStream, owned by the
|
||||
// QuicClient.
|
||||
QuicSpdyClientStream* CreateReliableClientStream();
|
||||
|
||||
// Wait for events until the stream with the given ID is closed.
|
||||
void WaitForStreamToClose(QuicStreamId id);
|
||||
|
||||
// Wait for events until the handshake is confirmed.
|
||||
void WaitForCryptoHandshakeConfirmed();
|
||||
|
||||
// Wait up to 50ms, and handle any events which occur.
|
||||
// Returns true if there are any outstanding requests.
|
||||
bool WaitForEvents();
|
||||
|
||||
// Migrate to a new socket during an active connection.
|
||||
bool MigrateSocket(const IPAddressNumber& new_host);
|
||||
|
||||
@ -175,11 +140,6 @@ class QuicClient : public EpollCallbackInterface,
|
||||
// Otherwise, deletes the data. Takes ownerership of |data_to_resend|.
|
||||
void MaybeAddQuicDataToResend(QuicDataToResend* data_to_resend);
|
||||
|
||||
QuicClientSession* session() { return session_.get(); }
|
||||
|
||||
bool connected() const;
|
||||
bool goaway_received() const;
|
||||
|
||||
void set_bind_to_address(IPAddressNumber address) {
|
||||
bind_to_address_ = address;
|
||||
}
|
||||
@ -194,87 +154,18 @@ class QuicClient : public EpollCallbackInterface,
|
||||
|
||||
int fd() { return fd_; }
|
||||
|
||||
const QuicServerId& server_id() const { return server_id_; }
|
||||
|
||||
// This should only be set before the initial Connect()
|
||||
void set_server_id(const QuicServerId& server_id) {
|
||||
server_id_ = server_id;
|
||||
}
|
||||
|
||||
void SetUserAgentID(const std::string& user_agent_id) {
|
||||
crypto_config_.set_user_agent_id(user_agent_id);
|
||||
}
|
||||
|
||||
// SetProofVerifier sets the ProofVerifier that will be used to verify the
|
||||
// server's certificate and takes ownership of |verifier|.
|
||||
void SetProofVerifier(ProofVerifier* verifier) {
|
||||
// TODO(rtenneti): We should set ProofVerifier in QuicClientSession.
|
||||
crypto_config_.SetProofVerifier(verifier);
|
||||
}
|
||||
|
||||
// SetChannelIDSource sets a ChannelIDSource that will be called, when the
|
||||
// server supports channel IDs, to obtain a channel ID for signing a message
|
||||
// proving possession of the channel ID. This object takes ownership of
|
||||
// |source|.
|
||||
void SetChannelIDSource(ChannelIDSource* source) {
|
||||
crypto_config_.SetChannelIDSource(source);
|
||||
}
|
||||
|
||||
void SetSupportedVersions(const QuicVersionVector& versions) {
|
||||
supported_versions_ = versions;
|
||||
}
|
||||
|
||||
// Takes ownership of the listener.
|
||||
void set_response_listener(ResponseListener* listener) {
|
||||
response_listener_.reset(listener);
|
||||
}
|
||||
|
||||
QuicConfig* config() { return &config_; }
|
||||
|
||||
void set_store_response(bool val) { store_response_ = val; }
|
||||
|
||||
size_t latest_response_code() const;
|
||||
const std::string& latest_response_headers() const;
|
||||
const std::string& latest_response_body() const;
|
||||
|
||||
// Change the initial maximum packet size of the connection. Has to be called
|
||||
// before Connect()/StartConnect() in order to have any effect.
|
||||
void set_initial_max_packet_length(QuicByteCount initial_max_packet_length) {
|
||||
initial_max_packet_length_ = initial_max_packet_length;
|
||||
}
|
||||
|
||||
int num_stateless_rejects_received() const {
|
||||
return num_stateless_rejects_received_;
|
||||
}
|
||||
|
||||
// The number of client hellos sent, taking stateless rejects into
|
||||
// account. In the case of a stateless reject, the initial
|
||||
// connection object may be torn down and a new one created. The
|
||||
// user cannot rely upon the latest connection object to get the
|
||||
// total number of client hellos sent, and should use this function
|
||||
// instead.
|
||||
int GetNumSentClientHellos();
|
||||
|
||||
// Returns any errors that occurred at the connection-level (as
|
||||
// opposed to the session-level). When a stateless reject occurs,
|
||||
// the error of the last session may not reflect the overall state
|
||||
// of the connection.
|
||||
QuicErrorCode connection_error() const;
|
||||
|
||||
protected:
|
||||
// Generates the next ConnectionId for |server_id_|. By default, if the
|
||||
// cached server config contains a server-designated ID, that ID will be
|
||||
// returned. Otherwise, the next random ID will be returned.
|
||||
QuicConnectionId GetNextConnectionId();
|
||||
|
||||
// Returns the next server-designated ConnectionId from the cached config for
|
||||
// |server_id_|, if it exists. Otherwise, returns 0.
|
||||
QuicConnectionId GetNextServerDesignatedConnectionId();
|
||||
|
||||
// Generates a new, random connection ID (as opposed to a server-designated
|
||||
// connection ID).
|
||||
virtual QuicConnectionId GenerateNewConnectionId();
|
||||
|
||||
virtual QuicEpollConnectionHelper* CreateQuicConnectionHelper();
|
||||
virtual QuicPacketWriter* CreateQuicPacketWriter();
|
||||
|
||||
@ -283,12 +174,6 @@ class QuicClient : public EpollCallbackInterface,
|
||||
IPEndPoint* server_address,
|
||||
IPAddressNumber* client_ip);
|
||||
|
||||
virtual QuicClientSession* CreateQuicClientSession(
|
||||
const QuicConfig& config,
|
||||
QuicConnection* connection,
|
||||
const QuicServerId& server_id,
|
||||
QuicCryptoClientConfig* crypto_config);
|
||||
|
||||
EpollServer* epoll_server() { return epoll_server_; }
|
||||
|
||||
// If the socket has been created, then unregister and close() the FD.
|
||||
@ -333,14 +218,6 @@ class QuicClient : public EpollCallbackInterface,
|
||||
// Address of the server.
|
||||
const IPEndPoint server_address_;
|
||||
|
||||
// |server_id_| is a tuple (hostname, port, is_https) of the server.
|
||||
QuicServerId server_id_;
|
||||
|
||||
// config_ and crypto_config_ contain configuration and cached state about
|
||||
// servers.
|
||||
QuicConfig config_;
|
||||
QuicCryptoClientConfig crypto_config_;
|
||||
|
||||
// Address of the client if the client is connected to the server.
|
||||
IPEndPoint client_address_;
|
||||
|
||||
@ -349,12 +226,6 @@ class QuicClient : public EpollCallbackInterface,
|
||||
// Local port to bind to. Initialize to 0.
|
||||
int local_port_;
|
||||
|
||||
// Writer used to actually send packets to the wire. Needs to outlive
|
||||
// |session_|.
|
||||
scoped_ptr<QuicPacketWriter> writer_;
|
||||
|
||||
// Session which manages streams.
|
||||
scoped_ptr<QuicClientSession> session_;
|
||||
// Listens for events on the client socket.
|
||||
EpollServer* epoll_server_;
|
||||
// UDP socket.
|
||||
@ -377,13 +248,6 @@ class QuicClient : public EpollCallbackInterface,
|
||||
// because the socket would otherwise overflow.
|
||||
bool overflow_supported_;
|
||||
|
||||
// This vector contains QUIC versions which we currently support.
|
||||
// This should be ordered such that the highest supported version is the first
|
||||
// element, with subsequent elements in descending order (versions can be
|
||||
// skipped as necessary). We will always pick supported_versions_[0] as the
|
||||
// initial version to use.
|
||||
QuicVersionVector supported_versions_;
|
||||
|
||||
// If true, store the latest response code, headers, and body.
|
||||
bool store_response_;
|
||||
// HTTP response code from most recent response.
|
||||
@ -393,31 +257,6 @@ class QuicClient : public EpollCallbackInterface,
|
||||
// Body of most recent response.
|
||||
std::string latest_response_body_;
|
||||
|
||||
// The initial value of maximum packet size of the connection. If set to
|
||||
// zero, the default is used.
|
||||
QuicByteCount initial_max_packet_length_;
|
||||
|
||||
// The number of stateless rejects received during the current/latest
|
||||
// connection.
|
||||
// TODO(jokulik): Consider some consistent naming scheme (or other) for member
|
||||
// variables that are kept per-request, per-connection, and over the client's
|
||||
// lifetime.
|
||||
int num_stateless_rejects_received_;
|
||||
|
||||
// The number of hellos sent during the current/latest connection.
|
||||
int num_sent_client_hellos_;
|
||||
|
||||
// Used to store any errors that occurred with the overall connection (as
|
||||
// opposed to that associated with the last session object).
|
||||
QuicErrorCode connection_error_;
|
||||
|
||||
// True when the client is attempting to connect or re-connect the session (in
|
||||
// the case of a stateless reject). Set to false between a call to
|
||||
// Disconnect() and the subsequent call to StartConnect(). When
|
||||
// connected_or_attempting_connect_ is false, the session object corresponds
|
||||
// to the previous client-level connection.
|
||||
bool connected_or_attempting_connect_;
|
||||
|
||||
// Keeps track of any data sent before the handshake.
|
||||
std::vector<QuicDataToResend*> data_sent_before_handshake_;
|
||||
|
||||
|
145
net/tools/quic/quic_client_base.cc
Normal file
145
net/tools/quic/quic_client_base.cc
Normal file
@ -0,0 +1,145 @@
|
||||
// Copyright (c) 2015 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.
|
||||
|
||||
#include "net/tools/quic/quic_client_base.h"
|
||||
|
||||
#include "net/quic/crypto/quic_random.h"
|
||||
#include "net/quic/quic_server_id.h"
|
||||
|
||||
namespace net {
|
||||
namespace tools {
|
||||
|
||||
QuicClientBase::QuicClientBase(const QuicServerId& server_id,
|
||||
const QuicVersionVector& supported_versions,
|
||||
const QuicConfig& config)
|
||||
: server_id_(server_id),
|
||||
config_(config),
|
||||
supported_versions_(supported_versions),
|
||||
initial_max_packet_length_(0),
|
||||
num_stateless_rejects_received_(0),
|
||||
num_sent_client_hellos_(0),
|
||||
connection_error_(QUIC_NO_ERROR),
|
||||
connected_or_attempting_connect_(false) {}
|
||||
|
||||
QuicClientBase::~QuicClientBase() {}
|
||||
|
||||
bool QuicClientBase::Initialize() {
|
||||
num_sent_client_hellos_ = 0;
|
||||
num_stateless_rejects_received_ = 0;
|
||||
connection_error_ = QUIC_NO_ERROR;
|
||||
connected_or_attempting_connect_ = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
QuicClientBase::DummyPacketWriterFactory::DummyPacketWriterFactory(
|
||||
QuicPacketWriter* writer)
|
||||
: writer_(writer) {}
|
||||
|
||||
QuicClientBase::DummyPacketWriterFactory::~DummyPacketWriterFactory() {}
|
||||
|
||||
QuicPacketWriter* QuicClientBase::DummyPacketWriterFactory::Create(
|
||||
QuicConnection* /*connection*/) const {
|
||||
return writer_;
|
||||
}
|
||||
|
||||
QuicClientSession* QuicClientBase::CreateQuicClientSession(
|
||||
QuicConnection* connection) {
|
||||
session_.reset(
|
||||
new QuicClientSession(config_, connection, server_id_, &crypto_config_));
|
||||
if (initial_max_packet_length_ != 0) {
|
||||
session()->connection()->set_max_packet_length(initial_max_packet_length_);
|
||||
}
|
||||
return session_.get();
|
||||
}
|
||||
|
||||
bool QuicClientBase::EncryptionBeingEstablished() {
|
||||
return !session_->IsEncryptionEstablished() &&
|
||||
session_->connection()->connected();
|
||||
}
|
||||
|
||||
QuicSpdyClientStream* QuicClientBase::CreateReliableClientStream() {
|
||||
if (!connected()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return session_->CreateOutgoingDynamicStream();
|
||||
}
|
||||
|
||||
void QuicClientBase::WaitForStreamToClose(QuicStreamId id) {
|
||||
DCHECK(connected());
|
||||
|
||||
while (connected() && !session_->IsClosedStream(id)) {
|
||||
WaitForEvents();
|
||||
}
|
||||
}
|
||||
|
||||
void QuicClientBase::WaitForCryptoHandshakeConfirmed() {
|
||||
DCHECK(connected());
|
||||
|
||||
while (connected() && !session_->IsCryptoHandshakeConfirmed()) {
|
||||
WaitForEvents();
|
||||
}
|
||||
}
|
||||
|
||||
bool QuicClientBase::connected() const {
|
||||
return session_.get() && session_->connection() &&
|
||||
session_->connection()->connected();
|
||||
}
|
||||
|
||||
bool QuicClientBase::goaway_received() const {
|
||||
return session_ != nullptr && session_->goaway_received();
|
||||
}
|
||||
|
||||
int QuicClientBase::GetNumSentClientHellos() {
|
||||
// If we are not actively attempting to connect, the session object
|
||||
// corresponds to the previous connection and should not be used.
|
||||
const int current_session_hellos = !connected_or_attempting_connect_
|
||||
? 0
|
||||
: session_->GetNumSentClientHellos();
|
||||
return num_sent_client_hellos_ + current_session_hellos;
|
||||
}
|
||||
|
||||
void QuicClientBase::UpdateStats() {
|
||||
num_sent_client_hellos_ += session()->GetNumSentClientHellos();
|
||||
if (session()->error() == QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT) {
|
||||
++num_stateless_rejects_received_;
|
||||
}
|
||||
}
|
||||
|
||||
QuicErrorCode QuicClientBase::connection_error() const {
|
||||
// Return the high-level error if there was one. Otherwise, return the
|
||||
// connection error from the last session.
|
||||
if (connection_error_ != QUIC_NO_ERROR) {
|
||||
return connection_error_;
|
||||
}
|
||||
if (session_.get() == nullptr) {
|
||||
return QUIC_NO_ERROR;
|
||||
}
|
||||
return session_->error();
|
||||
}
|
||||
|
||||
QuicConnectionId QuicClientBase::GetNextConnectionId() {
|
||||
QuicConnectionId server_designated_id = GetNextServerDesignatedConnectionId();
|
||||
return server_designated_id ? server_designated_id
|
||||
: GenerateNewConnectionId();
|
||||
}
|
||||
|
||||
QuicConnectionId QuicClientBase::GetNextServerDesignatedConnectionId() {
|
||||
QuicCryptoClientConfig::CachedState* cached =
|
||||
crypto_config_.LookupOrCreate(server_id_);
|
||||
// If the cached state indicates that we should use a server-designated
|
||||
// connection ID, then return that connection ID.
|
||||
CHECK(cached != nullptr) << "QuicClientCryptoConfig::LookupOrCreate returned "
|
||||
<< "unexpected nullptr.";
|
||||
return cached->has_server_designated_connection_id()
|
||||
? cached->GetNextServerDesignatedConnectionId()
|
||||
: 0;
|
||||
}
|
||||
|
||||
QuicConnectionId QuicClientBase::GenerateNewConnectionId() {
|
||||
return QuicRandom::GetInstance()->RandUint64();
|
||||
}
|
||||
|
||||
} // namespace tools
|
||||
} // namespace net
|
241
net/tools/quic/quic_client_base.h
Normal file
241
net/tools/quic/quic_client_base.h
Normal file
@ -0,0 +1,241 @@
|
||||
// Copyright (c) 2015 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.
|
||||
//
|
||||
// A base class for the toy client, which connects to a specified port and sends
|
||||
// QUIC request to that endpoint.
|
||||
|
||||
#ifndef NET_TOOLS_QUIC_QUIC_CLIENT_BASE_H_
|
||||
#define NET_TOOLS_QUIC_QUIC_CLIENT_BASE_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "base/basictypes.h"
|
||||
#include "base/memory/scoped_ptr.h"
|
||||
#include "net/base/ip_endpoint.h"
|
||||
#include "net/log/net_log.h"
|
||||
#include "net/quic/crypto/crypto_handshake.h"
|
||||
#include "net/quic/crypto/quic_crypto_client_config.h"
|
||||
#include "net/quic/quic_bandwidth.h"
|
||||
#include "net/quic/quic_config.h"
|
||||
#include "net/quic/quic_connection.h"
|
||||
#include "net/quic/quic_packet_writer.h"
|
||||
#include "net/quic/quic_protocol.h"
|
||||
#include "net/tools/quic/quic_client_session.h"
|
||||
#include "net/tools/quic/quic_spdy_client_stream.h"
|
||||
|
||||
namespace net {
|
||||
|
||||
class ProofVerifier;
|
||||
class QuicServerId;
|
||||
|
||||
namespace tools {
|
||||
|
||||
class QuicClientBase {
|
||||
public:
|
||||
// A packet writer factory that always returns the same writer.
|
||||
class DummyPacketWriterFactory : public QuicConnection::PacketWriterFactory {
|
||||
public:
|
||||
explicit DummyPacketWriterFactory(QuicPacketWriter* writer);
|
||||
~DummyPacketWriterFactory() override;
|
||||
|
||||
QuicPacketWriter* Create(QuicConnection* connection) const override;
|
||||
|
||||
private:
|
||||
QuicPacketWriter* writer_;
|
||||
};
|
||||
|
||||
QuicClientBase(const QuicServerId& server_id,
|
||||
const QuicVersionVector& supported_versions,
|
||||
const QuicConfig& config);
|
||||
|
||||
~QuicClientBase();
|
||||
|
||||
// Initializes the client to create a connection. Should be called exactly
|
||||
// once before calling StartConnect or Connect. Returns true if the
|
||||
// initialization succeeds, false otherwise.
|
||||
virtual bool Initialize();
|
||||
|
||||
// Returns true if the crypto handshake has yet to establish encryption.
|
||||
// Returns false if encryption is active (even if the server hasn't confirmed
|
||||
// the handshake) or if the connection has been closed.
|
||||
bool EncryptionBeingEstablished();
|
||||
|
||||
// Returns a newly created QuicSpdyClientStream, owned by the
|
||||
// QuicSimpleClient.
|
||||
QuicSpdyClientStream* CreateReliableClientStream();
|
||||
|
||||
// Wait for events until the stream with the given ID is closed.
|
||||
void WaitForStreamToClose(QuicStreamId id);
|
||||
|
||||
// Wait for events until the handshake is confirmed.
|
||||
void WaitForCryptoHandshakeConfirmed();
|
||||
|
||||
// Wait up to 50ms, and handle any events which occur.
|
||||
// Returns true if there are any outstanding requests.
|
||||
virtual bool WaitForEvents() = 0;
|
||||
|
||||
QuicClientSession* session() { return session_.get(); }
|
||||
|
||||
bool connected() const;
|
||||
bool goaway_received() const;
|
||||
|
||||
const QuicServerId& server_id() const { return server_id_; }
|
||||
|
||||
// This should only be set before the initial Connect()
|
||||
void set_server_id(const QuicServerId& server_id) { server_id_ = server_id; }
|
||||
|
||||
void SetUserAgentID(const std::string& user_agent_id) {
|
||||
crypto_config_.set_user_agent_id(user_agent_id);
|
||||
}
|
||||
|
||||
// SetProofVerifier sets the ProofVerifier that will be used to verify the
|
||||
// server's certificate and takes ownership of |verifier|.
|
||||
void SetProofVerifier(ProofVerifier* verifier) {
|
||||
// TODO(rtenneti): We should set ProofVerifier in QuicClientSession.
|
||||
crypto_config_.SetProofVerifier(verifier);
|
||||
}
|
||||
|
||||
// SetChannelIDSource sets a ChannelIDSource that will be called, when the
|
||||
// server supports channel IDs, to obtain a channel ID for signing a message
|
||||
// proving possession of the channel ID. This object takes ownership of
|
||||
// |source|.
|
||||
void SetChannelIDSource(ChannelIDSource* source) {
|
||||
crypto_config_.SetChannelIDSource(source);
|
||||
}
|
||||
|
||||
const QuicVersionVector& supported_versions() const {
|
||||
return supported_versions_;
|
||||
}
|
||||
|
||||
void SetSupportedVersions(const QuicVersionVector& versions) {
|
||||
supported_versions_ = versions;
|
||||
}
|
||||
|
||||
QuicConfig* config() { return &config_; }
|
||||
|
||||
QuicCryptoClientConfig* crypto_config() { return &crypto_config_; }
|
||||
|
||||
// Change the initial maximum packet size of the connection. Has to be called
|
||||
// before Connect()/StartConnect() in order to have any effect.
|
||||
void set_initial_max_packet_length(QuicByteCount initial_max_packet_length) {
|
||||
initial_max_packet_length_ = initial_max_packet_length;
|
||||
}
|
||||
|
||||
int num_stateless_rejects_received() const {
|
||||
return num_stateless_rejects_received_;
|
||||
}
|
||||
|
||||
// The number of client hellos sent, taking stateless rejects into
|
||||
// account. In the case of a stateless reject, the initial
|
||||
// connection object may be torn down and a new one created. The
|
||||
// user cannot rely upon the latest connection object to get the
|
||||
// total number of client hellos sent, and should use this function
|
||||
// instead.
|
||||
int GetNumSentClientHellos();
|
||||
|
||||
// Gather the stats for the last session and update the stats for the overall
|
||||
// connection.
|
||||
void UpdateStats();
|
||||
|
||||
// Returns any errors that occurred at the connection-level (as
|
||||
// opposed to the session-level). When a stateless reject occurs,
|
||||
// the error of the last session may not reflect the overall state
|
||||
// of the connection.
|
||||
QuicErrorCode connection_error() const;
|
||||
void set_connection_error(QuicErrorCode connection_error) {
|
||||
connection_error_ = connection_error;
|
||||
}
|
||||
|
||||
bool connected_or_attempting_connect() const {
|
||||
return connected_or_attempting_connect_;
|
||||
}
|
||||
void set_connected_or_attempting_connect(
|
||||
bool connected_or_attempting_connect) {
|
||||
connected_or_attempting_connect_ = connected_or_attempting_connect;
|
||||
}
|
||||
|
||||
QuicPacketWriter* writer() { return writer_.get(); }
|
||||
void set_writer(QuicPacketWriter* writer) {
|
||||
if (writer_.get() != writer) {
|
||||
writer_.reset(writer);
|
||||
}
|
||||
}
|
||||
void reset_writer() { writer_.reset(); }
|
||||
|
||||
QuicByteCount initial_max_packet_length() {
|
||||
return initial_max_packet_length_;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual QuicClientSession* CreateQuicClientSession(
|
||||
QuicConnection* connection);
|
||||
|
||||
// Generates the next ConnectionId for |server_id_|. By default, if the
|
||||
// cached server config contains a server-designated ID, that ID will be
|
||||
// returned. Otherwise, the next random ID will be returned.
|
||||
QuicConnectionId GetNextConnectionId();
|
||||
|
||||
// Returns the next server-designated ConnectionId from the cached config for
|
||||
// |server_id_|, if it exists. Otherwise, returns 0.
|
||||
QuicConnectionId GetNextServerDesignatedConnectionId();
|
||||
|
||||
// Generates a new, random connection ID (as opposed to a server-designated
|
||||
// connection ID).
|
||||
virtual QuicConnectionId GenerateNewConnectionId();
|
||||
|
||||
private:
|
||||
// |server_id_| is a tuple (hostname, port, is_https) of the server.
|
||||
QuicServerId server_id_;
|
||||
|
||||
// config_ and crypto_config_ contain configuration and cached state about
|
||||
// servers.
|
||||
QuicConfig config_;
|
||||
QuicCryptoClientConfig crypto_config_;
|
||||
|
||||
// Writer used to actually send packets to the wire. Needs to outlive
|
||||
// |session_|.
|
||||
scoped_ptr<QuicPacketWriter> writer_;
|
||||
|
||||
// Session which manages streams.
|
||||
scoped_ptr<QuicClientSession> session_;
|
||||
|
||||
// This vector contains QUIC versions which we currently support.
|
||||
// This should be ordered such that the highest supported version is the first
|
||||
// element, with subsequent elements in descending order (versions can be
|
||||
// skipped as necessary). We will always pick supported_versions_[0] as the
|
||||
// initial version to use.
|
||||
QuicVersionVector supported_versions_;
|
||||
|
||||
// The initial value of maximum packet size of the connection. If set to
|
||||
// zero, the default is used.
|
||||
QuicByteCount initial_max_packet_length_;
|
||||
|
||||
// The number of stateless rejects received during the current/latest
|
||||
// connection.
|
||||
// TODO(jokulik): Consider some consistent naming scheme (or other) for member
|
||||
// variables that are kept per-request, per-connection, and over the client's
|
||||
// lifetime.
|
||||
int num_stateless_rejects_received_;
|
||||
|
||||
// The number of hellos sent during the current/latest connection.
|
||||
int num_sent_client_hellos_;
|
||||
|
||||
// Used to store any errors that occurred with the overall connection (as
|
||||
// opposed to that associated with the last session object).
|
||||
QuicErrorCode connection_error_;
|
||||
|
||||
// True when the client is attempting to connect or re-connect the session (in
|
||||
// the case of a stateless reject). Set to false between a call to
|
||||
// Disconnect() and the subsequent call to StartConnect(). When
|
||||
// connected_or_attempting_connect_ is false, the session object corresponds
|
||||
// to the previous client-level connection.
|
||||
bool connected_or_attempting_connect_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(QuicClientBase);
|
||||
};
|
||||
|
||||
} // namespace tools
|
||||
} // namespace net
|
||||
|
||||
#endif // NET_TOOLS_QUIC_QUIC_CLIENT_BASE_H_
|
@ -13,7 +13,6 @@
|
||||
#include "net/quic/crypto/quic_random.h"
|
||||
#include "net/quic/quic_connection.h"
|
||||
#include "net/quic/quic_connection_helper.h"
|
||||
#include "net/quic/quic_crypto_client_stream.h"
|
||||
#include "net/quic/quic_default_packet_writer.h"
|
||||
#include "net/quic/quic_flags.h"
|
||||
#include "net/quic/quic_protocol.h"
|
||||
@ -37,12 +36,11 @@ void QuicSimpleClient::ClientQuicDataToResend::Resend() {
|
||||
QuicSimpleClient::QuicSimpleClient(IPEndPoint server_address,
|
||||
const QuicServerId& server_id,
|
||||
const QuicVersionVector& supported_versions)
|
||||
: server_address_(server_address),
|
||||
server_id_(server_id),
|
||||
: QuicClientBase(server_id, supported_versions, QuicConfig()),
|
||||
server_address_(server_address),
|
||||
local_port_(0),
|
||||
helper_(CreateQuicConnectionHelper()),
|
||||
initialized_(false),
|
||||
supported_versions_(supported_versions),
|
||||
packet_reader_started_(false),
|
||||
weak_factory_(this) {}
|
||||
|
||||
@ -50,18 +48,11 @@ QuicSimpleClient::QuicSimpleClient(IPEndPoint server_address,
|
||||
const QuicServerId& server_id,
|
||||
const QuicVersionVector& supported_versions,
|
||||
const QuicConfig& config)
|
||||
: server_address_(server_address),
|
||||
server_id_(server_id),
|
||||
config_(config),
|
||||
: QuicClientBase(server_id, supported_versions, config),
|
||||
server_address_(server_address),
|
||||
local_port_(0),
|
||||
helper_(CreateQuicConnectionHelper()),
|
||||
initialized_(false),
|
||||
supported_versions_(supported_versions),
|
||||
initial_max_packet_length_(0),
|
||||
num_stateless_rejects_received_(0),
|
||||
num_sent_client_hellos_(0),
|
||||
connection_error_(QUIC_NO_ERROR),
|
||||
connected_or_attempting_connect_(false),
|
||||
packet_reader_started_(false),
|
||||
weak_factory_(this) {}
|
||||
|
||||
@ -77,10 +68,7 @@ QuicSimpleClient::~QuicSimpleClient() {
|
||||
bool QuicSimpleClient::Initialize() {
|
||||
DCHECK(!initialized_);
|
||||
|
||||
num_sent_client_hellos_ = 0;
|
||||
num_stateless_rejects_received_ = 0;
|
||||
connection_error_ = QUIC_NO_ERROR;
|
||||
connected_or_attempting_connect_ = false;
|
||||
QuicClientBase::Initialize();
|
||||
|
||||
if (!CreateUDPSocket()) {
|
||||
return false;
|
||||
@ -90,17 +78,6 @@ bool QuicSimpleClient::Initialize() {
|
||||
return true;
|
||||
}
|
||||
|
||||
QuicSimpleClient::DummyPacketWriterFactory::DummyPacketWriterFactory(
|
||||
QuicPacketWriter* writer)
|
||||
: writer_(writer) {}
|
||||
|
||||
QuicSimpleClient::DummyPacketWriterFactory::~DummyPacketWriterFactory() {}
|
||||
|
||||
QuicPacketWriter* QuicSimpleClient::DummyPacketWriterFactory::Create(
|
||||
QuicConnection* /*connection*/) const {
|
||||
return writer_;
|
||||
}
|
||||
|
||||
QuicSimpleClient::QuicDataToResend::QuicDataToResend(HttpRequestInfo* headers,
|
||||
StringPiece body,
|
||||
bool fin)
|
||||
@ -193,8 +170,8 @@ bool QuicSimpleClient::Connect() {
|
||||
}
|
||||
STLDeleteElements(&data_to_resend_on_connect_);
|
||||
}
|
||||
if (session_.get() != nullptr &&
|
||||
session_->error() != QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT) {
|
||||
if (session() != nullptr &&
|
||||
session()->error() != QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT) {
|
||||
// We've successfully created a session but we're not connected, and there
|
||||
// is no stateless reject to recover from. Give up trying.
|
||||
break;
|
||||
@ -202,63 +179,44 @@ bool QuicSimpleClient::Connect() {
|
||||
}
|
||||
if (!connected() &&
|
||||
GetNumSentClientHellos() > QuicCryptoClientStream::kMaxClientHellos &&
|
||||
session_ != nullptr &&
|
||||
session_->error() == QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT) {
|
||||
session() != nullptr &&
|
||||
session()->error() == QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT) {
|
||||
// The overall connection failed due too many stateless rejects.
|
||||
connection_error_ = QUIC_CRYPTO_TOO_MANY_REJECTS;
|
||||
set_connection_error(QUIC_CRYPTO_TOO_MANY_REJECTS);
|
||||
}
|
||||
return session_->connection()->connected();
|
||||
}
|
||||
|
||||
QuicClientSession* QuicSimpleClient::CreateQuicClientSession(
|
||||
const QuicConfig& config,
|
||||
QuicConnection* connection,
|
||||
const QuicServerId& server_id,
|
||||
QuicCryptoClientConfig* crypto_config) {
|
||||
return new QuicClientSession(config, connection, server_id_, &crypto_config_);
|
||||
return session()->connection()->connected();
|
||||
}
|
||||
|
||||
void QuicSimpleClient::StartConnect() {
|
||||
DCHECK(initialized_);
|
||||
DCHECK(!connected());
|
||||
|
||||
writer_.reset(CreateQuicPacketWriter());
|
||||
set_writer(CreateQuicPacketWriter());
|
||||
|
||||
DummyPacketWriterFactory factory(writer_.get());
|
||||
DummyPacketWriterFactory factory(writer());
|
||||
|
||||
if (connected_or_attempting_connect_) {
|
||||
if (connected_or_attempting_connect()) {
|
||||
// Before we destroy the last session and create a new one, gather its stats
|
||||
// and update the stats for the overall connection.
|
||||
num_sent_client_hellos_ += session_->GetNumSentClientHellos();
|
||||
if (session_->error() == QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT) {
|
||||
UpdateStats();
|
||||
if (session()->error() == QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT) {
|
||||
// If the last error was due to a stateless reject, queue up the data to
|
||||
// be resent on the next successful connection.
|
||||
// TODO(jokulik): I'm a little bit concerned about ordering here. Maybe
|
||||
// we should just maintain one queue?
|
||||
++num_stateless_rejects_received_;
|
||||
DCHECK(data_to_resend_on_connect_.empty());
|
||||
data_to_resend_on_connect_.swap(data_sent_before_handshake_);
|
||||
}
|
||||
}
|
||||
|
||||
session_.reset(CreateQuicClientSession(
|
||||
config_,
|
||||
new QuicConnection(GetNextConnectionId(), server_address_, helper_.get(),
|
||||
factory,
|
||||
/* owns_writer= */ false, Perspective::IS_CLIENT,
|
||||
server_id_.is_https(), supported_versions_),
|
||||
server_id_, &crypto_config_));
|
||||
if (initial_max_packet_length_ != 0) {
|
||||
session_->connection()->set_max_packet_length(initial_max_packet_length_);
|
||||
}
|
||||
session_->Initialize();
|
||||
session_->CryptoConnect();
|
||||
connected_or_attempting_connect_ = true;
|
||||
}
|
||||
CreateQuicClientSession(new QuicConnection(
|
||||
GetNextConnectionId(), server_address_, helper_.get(), factory,
|
||||
/* owns_writer= */ false, Perspective::IS_CLIENT, server_id().is_https(),
|
||||
supported_versions()));
|
||||
|
||||
bool QuicSimpleClient::EncryptionBeingEstablished() {
|
||||
return !session_->IsEncryptionEstablished() &&
|
||||
session_->connection()->connected();
|
||||
session()->Initialize();
|
||||
session()->CryptoConnect();
|
||||
set_connected_or_attempting_connect(true);
|
||||
}
|
||||
|
||||
void QuicSimpleClient::Disconnect() {
|
||||
@ -270,14 +228,14 @@ void QuicSimpleClient::Disconnect() {
|
||||
STLDeleteElements(&data_to_resend_on_connect_);
|
||||
STLDeleteElements(&data_sent_before_handshake_);
|
||||
|
||||
writer_.reset();
|
||||
reset_writer();
|
||||
packet_reader_.reset();
|
||||
|
||||
initialized_ = false;
|
||||
}
|
||||
|
||||
void QuicSimpleClient::SendRequest(const HttpRequestInfo& headers,
|
||||
base::StringPiece body,
|
||||
StringPiece body,
|
||||
bool fin) {
|
||||
QuicSpdyClientStream* stream = CreateReliableClientStream();
|
||||
if (stream == nullptr) {
|
||||
@ -304,7 +262,7 @@ void QuicSimpleClient::SendRequest(const HttpRequestInfo& headers,
|
||||
void QuicSimpleClient::MaybeAddQuicDataToResend(
|
||||
QuicDataToResend* data_to_resend) {
|
||||
DCHECK(FLAGS_enable_quic_stateless_reject_support);
|
||||
if (session_->IsCryptoHandshakeConfirmed()) {
|
||||
if (session()->IsCryptoHandshakeConfirmed()) {
|
||||
// The handshake is confirmed. No need to continue saving requests to
|
||||
// resend.
|
||||
STLDeleteElements(&data_sent_before_handshake_);
|
||||
@ -319,7 +277,7 @@ void QuicSimpleClient::MaybeAddQuicDataToResend(
|
||||
|
||||
void QuicSimpleClient::SendRequestAndWaitForResponse(
|
||||
const HttpRequestInfo& request,
|
||||
base::StringPiece body,
|
||||
StringPiece body,
|
||||
bool fin) {
|
||||
SendRequest(request, body, fin);
|
||||
while (WaitForEvents()) {}
|
||||
@ -337,45 +295,21 @@ void QuicSimpleClient::SendRequestsAndWaitForResponse(
|
||||
while (WaitForEvents()) {}
|
||||
}
|
||||
|
||||
QuicSpdyClientStream* QuicSimpleClient::CreateReliableClientStream() {
|
||||
if (!connected()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return session_->CreateOutgoingDynamicStream();
|
||||
}
|
||||
|
||||
void QuicSimpleClient::WaitForStreamToClose(QuicStreamId id) {
|
||||
DCHECK(connected());
|
||||
|
||||
while (connected() && !session_->IsClosedStream(id)) {
|
||||
WaitForEvents();
|
||||
}
|
||||
}
|
||||
|
||||
void QuicSimpleClient::WaitForCryptoHandshakeConfirmed() {
|
||||
DCHECK(connected());
|
||||
|
||||
while (connected() && !session_->IsCryptoHandshakeConfirmed()) {
|
||||
WaitForEvents();
|
||||
}
|
||||
}
|
||||
|
||||
bool QuicSimpleClient::WaitForEvents() {
|
||||
DCHECK(connected());
|
||||
|
||||
base::RunLoop().RunUntilIdle();
|
||||
|
||||
DCHECK(session_ != nullptr);
|
||||
DCHECK(session() != nullptr);
|
||||
if (!connected() &&
|
||||
session_->error() == QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT) {
|
||||
session()->error() == QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT) {
|
||||
DCHECK(FLAGS_enable_quic_stateless_reject_support);
|
||||
DVLOG(1) << "Detected stateless reject while waiting for events. "
|
||||
<< "Attempting to reconnect.";
|
||||
Connect();
|
||||
}
|
||||
|
||||
return session_->num_active_requests() != 0;
|
||||
return session()->num_active_requests() != 0;
|
||||
}
|
||||
|
||||
bool QuicSimpleClient::MigrateSocket(const IPAddressNumber& new_host) {
|
||||
@ -388,14 +322,12 @@ bool QuicSimpleClient::MigrateSocket(const IPAddressNumber& new_host) {
|
||||
return false;
|
||||
}
|
||||
|
||||
session_->connection()->SetSelfAddress(client_address_);
|
||||
session()->connection()->SetSelfAddress(client_address_);
|
||||
|
||||
QuicPacketWriter* writer = CreateQuicPacketWriter();
|
||||
DummyPacketWriterFactory factory(writer);
|
||||
if (writer_.get() != writer) {
|
||||
writer_.reset(writer);
|
||||
}
|
||||
session_->connection()->SetQuicPacketWriter(writer, false);
|
||||
set_writer(writer);
|
||||
session()->connection()->SetQuicPacketWriter(writer, false);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -421,15 +353,6 @@ void QuicSimpleClient::OnClose(QuicDataStream* stream) {
|
||||
}
|
||||
}
|
||||
|
||||
bool QuicSimpleClient::connected() const {
|
||||
return session_.get() && session_->connection() &&
|
||||
session_->connection()->connected();
|
||||
}
|
||||
|
||||
bool QuicSimpleClient::goaway_received() const {
|
||||
return session_ != nullptr && session_->goaway_received();
|
||||
}
|
||||
|
||||
size_t QuicSimpleClient::latest_response_code() const {
|
||||
LOG_IF(DFATAL, !store_response_) << "Response not stored!";
|
||||
return latest_response_code_;
|
||||
@ -445,45 +368,6 @@ const string& QuicSimpleClient::latest_response_body() const {
|
||||
return latest_response_body_;
|
||||
}
|
||||
|
||||
int QuicSimpleClient::GetNumSentClientHellos() {
|
||||
// If we are not actively attempting to connect, the session object
|
||||
// corresponds to the previous connection and should not be used.
|
||||
const int current_session_hellos = !connected_or_attempting_connect_
|
||||
? 0
|
||||
: session_->GetNumSentClientHellos();
|
||||
return num_sent_client_hellos_ + current_session_hellos;
|
||||
}
|
||||
|
||||
QuicErrorCode QuicSimpleClient::connection_error() const {
|
||||
// Return the high-level error if there was one. Otherwise, return the
|
||||
// connection error from the last session.
|
||||
if (connection_error_ != QUIC_NO_ERROR) {
|
||||
return connection_error_;
|
||||
}
|
||||
if (session_.get() == nullptr) {
|
||||
return QUIC_NO_ERROR;
|
||||
}
|
||||
return session_->error();
|
||||
}
|
||||
|
||||
QuicConnectionId QuicSimpleClient::GetNextConnectionId() {
|
||||
QuicConnectionId server_designated_id = GetNextServerDesignatedConnectionId();
|
||||
return server_designated_id ? server_designated_id
|
||||
: GenerateNewConnectionId();
|
||||
}
|
||||
|
||||
QuicConnectionId QuicSimpleClient::GetNextServerDesignatedConnectionId() {
|
||||
QuicCryptoClientConfig::CachedState* cached =
|
||||
crypto_config_.LookupOrCreate(server_id_);
|
||||
// If the cached state indicates that we should use a server-designated
|
||||
// connection ID, then return that connection ID.
|
||||
CHECK(cached != nullptr) << "QuicClientCryptoConfig::LookupOrCreate returned "
|
||||
<< "unexpected nullptr.";
|
||||
return cached->has_server_designated_connection_id()
|
||||
? cached->GetNextServerDesignatedConnectionId()
|
||||
: 0;
|
||||
}
|
||||
|
||||
QuicConnectionId QuicSimpleClient::GenerateNewConnectionId() {
|
||||
return helper_->GetRandomGenerator()->RandUint64();
|
||||
}
|
||||
@ -505,8 +389,9 @@ void QuicSimpleClient::OnReadError(int result) {
|
||||
bool QuicSimpleClient::OnPacket(const QuicEncryptedPacket& packet,
|
||||
IPEndPoint local_address,
|
||||
IPEndPoint peer_address) {
|
||||
session_->connection()->ProcessUdpPacket(local_address, peer_address, packet);
|
||||
if (!session_->connection()->connected()) {
|
||||
session()->connection()->ProcessUdpPacket(local_address, peer_address,
|
||||
packet);
|
||||
if (!session()->connection()->connected()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -14,23 +14,17 @@
|
||||
#include "base/command_line.h"
|
||||
#include "base/memory/scoped_ptr.h"
|
||||
#include "base/strings/string_piece.h"
|
||||
#include "net/base/io_buffer.h"
|
||||
#include "net/base/ip_endpoint.h"
|
||||
#include "net/http/http_response_headers.h"
|
||||
#include "net/log/net_log.h"
|
||||
#include "net/quic/crypto/crypto_handshake.h"
|
||||
#include "net/quic/quic_config.h"
|
||||
#include "net/quic/quic_framer.h"
|
||||
#include "net/quic/quic_packet_creator.h"
|
||||
#include "net/quic/quic_data_stream.h"
|
||||
#include "net/quic/quic_packet_reader.h"
|
||||
#include "net/tools/quic/quic_client_session.h"
|
||||
#include "net/tools/quic/quic_spdy_client_stream.h"
|
||||
#include "net/tools/quic/quic_client_base.h"
|
||||
|
||||
namespace net {
|
||||
|
||||
struct HttpRequestInfo;
|
||||
class ProofVerifier;
|
||||
class QuicServerId;
|
||||
class QuicConnectionHelper;
|
||||
class UDPClientSocket;
|
||||
|
||||
@ -40,7 +34,8 @@ namespace test {
|
||||
class QuicClientPeer;
|
||||
} // namespace test
|
||||
|
||||
class QuicSimpleClient : public QuicDataStream::Visitor,
|
||||
class QuicSimpleClient : public QuicClientBase,
|
||||
public QuicDataStream::Visitor,
|
||||
public QuicPacketReader::Visitor {
|
||||
public:
|
||||
class ResponseListener {
|
||||
@ -94,10 +89,10 @@ class QuicSimpleClient : public QuicDataStream::Visitor,
|
||||
|
||||
~QuicSimpleClient() override;
|
||||
|
||||
// Initializes the client to create a connection. Should be called exactly
|
||||
// once before calling StartConnect or Connect. Returns true if the
|
||||
// initialization succeeds, false otherwise.
|
||||
bool Initialize();
|
||||
// From QuicClientBase
|
||||
bool Initialize() override;
|
||||
bool WaitForEvents() override;
|
||||
QuicConnectionId GenerateNewConnectionId() override;
|
||||
|
||||
// "Connect" to the QUIC server, including performing synchronous crypto
|
||||
// handshake.
|
||||
@ -108,11 +103,6 @@ class QuicSimpleClient : public QuicDataStream::Visitor,
|
||||
// completes.
|
||||
void StartConnect();
|
||||
|
||||
// Returns true if the crypto handshake has yet to establish encryption.
|
||||
// Returns false if encryption is active (even if the server hasn't confirmed
|
||||
// the handshake) or if the connection has been closed.
|
||||
bool EncryptionBeingEstablished();
|
||||
|
||||
// Disconnects from the QUIC server.
|
||||
void Disconnect();
|
||||
|
||||
@ -131,20 +121,6 @@ class QuicSimpleClient : public QuicDataStream::Visitor,
|
||||
void SendRequestsAndWaitForResponse(
|
||||
const base::CommandLine::StringVector& url_list);
|
||||
|
||||
// Returns a newly created QuicSpdyClientStream, owned by the
|
||||
// QuicSimpleClient.
|
||||
QuicSpdyClientStream* CreateReliableClientStream();
|
||||
|
||||
// Wait for events until the stream with the given ID is closed.
|
||||
void WaitForStreamToClose(QuicStreamId id);
|
||||
|
||||
// Wait for events until the handshake is confirmed.
|
||||
void WaitForCryptoHandshakeConfirmed();
|
||||
|
||||
// Wait up to 50ms, and handle any events which occur.
|
||||
// Returns true if there are any outstanding requests.
|
||||
bool WaitForEvents();
|
||||
|
||||
// Migrate to a new socket during an active connection.
|
||||
bool MigrateSocket(const IPAddressNumber& new_host);
|
||||
|
||||
@ -162,11 +138,6 @@ class QuicSimpleClient : public QuicDataStream::Visitor,
|
||||
// Otherwise, deletes the data. Takes ownerership of |data_to_resend|.
|
||||
void MaybeAddQuicDataToResend(QuicDataToResend* data_to_resend);
|
||||
|
||||
QuicClientSession* session() { return session_.get(); }
|
||||
|
||||
bool connected() const;
|
||||
bool goaway_received() const;
|
||||
|
||||
void set_bind_to_address(IPAddressNumber address) {
|
||||
bind_to_address_ = address;
|
||||
}
|
||||
@ -179,111 +150,24 @@ class QuicSimpleClient : public QuicDataStream::Visitor,
|
||||
|
||||
const IPEndPoint& client_address() const { return client_address_; }
|
||||
|
||||
const QuicServerId& server_id() const { return server_id_; }
|
||||
|
||||
// This should only be set before the initial Connect()
|
||||
void set_server_id(const QuicServerId& server_id) {
|
||||
server_id_ = server_id;
|
||||
}
|
||||
|
||||
void SetUserAgentID(const std::string& user_agent_id) {
|
||||
crypto_config_.set_user_agent_id(user_agent_id);
|
||||
}
|
||||
|
||||
// SetProofVerifier sets the ProofVerifier that will be used to verify the
|
||||
// server's certificate and takes ownership of |verifier|.
|
||||
void SetProofVerifier(ProofVerifier* verifier) {
|
||||
// TODO(rtenneti): We should set ProofVerifier in QuicClientSession.
|
||||
crypto_config_.SetProofVerifier(verifier);
|
||||
}
|
||||
|
||||
// SetChannelIDSource sets a ChannelIDSource that will be called, when the
|
||||
// server supports channel IDs, to obtain a channel ID for signing a message
|
||||
// proving possession of the channel ID. This object takes ownership of
|
||||
// |source|.
|
||||
void SetChannelIDSource(ChannelIDSource* source) {
|
||||
crypto_config_.SetChannelIDSource(source);
|
||||
}
|
||||
|
||||
void SetSupportedVersions(const QuicVersionVector& versions) {
|
||||
supported_versions_ = versions;
|
||||
}
|
||||
|
||||
// Takes ownership of the listener.
|
||||
void set_response_listener(ResponseListener* listener) {
|
||||
response_listener_.reset(listener);
|
||||
}
|
||||
|
||||
QuicConfig* config() { return &config_; }
|
||||
|
||||
void set_store_response(bool val) { store_response_ = val; }
|
||||
|
||||
size_t latest_response_code() const;
|
||||
const std::string& latest_response_headers() const;
|
||||
const std::string& latest_response_body() const;
|
||||
|
||||
// Change the initial maximum packet size of the connection. Has to be called
|
||||
// before Connect()/StartConnect() in order to have any effect.
|
||||
void set_initial_max_packet_length(QuicByteCount initial_max_packet_length) {
|
||||
initial_max_packet_length_ = initial_max_packet_length;
|
||||
}
|
||||
|
||||
int num_stateless_rejects_received() const {
|
||||
return num_stateless_rejects_received_;
|
||||
}
|
||||
|
||||
// The number of client hellos sent, taking stateless rejects into
|
||||
// account. In the case of a stateless reject, the initial
|
||||
// connection object may be torn down and a new one created. The
|
||||
// user cannot rely upon the latest connection object to get the
|
||||
// total number of client hellos sent, and should use this function
|
||||
// instead.
|
||||
int GetNumSentClientHellos();
|
||||
|
||||
// Returns any errors that occurred at the connection-level (as
|
||||
// opposed to the session-level). When a stateless reject occurs,
|
||||
// the error of the last session may not reflect the overall state
|
||||
// of the connection.
|
||||
QuicErrorCode connection_error() const;
|
||||
|
||||
protected:
|
||||
// Generates the next ConnectionId for |server_id_|. By default, if the
|
||||
// cached server config contains a server-designated ID, that ID will be
|
||||
// returned. Otherwise, the next random ID will be returned.
|
||||
QuicConnectionId GetNextConnectionId();
|
||||
|
||||
// Returns the next server-designated ConnectionId from the cached config for
|
||||
// |server_id_|, if it exists. Otherwise, returns 0.
|
||||
QuicConnectionId GetNextServerDesignatedConnectionId();
|
||||
|
||||
// Generates a new, random connection ID (as opposed to a server-designated
|
||||
// connection ID).
|
||||
virtual QuicConnectionId GenerateNewConnectionId();
|
||||
|
||||
virtual QuicConnectionHelper* CreateQuicConnectionHelper();
|
||||
virtual QuicPacketWriter* CreateQuicPacketWriter();
|
||||
|
||||
virtual QuicClientSession* CreateQuicClientSession(
|
||||
const QuicConfig& config,
|
||||
QuicConnection* connection,
|
||||
const QuicServerId& server_id,
|
||||
QuicCryptoClientConfig* crypto_config);
|
||||
|
||||
private:
|
||||
friend class net::tools::test::QuicClientPeer;
|
||||
|
||||
// A packet writer factory that always returns the same writer
|
||||
class DummyPacketWriterFactory : public QuicConnection::PacketWriterFactory {
|
||||
public:
|
||||
DummyPacketWriterFactory(QuicPacketWriter* writer);
|
||||
~DummyPacketWriterFactory() override;
|
||||
|
||||
QuicPacketWriter* Create(QuicConnection* connection) const override;
|
||||
|
||||
private:
|
||||
QuicPacketWriter* writer_;
|
||||
};
|
||||
|
||||
// Specific QuicClient class for storing data to resend.
|
||||
class ClientQuicDataToResend : public QuicDataToResend {
|
||||
public:
|
||||
@ -322,14 +206,6 @@ class QuicSimpleClient : public QuicDataStream::Visitor,
|
||||
// Address of the server.
|
||||
const IPEndPoint server_address_;
|
||||
|
||||
// |server_id_| is a tuple (hostname, port, is_https) of the server.
|
||||
QuicServerId server_id_;
|
||||
|
||||
// config_ and crypto_config_ contain configuration and cached state about
|
||||
// servers.
|
||||
QuicConfig config_;
|
||||
QuicCryptoClientConfig crypto_config_;
|
||||
|
||||
// Address of the client if the client is connected to the server.
|
||||
IPEndPoint client_address_;
|
||||
|
||||
@ -338,19 +214,9 @@ class QuicSimpleClient : public QuicDataStream::Visitor,
|
||||
// Local port to bind to. Initialize to 0.
|
||||
int local_port_;
|
||||
|
||||
// Writer used to actually send packets to the wire. Needs to outlive
|
||||
// |session_|.
|
||||
scoped_ptr<QuicPacketWriter> writer_;
|
||||
|
||||
// Session which manages streams.
|
||||
scoped_ptr<QuicClientSession> session_;
|
||||
|
||||
// UDP socket connected to the server.
|
||||
scoped_ptr<UDPClientSocket> socket_;
|
||||
|
||||
// Connection on the socket. Owned by |session_|.
|
||||
QuicConnection* connection_;
|
||||
|
||||
// Helper to be used by created connections.
|
||||
scoped_ptr<QuicConnectionHelper> helper_;
|
||||
|
||||
@ -368,13 +234,6 @@ class QuicSimpleClient : public QuicDataStream::Visitor,
|
||||
// because the socket would otherwise overflow.
|
||||
bool overflow_supported_;
|
||||
|
||||
// This vector contains QUIC versions which we currently support.
|
||||
// This should be ordered such that the highest supported version is the first
|
||||
// element, with subsequent elements in descending order (versions can be
|
||||
// skipped as necessary). We will always pick supported_versions_[0] as the
|
||||
// initial version to use.
|
||||
QuicVersionVector supported_versions_;
|
||||
|
||||
// If true, store the latest response code, headers, and body.
|
||||
bool store_response_;
|
||||
// HTTP response code from most recent response.
|
||||
@ -384,31 +243,6 @@ class QuicSimpleClient : public QuicDataStream::Visitor,
|
||||
// Body of most recent response.
|
||||
std::string latest_response_body_;
|
||||
|
||||
// The initial value of maximum packet size of the connection. If set to
|
||||
// zero, the default is used.
|
||||
QuicByteCount initial_max_packet_length_;
|
||||
|
||||
// The number of stateless rejects received during the current/latest
|
||||
// connection.
|
||||
// TODO(jokulik): Consider some consistent naming scheme (or other) for member
|
||||
// variables that are kept per-request, per-connection, and over the client's
|
||||
// lifetime.
|
||||
int num_stateless_rejects_received_;
|
||||
|
||||
// The number of hellos sent during the current/latest connection.
|
||||
int num_sent_client_hellos_;
|
||||
|
||||
// Used to store any errors that occurred with the overall connection (as
|
||||
// opposed to that associated with the last session object).
|
||||
QuicErrorCode connection_error_;
|
||||
|
||||
// True when the client is attempting to connect or re-connect the session (in
|
||||
// the case of a stateless reject). Set to false between a call to
|
||||
// Disconnect() and the subsequent call to StartConnect(). When
|
||||
// connected_or_attempting_connect_ is false, the session object corresponds
|
||||
// to the previous client-level connection.
|
||||
bool connected_or_attempting_connect_;
|
||||
|
||||
// Keeps track of any data sent before the handshake.
|
||||
std::vector<QuicDataToResend*> data_sent_before_handshake_;
|
||||
|
||||
|
@ -10,11 +10,6 @@ namespace net {
|
||||
namespace tools {
|
||||
namespace test {
|
||||
|
||||
// static
|
||||
QuicCryptoClientConfig* QuicClientPeer::GetCryptoConfig(QuicClient* client) {
|
||||
return &client->crypto_config_;
|
||||
}
|
||||
|
||||
// static
|
||||
bool QuicClientPeer::CreateUDPSocket(QuicClient* client) {
|
||||
return client->CreateUDPSocket();
|
||||
@ -25,11 +20,6 @@ void QuicClientPeer::SetClientPort(QuicClient* client, int port) {
|
||||
client->client_address_ = IPEndPoint(client->client_address_.address(), port);
|
||||
}
|
||||
|
||||
// static
|
||||
void QuicClientPeer::SetWriter(QuicClient* client, QuicPacketWriter* writer) {
|
||||
client->writer_.reset(writer);
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
} // namespace tools
|
||||
} // namespace net
|
||||
|
@ -20,10 +20,8 @@ namespace test {
|
||||
|
||||
class QuicClientPeer {
|
||||
public:
|
||||
static QuicCryptoClientConfig* GetCryptoConfig(QuicClient* client);
|
||||
static bool CreateUDPSocket(QuicClient* client);
|
||||
static void SetClientPort(QuicClient* client, int port);
|
||||
static void SetWriter(QuicClient* client, QuicPacketWriter* writer);
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(QuicClientPeer);
|
||||
|
@ -410,8 +410,7 @@ const string& QuicTestClient::cert_common_name() const {
|
||||
}
|
||||
|
||||
QuicTagValueMap QuicTestClient::GetServerConfig() const {
|
||||
QuicCryptoClientConfig* config =
|
||||
QuicClientPeer::GetCryptoConfig(client_.get());
|
||||
QuicCryptoClientConfig* config = client_->crypto_config();
|
||||
QuicCryptoClientConfig::CachedState* state =
|
||||
config->LookupOrCreate(client_->server_id());
|
||||
const CryptoHandshakeMessage* handshake_msg = state->GetServerConfig();
|
||||
|
Reference in New Issue
Block a user