Commit 40fa1747 authored by rch's avatar rch Committed by Commit bot

Remove Balsa from QuicSpdyClientStream.

To facilitate landing actual QuicServer support in Chromium using
Chromium's MessageLoop and friends.

Merge internal change: 89526581

Review URL: https://codereview.chromium.org/1006193003

Cr-Commit-Position: refs/heads/master@{#322246}
parent c325afc5
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "net/tools/quic/quic_epoll_connection_helper.h" #include "net/tools/quic/quic_epoll_connection_helper.h"
#include "net/tools/quic/quic_socket_utils.h" #include "net/tools/quic/quic_socket_utils.h"
#include "net/tools/quic/quic_spdy_client_stream.h" #include "net/tools/quic/quic_spdy_client_stream.h"
#include "net/tools/quic/spdy_utils.h"
#ifndef SO_RXQ_OVFL #ifndef SO_RXQ_OVFL
#define SO_RXQ_OVFL 40 #define SO_RXQ_OVFL 40
...@@ -249,7 +250,8 @@ void QuicClient::SendRequest(const BalsaHeaders& headers, ...@@ -249,7 +250,8 @@ void QuicClient::SendRequest(const BalsaHeaders& headers,
LOG(DFATAL) << "stream creation failed!"; LOG(DFATAL) << "stream creation failed!";
return; return;
} }
stream->SendRequest(headers, body, fin); stream->SendRequest(
SpdyUtils::RequestHeadersToSpdyHeaders(headers), body, fin);
stream->set_visitor(this); stream->set_visitor(this);
} }
...@@ -321,15 +323,18 @@ void QuicClient::OnEvent(int fd, EpollEvent* event) { ...@@ -321,15 +323,18 @@ void QuicClient::OnEvent(int fd, EpollEvent* event) {
void QuicClient::OnClose(QuicDataStream* stream) { void QuicClient::OnClose(QuicDataStream* stream) {
QuicSpdyClientStream* client_stream = QuicSpdyClientStream* client_stream =
static_cast<QuicSpdyClientStream*>(stream); static_cast<QuicSpdyClientStream*>(stream);
BalsaHeaders headers;
SpdyUtils::FillBalsaResponseHeaders(client_stream->headers(), &headers);
if (response_listener_.get() != nullptr) { if (response_listener_.get() != nullptr) {
response_listener_->OnCompleteResponse( response_listener_->OnCompleteResponse(
stream->id(), client_stream->headers(), client_stream->data()); stream->id(), headers, client_stream->data());
} }
// Store response headers and body. // Store response headers and body.
if (store_response_) { if (store_response_) {
latest_response_code_ = client_stream->headers().parsed_response_code(); latest_response_code_ = headers.parsed_response_code();
client_stream->headers().DumpHeadersToString(&latest_response_headers_); headers.DumpHeadersToString(&latest_response_headers_);
latest_response_body_ = client_stream->data(); latest_response_body_ = client_stream->data();
} }
} }
......
...@@ -4,23 +4,26 @@ ...@@ -4,23 +4,26 @@
#include "net/tools/quic/quic_spdy_client_stream.h" #include "net/tools/quic/quic_spdy_client_stream.h"
#include "net/spdy/spdy_framer.h" #include "base/logging.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "net/quic/spdy_utils.h"
#include "net/spdy/spdy_protocol.h"
#include "net/tools/quic/quic_client_session.h" #include "net/tools/quic/quic_client_session.h"
#include "net/tools/quic/spdy_utils.h" #include "net/tools/quic/spdy_utils.h"
using base::StringPiece; using base::StringPiece;
using std::string; using std::string;
using base::StringToInt;
namespace net { namespace net {
namespace tools { namespace tools {
static const size_t kHeaderBufInitialSize = 4096;
QuicSpdyClientStream::QuicSpdyClientStream(QuicStreamId id, QuicSpdyClientStream::QuicSpdyClientStream(QuicStreamId id,
QuicClientSession* session) QuicClientSession* session)
: QuicDataStream(id, session), : QuicDataStream(id, session),
read_buf_(new GrowableIOBuffer()), content_length_(-1),
response_headers_received_(false), response_code_(0),
header_bytes_read_(0), header_bytes_read_(0),
header_bytes_written_(0) { header_bytes_written_(0) {
} }
...@@ -43,47 +46,67 @@ void QuicSpdyClientStream::OnStreamHeadersComplete(bool fin, ...@@ -43,47 +46,67 @@ void QuicSpdyClientStream::OnStreamHeadersComplete(bool fin,
QuicDataStream::OnStreamHeadersComplete(fin, frame_len); QuicDataStream::OnStreamHeadersComplete(fin, frame_len);
} }
uint32 QuicSpdyClientStream::ProcessData(const char* data, uint32 QuicSpdyClientStream::ProcessData(const char* data, uint32 data_len) {
uint32 data_len) { if (!headers_decompressed()) {
int total_bytes_processed = 0; // Let the headers data accumulate in the underlying QuicDataStream.
return 0;
// Are we still reading the response headers. }
if (!response_headers_received_) { if (response_headers_.empty()) {
// Grow the read buffer if necessary. if (!ParseResponseHeaders(data, data_len)) {
if (read_buf_->RemainingCapacity() < (int)data_len) { // Headers were invalid.
read_buf_->SetCapacity(read_buf_->capacity() + kHeaderBufInitialSize); Reset(QUIC_BAD_APPLICATION_PAYLOAD);
return 0;
} }
memcpy(read_buf_->data(), data, data_len);
read_buf_->set_offset(read_buf_->offset() + data_len);
ParseResponseHeaders();
} else { } else {
data_.append(data + total_bytes_processed, data_.append(data, data_len);
data_len - total_bytes_processed);
} }
DCHECK(!response_headers_.empty());
if (content_length_ >= 0 &&
static_cast<int>(data_.size()) > content_length_) {
Reset(QUIC_BAD_APPLICATION_PAYLOAD);
return 0;
}
DVLOG(1) << "Client processed " << data_len << " bytes for stream " << id();
return data_len; return data_len;
} }
void QuicSpdyClientStream::OnFinRead() { bool QuicSpdyClientStream::ParseResponseHeaders(const char* data,
ReliableQuicStream::OnFinRead(); uint32 data_len) {
if (!response_headers_received_) { DCHECK(headers_decompressed());
Reset(QUIC_BAD_APPLICATION_PAYLOAD); SpdyFramer framer(SPDY3);
} else if ((headers().content_length_status() == size_t len = framer.ParseHeaderBlockInBuffer(data,
BalsaHeadersEnums::VALID_CONTENT_LENGTH) && data_len,
data_.size() != headers().content_length()) { &response_headers_);
Reset(QUIC_BAD_APPLICATION_PAYLOAD); DCHECK_LE(len, data_len);
if (len == 0 || response_headers_.empty()) {
return false; // Headers were invalid.
}
if (data_len > len) {
data_.append(data + len, data_len - len);
}
if (ContainsKey(response_headers_, "content-length") &&
!StringToInt(response_headers_["content-length"], &content_length_)) {
return false; // Invalid content-length.
}
string status = response_headers_[":status"];
size_t end = status.find(" ");
if (end != string::npos) {
status.erase(end);
} }
if (!StringToInt(status, &response_code_)) {
return false; // Invalid response code.
}
return true;
} }
ssize_t QuicSpdyClientStream::SendRequest(const BalsaHeaders& headers, ssize_t QuicSpdyClientStream::SendRequest(const SpdyHeaderBlock& headers,
StringPiece body, StringPiece body,
bool fin) { bool fin) {
SpdyHeaderBlock header_block =
SpdyUtils::RequestHeadersToSpdyHeaders(headers);
bool send_fin_with_headers = fin && body.empty(); bool send_fin_with_headers = fin && body.empty();
size_t bytes_sent = body.size(); size_t bytes_sent = body.size();
header_bytes_written_ = header_bytes_written_ =
WriteHeaders(header_block, send_fin_with_headers, nullptr); WriteHeaders(headers, send_fin_with_headers, nullptr);
bytes_sent += header_bytes_written_; bytes_sent += header_bytes_written_;
if (!body.empty()) { if (!body.empty()) {
...@@ -93,38 +116,12 @@ ssize_t QuicSpdyClientStream::SendRequest(const BalsaHeaders& headers, ...@@ -93,38 +116,12 @@ ssize_t QuicSpdyClientStream::SendRequest(const BalsaHeaders& headers,
return bytes_sent; return bytes_sent;
} }
int QuicSpdyClientStream::ParseResponseHeaders() {
size_t read_buf_len = static_cast<size_t>(read_buf_->offset());
SpdyFramer framer(SPDY3);
SpdyHeaderBlock headers;
char* data = read_buf_->StartOfBuffer();
size_t len = framer.ParseHeaderBlockInBuffer(data, read_buf_->offset(),
&headers);
if (len == 0) {
return -1;
}
if (!SpdyUtils::FillBalsaResponseHeaders(headers, &headers_)) {
Reset(QUIC_BAD_APPLICATION_PAYLOAD);
return -1;
}
response_headers_received_ = true;
size_t delta = read_buf_len - len;
if (delta > 0) {
data_.append(data + len, delta);
}
return len;
}
void QuicSpdyClientStream::SendBody(const string& data, bool fin) { void QuicSpdyClientStream::SendBody(const string& data, bool fin) {
SendBody(data, fin, nullptr); SendBody(data, fin, nullptr);
} }
void QuicSpdyClientStream::SendBody( void QuicSpdyClientStream::SendBody(
const string& data, const string& data, bool fin,
bool fin,
QuicAckNotifier::DelegateInterface* delegate) { QuicAckNotifier::DelegateInterface* delegate) {
WriteOrBufferData(data, fin, delegate); WriteOrBufferData(data, fin, delegate);
} }
......
...@@ -10,14 +10,11 @@ ...@@ -10,14 +10,11 @@
#include "base/basictypes.h" #include "base/basictypes.h"
#include "base/strings/string_piece.h" #include "base/strings/string_piece.h"
#include "net/base/io_buffer.h"
#include "net/quic/quic_data_stream.h" #include "net/quic/quic_data_stream.h"
#include "net/quic/quic_protocol.h" #include "net/quic/quic_protocol.h"
#include "net/tools/balsa/balsa_frame.h" #include "net/spdy/spdy_framer.h"
#include "net/tools/balsa/balsa_headers.h"
namespace net { namespace net {
namespace tools { namespace tools {
class QuicClientSession; class QuicClientSession;
...@@ -41,11 +38,9 @@ class QuicSpdyClientStream : public QuicDataStream { ...@@ -41,11 +38,9 @@ class QuicSpdyClientStream : public QuicDataStream {
// data for us. // data for us.
uint32 ProcessData(const char* data, uint32 data_len) override; uint32 ProcessData(const char* data, uint32 data_len) override;
void OnFinRead() override;
// Serializes the headers and body, sends it to the server, and // Serializes the headers and body, sends it to the server, and
// returns the number of bytes sent. // returns the number of bytes sent.
ssize_t SendRequest(const BalsaHeaders& headers, ssize_t SendRequest(const SpdyHeaderBlock& headers,
base::StringPiece body, base::StringPiece body,
bool fin); bool fin);
...@@ -60,24 +55,27 @@ class QuicSpdyClientStream : public QuicDataStream { ...@@ -60,24 +55,27 @@ class QuicSpdyClientStream : public QuicDataStream {
const std::string& data() { return data_; } const std::string& data() { return data_; }
// Returns whatever headers have been received for this stream. // Returns whatever headers have been received for this stream.
const BalsaHeaders& headers() { return headers_; } const SpdyHeaderBlock& headers() { return response_headers_; }
size_t header_bytes_read() const { return header_bytes_read_; } size_t header_bytes_read() const { return header_bytes_read_; }
size_t header_bytes_written() const { return header_bytes_written_; } size_t header_bytes_written() const { return header_bytes_written_; }
int response_code() const { return response_code_; }
// While the server's set_priority shouldn't be called externally, the creator // While the server's set_priority shouldn't be called externally, the creator
// of client-side streams should be able to set the priority. // of client-side streams should be able to set the priority.
using QuicDataStream::set_priority; using QuicDataStream::set_priority;
private: private:
int ParseResponseHeaders(); bool ParseResponseHeaders(const char* data, uint32 data_len);
BalsaHeaders headers_; // The parsed headers received from the server.
SpdyHeaderBlock response_headers_;
// The parsed content-length, or -1 if none is specified.
int content_length_;
int response_code_;
std::string data_; std::string data_;
scoped_refptr<GrowableIOBuffer> read_buf_;
bool response_headers_received_;
size_t header_bytes_read_; size_t header_bytes_read_;
size_t header_bytes_written_; size_t header_bytes_written_;
......
...@@ -65,31 +65,32 @@ INSTANTIATE_TEST_CASE_P(Tests, QuicSpdyClientStreamTest, ...@@ -65,31 +65,32 @@ INSTANTIATE_TEST_CASE_P(Tests, QuicSpdyClientStreamTest,
::testing::ValuesIn(QuicSupportedVersions())); ::testing::ValuesIn(QuicSupportedVersions()));
TEST_P(QuicSpdyClientStreamTest, TestFraming) { TEST_P(QuicSpdyClientStreamTest, TestFraming) {
EXPECT_EQ(headers_string_.size(), stream_->ProcessData( stream_->OnStreamHeaders(headers_string_);
headers_string_.c_str(), headers_string_.size())); stream_->OnStreamHeadersComplete(false, headers_string_.size());
EXPECT_EQ(body_.size(), EXPECT_EQ(body_.size(), stream_->ProcessData(body_.c_str(), body_.size()));
stream_->ProcessData(body_.c_str(), body_.size())); EXPECT_EQ("200 Ok", stream_->headers().find(":status")->second);
EXPECT_EQ(200u, stream_->headers().parsed_response_code()); EXPECT_EQ(200, stream_->response_code());
EXPECT_EQ(body_, stream_->data()); EXPECT_EQ(body_, stream_->data());
} }
TEST_P(QuicSpdyClientStreamTest, TestFramingOnePacket) { TEST_P(QuicSpdyClientStreamTest, TestFramingOnePacket) {
string message = headers_string_ + body_; stream_->OnStreamHeaders(headers_string_);
stream_->OnStreamHeadersComplete(false, headers_string_.size());
EXPECT_EQ(message.size(), stream_->ProcessData( EXPECT_EQ(body_.size(), stream_->ProcessData(body_.c_str(), body_.size()));
message.c_str(), message.size())); EXPECT_EQ("200 Ok", stream_->headers().find(":status")->second);
EXPECT_EQ(200u, stream_->headers().parsed_response_code()); EXPECT_EQ(200, stream_->response_code());
EXPECT_EQ(body_, stream_->data()); EXPECT_EQ(body_, stream_->data());
} }
TEST_P(QuicSpdyClientStreamTest, DISABLED_TestFramingExtraData) { TEST_P(QuicSpdyClientStreamTest, DISABLED_TestFramingExtraData) {
string large_body = "hello world!!!!!!"; string large_body = "hello world!!!!!!";
EXPECT_EQ(headers_string_.size(), stream_->ProcessData( stream_->OnStreamHeaders(headers_string_);
headers_string_.c_str(), headers_string_.size())); stream_->OnStreamHeadersComplete(false, headers_string_.size());
// The headers should parse successfully. // The headers should parse successfully.
EXPECT_EQ(QUIC_STREAM_NO_ERROR, stream_->stream_error()); EXPECT_EQ(QUIC_STREAM_NO_ERROR, stream_->stream_error());
EXPECT_EQ(200u, stream_->headers().parsed_response_code()); EXPECT_EQ("200 Ok", stream_->headers().find(":status")->second);
EXPECT_EQ(200, stream_->response_code());
EXPECT_CALL(*connection_, EXPECT_CALL(*connection_,
SendRstStream(stream_->id(), QUIC_BAD_APPLICATION_PAYLOAD, 0)); SendRstStream(stream_->id(), QUIC_BAD_APPLICATION_PAYLOAD, 0));
......
...@@ -42,7 +42,8 @@ uint32 QuicSpdyServerStream::ProcessData(const char* data, uint32 data_len) { ...@@ -42,7 +42,8 @@ uint32 QuicSpdyServerStream::ProcessData(const char* data, uint32 data_len) {
body_.append(data, data_len); body_.append(data, data_len);
} }
DCHECK(!request_headers_.empty()); DCHECK(!request_headers_.empty());
if (content_length_ > 0 && static_cast<int>(body_.size()) > content_length_) { if (content_length_ >= 0 &&
static_cast<int>(body_.size()) > content_length_) {
SendErrorResponse(); SendErrorResponse();
return 0; return 0;
} }
......
...@@ -326,5 +326,12 @@ bool SpdyUtils::FillBalsaResponseHeaders( ...@@ -326,5 +326,12 @@ bool SpdyUtils::FillBalsaResponseHeaders(
return true; return true;
} }
// static
void SpdyUtils::SpdyHeadersToResponseHeaders(
const SpdyHeaderBlock& block,
BalsaHeaders* headers) {
FillBalsaResponseHeaders(block, headers);
}
} // namespace tools } // namespace tools
} // namespace net } // namespace net
...@@ -41,6 +41,9 @@ class SpdyUtils { ...@@ -41,6 +41,9 @@ class SpdyUtils {
static std::string SerializeUncompressedHeaders( static std::string SerializeUncompressedHeaders(
const SpdyHeaderBlock& headers); const SpdyHeaderBlock& headers);
static void SpdyHeadersToResponseHeaders(const SpdyHeaderBlock& block,
BalsaHeaders* headers);
private: private:
DISALLOW_COPY_AND_ASSIGN(SpdyUtils); DISALLOW_COPY_AND_ASSIGN(SpdyUtils);
}; };
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include "net/tools/quic/quic_epoll_connection_helper.h" #include "net/tools/quic/quic_epoll_connection_helper.h"
#include "net/tools/quic/quic_packet_writer_wrapper.h" #include "net/tools/quic/quic_packet_writer_wrapper.h"
#include "net/tools/quic/quic_spdy_client_stream.h" #include "net/tools/quic/quic_spdy_client_stream.h"
#include "net/tools/quic/spdy_utils.h"
#include "net/tools/quic/test_tools/http_message.h" #include "net/tools/quic/test_tools/http_message.h"
#include "net/tools/quic/test_tools/quic_client_peer.h" #include "net/tools/quic/test_tools/quic_client_peer.h"
#include "url/gurl.h" #include "url/gurl.h"
...@@ -255,7 +256,8 @@ ssize_t QuicTestClient::SendMessage(const HTTPMessage& message) { ...@@ -255,7 +256,8 @@ ssize_t QuicTestClient::SendMessage(const HTTPMessage& message) {
scoped_ptr<BalsaHeaders> munged_headers(MungeHeaders(message.headers(), scoped_ptr<BalsaHeaders> munged_headers(MungeHeaders(message.headers(),
secure_)); secure_));
ssize_t ret = GetOrCreateStream()->SendRequest( ssize_t ret = GetOrCreateStream()->SendRequest(
munged_headers.get() ? *munged_headers : *message.headers(), SpdyUtils::RequestHeadersToSpdyHeaders(
munged_headers.get() ? *munged_headers : *message.headers()),
message.body(), message.has_complete_message()); message.body(), message.has_complete_message());
WaitForWriteToFlush(); WaitForWriteToFlush();
return ret; return ret;
...@@ -456,14 +458,14 @@ ssize_t QuicTestClient::Send(const void *buffer, size_t size) { ...@@ -456,14 +458,14 @@ ssize_t QuicTestClient::Send(const void *buffer, size_t size) {
bool QuicTestClient::response_headers_complete() const { bool QuicTestClient::response_headers_complete() const {
if (stream_ != nullptr) { if (stream_ != nullptr) {
return stream_->headers_decompressed(); return stream_->headers_decompressed();
} else {
return response_headers_complete_;
} }
return response_headers_complete_;
} }
const BalsaHeaders* QuicTestClient::response_headers() const { const BalsaHeaders* QuicTestClient::response_headers() const {
if (stream_ != nullptr) { if (stream_ != nullptr) {
return &stream_->headers(); SpdyUtils::SpdyHeadersToResponseHeaders(stream_->headers(), &headers_);
return &headers_;
} else { } else {
return &headers_; return &headers_;
} }
...@@ -491,7 +493,8 @@ void QuicTestClient::OnClose(QuicDataStream* stream) { ...@@ -491,7 +493,8 @@ void QuicTestClient::OnClose(QuicDataStream* stream) {
} }
response_complete_ = true; response_complete_ = true;
response_headers_complete_ = stream_->headers_decompressed(); response_headers_complete_ = stream_->headers_decompressed();
headers_.CopyFrom(stream_->headers()); SpdyUtils::SpdyHeadersToResponseHeaders(stream_->headers(),
&headers_);
stream_error_ = stream_->stream_error(); stream_error_ = stream_->stream_error();
bytes_read_ = stream_->stream_bytes_read() + stream_->header_bytes_read(); bytes_read_ = stream_->stream_bytes_read() + stream_->header_bytes_read();
bytes_written_ = bytes_written_ =
......
...@@ -185,7 +185,7 @@ class QuicTestClient : public SimpleClient, ...@@ -185,7 +185,7 @@ class QuicTestClient : public SimpleClient,
bool response_complete_; bool response_complete_;
bool response_headers_complete_; bool response_headers_complete_;
BalsaHeaders headers_; mutable BalsaHeaders headers_;
QuicPriority priority_; QuicPriority priority_;
std::string response_; std::string response_;
uint64 bytes_read_; uint64 bytes_read_;
......
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