| Index: net/tools/quic/quic_spdy_server_stream.cc
|
| diff --git a/net/tools/quic/quic_spdy_server_stream.cc b/net/tools/quic/quic_spdy_server_stream.cc
|
| index 9e07a788f694659e1bb0a2081cce3122e4d70f51..05180478fdf38e2e76bbd49985a58f737e783b4b 100644
|
| --- a/net/tools/quic/quic_spdy_server_stream.cc
|
| +++ b/net/tools/quic/quic_spdy_server_stream.cc
|
| @@ -4,6 +4,7 @@
|
|
|
| #include "net/tools/quic/quic_spdy_server_stream.h"
|
|
|
| +#include "base/strings/string_number_conversions.h"
|
| #include "net/quic/quic_session.h"
|
| #include "net/spdy/spdy_framer.h"
|
| #include "net/tools/quic/quic_in_memory_cache.h"
|
| @@ -16,34 +17,35 @@ using std::string;
|
| namespace net {
|
| namespace tools {
|
|
|
| -static const size_t kHeaderBufInitialSize = 4096;
|
| -
|
| QuicSpdyServerStream::QuicSpdyServerStream(QuicStreamId id,
|
| QuicSession* session)
|
| : QuicDataStream(id, session),
|
| - read_buf_(new GrowableIOBuffer()),
|
| - request_headers_received_(false) {
|
| + content_length_(-1) {
|
| }
|
|
|
| QuicSpdyServerStream::~QuicSpdyServerStream() {
|
| }
|
|
|
| uint32 QuicSpdyServerStream::ProcessData(const char* data, uint32 data_len) {
|
| - uint32 total_bytes_processed = 0;
|
| -
|
| - // Are we still reading the request headers.
|
| - if (!request_headers_received_) {
|
| - // Grow the read buffer if necessary.
|
| - if (read_buf_->RemainingCapacity() < (int)data_len) {
|
| - read_buf_->SetCapacity(read_buf_->capacity() + kHeaderBufInitialSize);
|
| + if (!headers_decompressed()) {
|
| + // Let the headers data accumulate in the underlying QuicDataStream.
|
| + return 0;
|
| + }
|
| + if (request_headers_.empty()) {
|
| + if (!ParseRequestHeaders(data, data_len)) {
|
| + // Headers were invalid.
|
| + SendErrorResponse();
|
| + return 0;
|
| }
|
| - memcpy(read_buf_->data(), data, data_len);
|
| - read_buf_->set_offset(read_buf_->offset() + data_len);
|
| - ParseRequestHeaders();
|
| } else {
|
| - body_.append(data + total_bytes_processed,
|
| - data_len - total_bytes_processed);
|
| + body_.append(data, data_len);
|
| + }
|
| + DCHECK(!request_headers_.empty());
|
| + if (content_length_ > 0 && static_cast<int>(body_.size()) > content_length_) {
|
| + SendErrorResponse();
|
| + return 0;
|
| }
|
| + DVLOG(1) << "Processed " << data_len << " bytes for stream " << id();
|
| return data_len;
|
| }
|
|
|
| @@ -53,52 +55,54 @@ void QuicSpdyServerStream::OnFinRead() {
|
| return;
|
| }
|
|
|
| - if (!request_headers_received_) {
|
| - SendErrorResponse(); // We're not done reading headers.
|
| - } else if ((headers_.content_length_status() ==
|
| - BalsaHeadersEnums::VALID_CONTENT_LENGTH) &&
|
| - body_.size() != headers_.content_length()) {
|
| - SendErrorResponse(); // Invalid content length
|
| - } else {
|
| - SendResponse();
|
| - }
|
| -}
|
| -
|
| -void QuicSpdyServerStream::ParseRequestHeaders() {
|
| - 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) {
|
| + if (request_headers_.empty()) {
|
| + SendErrorResponse();
|
| return;
|
| }
|
|
|
| - if (!SpdyUtils::FillBalsaRequestHeaders(headers, &headers_)) {
|
| + if (content_length_ > 0 &&
|
| + content_length_ != static_cast<int>(body_.size())) {
|
| SendErrorResponse();
|
| return;
|
| }
|
|
|
| - size_t delta = read_buf_len - len;
|
| - if (delta > 0) {
|
| - body_.append(data + len, delta);
|
| + SendResponse();
|
| +}
|
| +
|
| +bool QuicSpdyServerStream::ParseRequestHeaders(const char* data,
|
| + uint32 data_len) {
|
| + DCHECK(headers_decompressed());
|
| + SpdyFramer framer(SPDY3);
|
| + size_t len = framer.ParseHeaderBlockInBuffer(data,
|
| + data_len,
|
| + &request_headers_);
|
| + DCHECK_LE(len, data_len);
|
| + if (len == 0 || request_headers_.empty()) {
|
| + return false; // Headers were invalid.
|
| }
|
|
|
| - request_headers_received_ = true;
|
| + if (data_len > len) {
|
| + body_.append(data + len, data_len - len);
|
| + }
|
| + if (ContainsKey(request_headers_, "content-length") &&
|
| + !base::StringToInt(request_headers_["content-length"], &content_length_)) {
|
| + return false; // Invalid content-length.
|
| + }
|
| + return true;
|
| }
|
|
|
| void QuicSpdyServerStream::SendResponse() {
|
| - // Find response in cache. If not found, send error response.
|
| - GURL url(headers_.request_uri().as_string());
|
| - if (!url.is_valid()) {
|
| + if (!ContainsKey(request_headers_, ":host") ||
|
| + !ContainsKey(request_headers_, ":path")) {
|
| SendErrorResponse();
|
| return;
|
| }
|
| +
|
| + // Find response in cache. If not found, send error response.
|
| const QuicInMemoryCache::Response* response =
|
| QuicInMemoryCache::GetInstance()->GetResponse(
|
| - url.host(),
|
| - url.PathForRequest());
|
| + request_headers_[":host"],
|
| + request_headers_[":path"]);
|
| if (response == nullptr) {
|
| SendErrorResponse();
|
| return;
|
|
|