Index: net/tools/quic/quic_client_base.cc |
diff --git a/net/tools/quic/quic_client_base.cc b/net/tools/quic/quic_client_base.cc |
index 80b12df80f913d9a70047c19efd82cc2d4ebadd7..23a09b4f201fd60bbdcb1ed77f7b6a47a9d7e4a9 100644 |
--- a/net/tools/quic/quic_client_base.cc |
+++ b/net/tools/quic/quic_client_base.cc |
@@ -4,10 +4,13 @@ |
#include "net/tools/quic/quic_client_base.h" |
+#include "base/strings/string_number_conversions.h" |
#include "net/quic/core/crypto/quic_random.h" |
#include "net/quic/core/quic_server_id.h" |
using base::StringPiece; |
+using base::StringToInt; |
+using std::string; |
namespace net { |
@@ -31,6 +34,7 @@ QuicClientBase::QuicClientBase(const QuicServerId& server_id, |
QuicAlarmFactory* alarm_factory, |
std::unique_ptr<ProofVerifier> proof_verifier) |
: server_id_(server_id), |
+ local_port_(0), |
config_(config), |
crypto_config_(std::move(proof_verifier)), |
helper_(helper), |
@@ -40,10 +44,37 @@ QuicClientBase::QuicClientBase(const QuicServerId& server_id, |
num_stateless_rejects_received_(0), |
num_sent_client_hellos_(0), |
connection_error_(QUIC_NO_ERROR), |
- connected_or_attempting_connect_(false) {} |
+ connected_or_attempting_connect_(false), |
+ store_response_(false), |
+ latest_response_code_(-1) {} |
QuicClientBase::~QuicClientBase() {} |
+void QuicClientBase::OnClose(QuicSpdyStream* stream) { |
+ DCHECK(stream != nullptr); |
+ QuicSpdyClientStream* client_stream = |
+ static_cast<QuicSpdyClientStream*>(stream); |
+ |
+ const SpdyHeaderBlock& response_headers = client_stream->response_headers(); |
+ if (response_listener_ != nullptr) { |
+ response_listener_->OnCompleteResponse(stream->id(), response_headers, |
+ client_stream->data()); |
+ } |
+ |
+ // Store response headers and body. |
+ if (store_response_) { |
+ auto status = response_headers.find(":status"); |
+ if (status == response_headers.end() || |
+ !StringToInt(status->second, &latest_response_code_)) { |
+ LOG(ERROR) << "Invalid response headers"; |
+ } |
+ latest_response_headers_ = response_headers.DebugString(); |
+ latest_response_body_ = client_stream->data(); |
+ latest_response_trailers_ = |
+ client_stream->received_trailers().DebugString(); |
+ } |
+} |
+ |
bool QuicClientBase::Initialize() { |
num_sent_client_hellos_ = 0; |
num_stateless_rejects_received_ = 0; |
@@ -76,7 +107,12 @@ QuicSpdyClientStream* QuicClientBase::CreateReliableClientStream() { |
return nullptr; |
} |
- return session_->CreateOutgoingDynamicStream(kDefaultPriority); |
+ QuicSpdyClientStream* stream = |
+ session_->CreateOutgoingDynamicStream(kDefaultPriority); |
+ if (stream) { |
+ stream->set_visitor(this); |
+ } |
+ return stream; |
} |
void QuicClientBase::WaitForStreamToClose(QuicStreamId id) { |
@@ -198,7 +234,11 @@ void QuicClientBase::ClearDataToResend() { |
} |
void QuicClientBase::ResendSavedData() { |
- for (const auto& data : data_to_resend_on_connect_) { |
+ // Calling Resend will re-enqueue the data, so swap out |
+ // data_to_resend_on_connect_ before iterating. |
+ 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(); |
@@ -230,4 +270,29 @@ void QuicClientBase::OnRendezvousResult(QuicSpdyStream* stream) { |
} |
} |
+size_t QuicClientBase::latest_response_code() const { |
+ QUIC_BUG_IF(!store_response_) << "Response not stored!"; |
+ return latest_response_code_; |
+} |
+ |
+const string& QuicClientBase::latest_response_headers() const { |
+ QUIC_BUG_IF(!store_response_) << "Response not stored!"; |
+ return latest_response_headers_; |
+} |
+ |
+const SpdyHeaderBlock& QuicClientBase::latest_response_header_block() const { |
+ QUIC_BUG_IF(!store_response_) << "Response not stored!"; |
+ return latest_response_header_block_; |
+} |
+ |
+const string& QuicClientBase::latest_response_body() const { |
+ QUIC_BUG_IF(!store_response_) << "Response not stored!"; |
+ return latest_response_body_; |
+} |
+ |
+const string& QuicClientBase::latest_response_trailers() const { |
+ QUIC_BUG_IF(!store_response_) << "Response not stored!"; |
+ return latest_response_trailers_; |
+} |
+ |
} // namespace net |