Commit dfcc7d6b authored by rch's avatar rch Committed by Commit bot

Move QuicClient::ClientQuicDataToResend from QuicClient to QuicClientBase.

Merge internal change: 134339524

Review-Url: https://codereview.chromium.org/2368183003
Cr-Commit-Position: refs/heads/master@{#421289}
parent 950c3c1b
......@@ -44,11 +44,6 @@ namespace net {
const int kEpollFlags = EPOLLIN | EPOLLOUT | EPOLLET;
void QuicClient::ClientQuicDataToResend::Resend() {
client_->SendRequest(*headers_, body_, fin_);
headers_ = nullptr;
}
QuicClient::QuicClient(IPEndPoint server_address,
const QuicServerId& server_id,
const QuicVersionVector& supported_versions,
......@@ -174,15 +169,9 @@ bool QuicClient::Connect() {
while (EncryptionBeingEstablished()) {
WaitForEvents();
}
if (FLAGS_enable_quic_stateless_reject_support && connected() &&
!data_to_resend_on_connect_.empty()) {
// A connection has been established and there was previously queued data
// to resend. Resend it and empty the queue.
std::vector<std::unique_ptr<QuicDataToResend>> old_data;
old_data.swap(data_to_resend_on_connect_);
for (const auto& data : old_data) {
data->Resend();
}
if (FLAGS_enable_quic_stateless_reject_support && connected()) {
// Resend any previously queued data.
ResendSavedData();
}
if (session() != nullptr &&
session()->error() != QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT) {
......@@ -211,7 +200,7 @@ void QuicClient::StartConnect() {
// If the last error was not a stateless reject, then the queued up data
// does not need to be resent.
if (session()->error() != QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT) {
data_to_resend_on_connect_.clear();
ClearDataToResend();
}
// Before we destroy the last session and create a new one, gather its stats
// and update the stats for the overall connection.
......@@ -239,7 +228,7 @@ void QuicClient::Disconnect() {
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
}
data_to_resend_on_connect_.clear();
ClearDataToResend();
CleanUpAllUDPSockets();
......@@ -276,10 +265,7 @@ void QuicClient::SendRequest(const SpdyHeaderBlock& headers,
if (rv == QUIC_PENDING) {
// May need to retry request if asynchronous rendezvous fails.
std::unique_ptr<SpdyHeaderBlock> new_headers(
new SpdyHeaderBlock(headers.Clone()));
push_promise_data_to_resend_.reset(
new ClientQuicDataToResend(std::move(new_headers), body, fin, this));
AddPromiseDataToResend(headers, body, fin);
return;
}
......@@ -289,29 +275,8 @@ void QuicClient::SendRequest(const SpdyHeaderBlock& headers,
return;
}
stream->SendRequest(headers.Clone(), body, fin);
if (FLAGS_enable_quic_stateless_reject_support) {
// Record this in case we need to resend.
std::unique_ptr<SpdyHeaderBlock> new_headers(
new SpdyHeaderBlock(headers.Clone()));
auto data_to_resend =
new ClientQuicDataToResend(std::move(new_headers), body, fin, this);
MaybeAddQuicDataToResend(std::unique_ptr<QuicDataToResend>(data_to_resend));
}
}
void QuicClient::MaybeAddQuicDataToResend(
std::unique_ptr<QuicDataToResend> data_to_resend) {
DCHECK(FLAGS_enable_quic_stateless_reject_support);
if (session()->IsCryptoHandshakeConfirmed()) {
// The handshake is confirmed. No need to continue saving requests to
// resend.
data_to_resend_on_connect_.clear();
return;
}
// The handshake is not confirmed. Push the data onto the queue of data to
// resend if statelessly rejected.
data_to_resend_on_connect_.push_back(std::move(data_to_resend));
// Record this in case we need to resend.
MaybeAddDataToResend(headers, body, fin);
}
void QuicClient::SendRequestAndWaitForResponse(const SpdyHeaderBlock& headers,
......@@ -431,23 +396,6 @@ void QuicClient::OnClose(QuicSpdyStream* stream) {
}
}
bool QuicClient::CheckVary(const SpdyHeaderBlock& client_request,
const SpdyHeaderBlock& promise_request,
const SpdyHeaderBlock& promise_response) {
return true;
}
void QuicClient::OnRendezvousResult(QuicSpdyStream* stream) {
std::unique_ptr<ClientQuicDataToResend> data_to_resend =
std::move(push_promise_data_to_resend_);
if (stream) {
stream->set_visitor(this);
stream->OnDataAvailable();
} else if (data_to_resend.get()) {
data_to_resend->Resend();
}
}
size_t QuicClient::latest_response_code() const {
QUIC_BUG_IF(!store_response_) << "Response not stored!";
return latest_response_code_;
......
......@@ -38,9 +38,7 @@ class QuicClientPeer;
class QuicClient : public QuicClientBase,
public EpollCallbackInterface,
public QuicSpdyStream::Visitor,
public ProcessPacketInterface,
public QuicClientPushPromiseIndex::Delegate {
public ProcessPacketInterface {
public:
class ResponseListener {
public:
......@@ -87,7 +85,7 @@ class QuicClient : public QuicClientBase,
// Sends an HTTP request and does not wait for response before returning.
void SendRequest(const SpdyHeaderBlock& headers,
base::StringPiece body,
bool fin);
bool fin) override;
// Sends an HTTP request and waits for response before returning.
void SendRequestAndWaitForResponse(const SpdyHeaderBlock& headers,
......@@ -114,17 +112,6 @@ class QuicClient : public QuicClientBase,
// QuicSpdyStream::Visitor
void OnClose(QuicSpdyStream* stream) override;
bool CheckVary(const SpdyHeaderBlock& client_request,
const SpdyHeaderBlock& promise_request,
const SpdyHeaderBlock& promise_response) override;
void OnRendezvousResult(QuicSpdyStream*) override;
// If the crypto handshake has not yet been confirmed, adds the data to the
// queue of data to resend if the client receives a stateless reject.
// Otherwise, deletes the data.
void MaybeAddQuicDataToResend(
std::unique_ptr<QuicDataToResend> data_to_resend);
// If the client has at least one UDP socket, return address of the latest
// created one. Otherwise, return an empty socket address.
const IPEndPoint GetLatestClientAddress() const;
......@@ -185,28 +172,6 @@ class QuicClient : public QuicClientBase,
private:
friend class net::test::QuicClientPeer;
// Specific QuicClient class for storing data to resend.
class ClientQuicDataToResend : public QuicDataToResend {
public:
ClientQuicDataToResend(std::unique_ptr<SpdyHeaderBlock> headers,
base::StringPiece body,
bool fin,
QuicClient* client)
: QuicDataToResend(std::move(headers), body, fin), client_(client) {
DCHECK(headers_);
DCHECK(client);
}
~ClientQuicDataToResend() override {}
void Resend() override;
private:
QuicClient* client_;
DISALLOW_COPY_AND_ASSIGN(ClientQuicDataToResend);
};
// Used during initialization: creates the UDP socket FD, sets socket options,
// and binds the socket to our address.
bool CreateUDPSocketAndBind();
......@@ -257,10 +222,6 @@ class QuicClient : public QuicClientBase,
// HTTP/2 trailers from most recent response.
std::string latest_response_trailers_;
// Keeps track of any data that must be resent upon a subsequent successful
// connection, in case the client receives a stateless reject.
std::vector<std::unique_ptr<QuicDataToResend>> data_to_resend_on_connect_;
// Point to a QuicPacketReader object on the heap. The reader allocates more
// space than allowed on the stack.
//
......@@ -268,8 +229,6 @@ class QuicClient : public QuicClientBase,
// QuicPacketReader
std::unique_ptr<QuicPacketReader> packet_reader_;
std::unique_ptr<ClientQuicDataToResend> push_promise_data_to_resend_;
DISALLOW_COPY_AND_ASSIGN(QuicClient);
};
......
......@@ -11,6 +11,11 @@ using base::StringPiece;
namespace net {
void QuicClientBase::ClientQuicDataToResend::Resend() {
client_->SendRequest(*headers_, body_, fin_);
headers_ = nullptr;
}
QuicClientBase::QuicDataToResend::QuicDataToResend(
std::unique_ptr<SpdyHeaderBlock> headers,
StringPiece body,
......@@ -160,4 +165,69 @@ QuicConnectionId QuicClientBase::GenerateNewConnectionId() {
return QuicRandom::GetInstance()->RandUint64();
}
void QuicClientBase::MaybeAddDataToResend(const SpdyHeaderBlock& headers,
StringPiece body,
bool fin) {
if (!FLAGS_enable_quic_stateless_reject_support) {
return;
}
if (session()->IsCryptoHandshakeConfirmed()) {
// The handshake is confirmed. No need to continue saving requests to
// resend.
data_to_resend_on_connect_.clear();
return;
}
// The handshake is not confirmed. Push the data onto the queue of data to
// resend if statelessly rejected.
std::unique_ptr<SpdyHeaderBlock> new_headers(
new SpdyHeaderBlock(headers.Clone()));
std::unique_ptr<QuicDataToResend> data_to_resend(
new ClientQuicDataToResend(std::move(new_headers), body, fin, this));
MaybeAddQuicDataToResend(std::move(data_to_resend));
}
void QuicClientBase::MaybeAddQuicDataToResend(
std::unique_ptr<QuicDataToResend> data_to_resend) {
data_to_resend_on_connect_.push_back(std::move(data_to_resend));
}
void QuicClientBase::ClearDataToResend() {
data_to_resend_on_connect_.clear();
}
void QuicClientBase::ResendSavedData() {
for (const auto& data : data_to_resend_on_connect_) {
data->Resend();
}
data_to_resend_on_connect_.clear();
}
void QuicClientBase::AddPromiseDataToResend(const SpdyHeaderBlock& headers,
StringPiece body,
bool fin) {
std::unique_ptr<SpdyHeaderBlock> new_headers(
new SpdyHeaderBlock(headers.Clone()));
push_promise_data_to_resend_.reset(
new ClientQuicDataToResend(std::move(new_headers), body, fin, this));
}
bool QuicClientBase::CheckVary(const SpdyHeaderBlock& client_request,
const SpdyHeaderBlock& promise_request,
const SpdyHeaderBlock& promise_response) {
return true;
}
void QuicClientBase::OnRendezvousResult(QuicSpdyStream* stream) {
std::unique_ptr<ClientQuicDataToResend> data_to_resend =
std::move(push_promise_data_to_resend_);
if (stream) {
stream->set_visitor(this);
stream->OnDataAvailable();
} else if (data_to_resend.get()) {
data_to_resend->Resend();
}
}
} // namespace net
......@@ -31,7 +31,8 @@ namespace net {
class ProofVerifier;
class QuicServerId;
class QuicClientBase {
class QuicClientBase : public QuicClientPushPromiseIndex::Delegate,
public QuicSpdyStream::Visitor {
public:
// 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
......@@ -69,7 +70,7 @@ class QuicClientBase {
QuicAlarmFactory* alarm_factory,
std::unique_ptr<ProofVerifier> proof_verifier);
~QuicClientBase();
~QuicClientBase() override;
// Initializes the client to create a connection. Should be called exactly
// once before calling StartConnect or Connect. Returns true if the
......@@ -91,6 +92,11 @@ class QuicClientBase {
// Wait for events until the handshake is confirmed.
void WaitForCryptoHandshakeConfirmed();
// Sends an HTTP request and does not wait for response before returning.
virtual void SendRequest(const SpdyHeaderBlock& headers,
base::StringPiece body,
bool fin) = 0;
// Wait up to 50ms, and handle any events which occur.
// Returns true if there are any outstanding requests.
virtual bool WaitForEvents() = 0;
......@@ -204,6 +210,17 @@ class QuicClientBase {
return &push_promise_index_;
}
bool CheckVary(const SpdyHeaderBlock& client_request,
const SpdyHeaderBlock& promise_request,
const SpdyHeaderBlock& promise_response) override;
void OnRendezvousResult(QuicSpdyStream*) override;
// If the crypto handshake has not yet been confirmed, adds the data to the
// queue of data to resend if the client receives a stateless reject.
// Otherwise, deletes the data.
void MaybeAddQuicDataToResend(
std::unique_ptr<QuicDataToResend> data_to_resend);
protected:
// Takes ownership of |connection|.
virtual QuicClientSession* CreateQuicClientSession(
......@@ -222,6 +239,21 @@ class QuicClientBase {
// connection ID).
virtual QuicConnectionId GenerateNewConnectionId();
// If the crypto handshake has not yet been confirmed, adds the data to the
// queue of data to resend if the client receives a stateless reject.
// Otherwise, deletes the data.
void MaybeAddDataToResend(const SpdyHeaderBlock& headers,
base::StringPiece body,
bool fin);
void ClearDataToResend();
void ResendSavedData();
void AddPromiseDataToResend(const SpdyHeaderBlock& headers,
base::StringPiece body,
bool fin);
QuicConnectionHelperInterface* helper() { return helper_.get(); }
QuicAlarmFactory* alarm_factory() { return alarm_factory_.get(); }
......@@ -235,6 +267,28 @@ class QuicClientBase {
}
private:
// Specific QuicClient class for storing data to resend.
class ClientQuicDataToResend : public QuicDataToResend {
public:
ClientQuicDataToResend(std::unique_ptr<SpdyHeaderBlock> headers,
base::StringPiece body,
bool fin,
QuicClientBase* client)
: QuicDataToResend(std::move(headers), body, fin), client_(client) {
DCHECK(headers_);
DCHECK(client);
}
~ClientQuicDataToResend() override {}
void Resend() override;
private:
QuicClientBase* client_;
DISALLOW_COPY_AND_ASSIGN(ClientQuicDataToResend);
};
// |server_id_| is a tuple (hostname, port, is_https) of the server.
QuicServerId server_id_;
......@@ -290,6 +344,12 @@ class QuicClientBase {
QuicClientPushPromiseIndex push_promise_index_;
// Keeps track of any data that must be resent upon a subsequent successful
// connection, in case the client receives a stateless reject.
std::vector<std::unique_ptr<QuicDataToResend>> data_to_resend_on_connect_;
std::unique_ptr<ClientQuicDataToResend> push_promise_data_to_resend_;
DISALLOW_COPY_AND_ASSIGN(QuicClientBase);
};
......
......@@ -32,11 +32,6 @@ using base::StringPiece;
namespace net {
void QuicSimpleClient::ClientQuicDataToResend::Resend() {
client_->SendRequest(*headers_, body_, fin_);
headers_ = nullptr;
}
QuicSimpleClient::QuicSimpleClient(
IPEndPoint server_address,
const QuicServerId& server_id,
......@@ -161,16 +156,9 @@ bool QuicSimpleClient::Connect() {
while (EncryptionBeingEstablished()) {
WaitForEvents();
}
if (FLAGS_enable_quic_stateless_reject_support && connected() &&
!data_to_resend_on_connect_.empty()) {
// A connection has been established and there was previously queued data
// to resend. Resend it and empty the queue.
std::vector<std::unique_ptr<QuicDataToResend>> old_data;
old_data.swap(data_to_resend_on_connect_);
for (const auto& data : old_data) {
data->Resend();
}
data_to_resend_on_connect_.clear();
if (FLAGS_enable_quic_stateless_reject_support && connected()) {
// Resend any previously queued data.
ResendSavedData();
}
if (session() != nullptr &&
session()->error() != QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT) {
......@@ -199,7 +187,7 @@ void QuicSimpleClient::StartConnect() {
// If the last error was not a stateless reject, then the queued up data
// does not need to be resent.
if (session()->error() != QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT) {
data_to_resend_on_connect_.clear();
ClearDataToResend();
}
// Before we destroy the last session and create a new one, gather its stats
// and update the stats for the overall connection.
......@@ -224,7 +212,7 @@ void QuicSimpleClient::Disconnect() {
QUIC_PEER_GOING_AWAY, "Client disconnecting",
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
}
data_to_resend_on_connect_.clear();
ClearDataToResend();
reset_writer();
packet_reader_.reset();
......@@ -236,36 +224,26 @@ void QuicSimpleClient::Disconnect() {
void QuicSimpleClient::SendRequest(const SpdyHeaderBlock& headers,
StringPiece body,
bool fin) {
QuicClientPushPromiseIndex::TryHandle* handle;
QuicAsyncStatus rv = push_promise_index()->Try(headers, this, &handle);
if (rv == QUIC_SUCCESS)
return;
if (rv == QUIC_PENDING) {
// May need to retry request if asynchronous rendezvous fails.
AddPromiseDataToResend(headers, body, fin);
return;
}
QuicSpdyClientStream* stream = CreateReliableClientStream();
if (stream == nullptr) {
LOG(DFATAL) << "stream creation failed!";
QUIC_BUG << "stream creation failed!";
return;
}
stream->set_visitor(this);
stream->SendRequest(headers.Clone(), body, fin);
if (FLAGS_enable_quic_stateless_reject_support) {
// Record this in case we need to resend.
std::unique_ptr<SpdyHeaderBlock> new_headers(
new SpdyHeaderBlock(headers.Clone()));
auto data_to_resend =
new ClientQuicDataToResend(std::move(new_headers), body, fin, this);
MaybeAddQuicDataToResend(std::unique_ptr<QuicDataToResend>(data_to_resend));
}
}
void QuicSimpleClient::MaybeAddQuicDataToResend(
std::unique_ptr<QuicDataToResend> data_to_resend) {
DCHECK(FLAGS_enable_quic_stateless_reject_support);
if (session()->IsCryptoHandshakeConfirmed()) {
// The handshake is confirmed. No need to continue saving requests to
// resend.
data_to_resend_on_connect_.clear();
return;
}
// The handshake is not confirmed. Push the data onto the queue of data to
// resend if statelessly rejected.
data_to_resend_on_connect_.push_back(std::move(data_to_resend));
// Record this in case we need to resend.
MaybeAddDataToResend(headers, body, fin);
}
void QuicSimpleClient::SendRequestAndWaitForResponse(
......
......@@ -38,7 +38,6 @@ class QuicClientPeer;
} // namespace test
class QuicSimpleClient : public QuicClientBase,
public QuicSpdyStream::Visitor,
public QuicChromiumPacketReader::Visitor {
public:
class ResponseListener {
......@@ -84,7 +83,7 @@ class QuicSimpleClient : public QuicClientBase,
// Sends an HTTP request and does not wait for response before returning.
void SendRequest(const SpdyHeaderBlock& headers,
base::StringPiece body,
bool fin);
bool fin) override;
// Sends an HTTP request and waits for response before returning.
void SendRequestAndWaitForResponse(const SpdyHeaderBlock& headers,
......@@ -108,12 +107,6 @@ class QuicSimpleClient : public QuicClientBase,
// QuicSpdyStream::Visitor
void OnClose(QuicSpdyStream* stream) override;
// If the crypto handshake has not yet been confirmed, adds the data to the
// queue of data to resend if the client receives a stateless reject.
// Otherwise, deletes the data.
void MaybeAddQuicDataToResend(
std::unique_ptr<QuicDataToResend> data_to_resend);
void set_bind_to_address(const IPAddress& address) {
bind_to_address_ = address;
}
......@@ -145,28 +138,6 @@ class QuicSimpleClient : public QuicClientBase,
private:
friend class net::test::QuicClientPeer;
// Specific QuicClient class for storing data to resend.
class ClientQuicDataToResend : public QuicDataToResend {
public:
// Takes ownership of |headers|.
ClientQuicDataToResend(std::unique_ptr<SpdyHeaderBlock> headers,
base::StringPiece body,
bool fin,
QuicSimpleClient* client)
: QuicDataToResend(std::move(headers), body, fin), client_(client) {
DCHECK(client);
}
~ClientQuicDataToResend() override {}
void Resend() override;
private:
QuicSimpleClient* client_;
DISALLOW_COPY_AND_ASSIGN(ClientQuicDataToResend);
};
// Used during initialization: creates the UDP socket FD, sets socket options,
// and binds the socket to our address.
bool CreateUDPSocket();
......@@ -217,10 +188,6 @@ class QuicSimpleClient : public QuicClientBase,
// Body of most recent response.
std::string latest_response_body_;
// Keeps track of any data that must be resent upon a subsequent successful
// connection, in case the client receives a stateless reject.
std::vector<std::unique_ptr<QuicDataToResend>> data_to_resend_on_connect_;
// The log used for the sockets.
NetLog net_log_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment