Index: net/http/http_stream_parser.cc |
diff --git a/net/http/http_stream_parser.cc b/net/http/http_stream_parser.cc |
index e53aafdac1cfd4871dd41d3cd2989d1ed6e1de27..853414a106a302d789c57c2a57887cda2b3aa6d9 100644 |
--- a/net/http/http_stream_parser.cc |
+++ b/net/http/http_stream_parser.cc |
@@ -79,7 +79,7 @@ namespace net { |
// Example: |
// |
// scoped_refptr<SeekableIOBuffer> buf = new SeekableIOBuffer(1024); |
-// // capacity() == 1024. size() == BytesRemaining == BytesConsumed() == 0. |
+// // capacity() == 1024. size() == BytesRemaining() == BytesConsumed() == 0. |
// // data() points to the beginning of the buffer. |
// |
// // Read() takes an IOBuffer. |
@@ -94,7 +94,7 @@ namespace net { |
// buf->DidConsume(bytes_written); |
// } |
// // BytesRemaining() == 0. BytesConsumed() == size(). |
-// // data() points to the end of the comsumed bytes (exclusive). |
+// // data() points to the end of the consumed bytes (exclusive). |
// |
// // If you want to reuse the buffer, be sure to clear the buffer. |
// buf->Clear(); |
@@ -161,7 +161,7 @@ class HttpStreamParser::SeekableIOBuffer : public net::IOBuffer { |
} |
char* real_data_; |
- int capacity_; |
+ const int capacity_; |
int size_; |
int used_; |
}; |
@@ -293,6 +293,7 @@ int HttpStreamParser::ReadResponseHeaders(const CompletionCallback& callback) { |
DCHECK(io_state_ == STATE_REQUEST_SENT || io_state_ == STATE_DONE); |
DCHECK(callback_.is_null()); |
DCHECK(!callback.is_null()); |
+ DCHECK_EQ(0, read_buf_unused_offset_); |
// This function can be called with io_state_ == STATE_DONE if the |
// connection is closed after seeing just a 1xx response code. |
@@ -304,8 +305,8 @@ int HttpStreamParser::ReadResponseHeaders(const CompletionCallback& callback) { |
if (read_buf_->offset() > 0) { |
// Simulate the state where the data was just read from the socket. |
- result = read_buf_->offset() - read_buf_unused_offset_; |
- read_buf_->set_offset(read_buf_unused_offset_); |
+ result = read_buf_->offset(); |
+ read_buf_->set_offset(0); |
} |
if (result > 0) |
io_state_ = STATE_READ_HEADERS_COMPLETE; |
@@ -517,6 +518,8 @@ int HttpStreamParser::DoReadHeaders() { |
} |
int HttpStreamParser::DoReadHeadersComplete(int result) { |
+ DCHECK_EQ(0, read_buf_unused_offset_); |
+ |
if (result == 0) |
result = ERR_CONNECTION_CLOSED; |
@@ -580,41 +583,43 @@ int HttpStreamParser::DoReadHeadersComplete(int result) { |
if (end_of_header_offset == -1) { |
io_state_ = STATE_READ_HEADERS; |
// Prevent growing the headers buffer indefinitely. |
- if (read_buf_->offset() - read_buf_unused_offset_ >= kMaxHeaderBufSize) { |
+ if (read_buf_->offset() >= kMaxHeaderBufSize) { |
io_state_ = STATE_DONE; |
return ERR_RESPONSE_HEADERS_TOO_BIG; |
} |
} else { |
+ CalculateResponseBodySize(); |
+ // If the body is zero length, the caller may not call ReadResponseBody, |
+ // which is where any extra data is copied to read_buf_, so we move the |
+ // data here. |
+ if (response_body_length_ == 0) { |
+ int extra_bytes = read_buf_->offset() - end_of_header_offset; |
+ if (extra_bytes) { |
+ CHECK_GT(extra_bytes, 0); |
+ memmove(read_buf_->StartOfBuffer(), |
+ read_buf_->StartOfBuffer() + end_of_header_offset, |
+ extra_bytes); |
+ } |
+ read_buf_->SetCapacity(extra_bytes); |
+ if (response_->headers->response_code() / 100 == 1) { |
+ // After processing a 1xx response, the caller will ask for the next |
+ // header, so reset state to support that. We don't completely ignore a |
+ // 1xx response because it cannot be returned in reply to a CONNECT |
+ // request so we return OK here, which lets the caller inspect the |
+ // response and reject it in the event that we're setting up a CONNECT |
+ // tunnel. |
+ response_header_start_offset_ = -1; |
+ response_body_length_ = -1; |
+ io_state_ = STATE_REQUEST_SENT; |
+ } else { |
+ io_state_ = STATE_DONE; |
+ } |
+ return OK; |
+ } |
+ |
// Note where the headers stop. |
read_buf_unused_offset_ = end_of_header_offset; |
- |
- if (response_->headers->response_code() / 100 == 1) { |
- // After processing a 1xx response, the caller will ask for the next |
- // header, so reset state to support that. We don't just skip these |
- // completely because 1xx codes aren't acceptable when establishing a |
- // tunnel. |
- io_state_ = STATE_REQUEST_SENT; |
- response_header_start_offset_ = -1; |
- } else { |
- io_state_ = STATE_BODY_PENDING; |
- CalculateResponseBodySize(); |
- // If the body is 0, the caller may not call ReadResponseBody, which |
- // is where any extra data is copied to read_buf_, so we move the |
- // data here and transition to DONE. |
- if (response_body_length_ == 0) { |
- io_state_ = STATE_DONE; |
- int extra_bytes = read_buf_->offset() - read_buf_unused_offset_; |
- if (extra_bytes) { |
- CHECK_GT(extra_bytes, 0); |
- memmove(read_buf_->StartOfBuffer(), |
- read_buf_->StartOfBuffer() + read_buf_unused_offset_, |
- extra_bytes); |
- } |
- read_buf_->SetCapacity(extra_bytes); |
- read_buf_unused_offset_ = 0; |
- return OK; |
- } |
- } |
+ io_state_ = STATE_BODY_PENDING; |
} |
return result; |
} |
@@ -751,20 +756,19 @@ int HttpStreamParser::DoReadBodyComplete(int result) { |
int HttpStreamParser::ParseResponseHeaders() { |
int end_offset = -1; |
+ DCHECK_EQ(0, read_buf_unused_offset_); |
// Look for the start of the status line, if it hasn't been found yet. |
if (response_header_start_offset_ < 0) { |
response_header_start_offset_ = HttpUtil::LocateStartOfStatusLine( |
- read_buf_->StartOfBuffer() + read_buf_unused_offset_, |
- read_buf_->offset() - read_buf_unused_offset_); |
+ read_buf_->StartOfBuffer(), read_buf_->offset()); |
} |
if (response_header_start_offset_ >= 0) { |
- end_offset = HttpUtil::LocateEndOfHeaders( |
- read_buf_->StartOfBuffer() + read_buf_unused_offset_, |
- read_buf_->offset() - read_buf_unused_offset_, |
- response_header_start_offset_); |
- } else if (read_buf_->offset() - read_buf_unused_offset_ >= 8) { |
+ end_offset = HttpUtil::LocateEndOfHeaders(read_buf_->StartOfBuffer(), |
+ read_buf_->offset(), |
+ response_header_start_offset_); |
+ } else if (read_buf_->offset() >= 8) { |
// Enough data to decide that this is an HTTP/0.9 response. |
// 8 bytes = (4 bytes of junk) + "http".length() |
end_offset = 0; |
@@ -776,14 +780,16 @@ int HttpStreamParser::ParseResponseHeaders() { |
int rv = DoParseResponseHeaders(end_offset); |
if (rv < 0) |
return rv; |
- return end_offset + read_buf_unused_offset_; |
+ return end_offset; |
} |
int HttpStreamParser::DoParseResponseHeaders(int end_offset) { |
scoped_refptr<HttpResponseHeaders> headers; |
+ DCHECK_EQ(0, read_buf_unused_offset_); |
+ |
if (response_header_start_offset_ >= 0) { |
headers = new HttpResponseHeaders(HttpUtil::AssembleRawHeaders( |
- read_buf_->StartOfBuffer() + read_buf_unused_offset_, end_offset)); |
+ read_buf_->StartOfBuffer(), end_offset)); |
} else { |
// Enough data was read -- there is no status line. |
headers = new HttpResponseHeaders(std::string("HTTP/0.9 200 OK")); |
@@ -830,13 +836,16 @@ void HttpStreamParser::CalculateResponseBodySize() { |
// (informational), 204 (no content), and 304 (not modified) responses |
// MUST NOT include a message-body. All other responses do include a |
// message-body, although it MAY be of zero length. |
- switch (response_->headers->response_code()) { |
- // Note that 1xx was already handled earlier. |
- case 204: // No Content |
- case 205: // Reset Content |
- case 304: // Not Modified |
- response_body_length_ = 0; |
- break; |
+ if (response_->headers->response_code() / 100 == 1) { |
+ response_body_length_ = 0; |
+ } else { |
+ switch (response_->headers->response_code()) { |
+ case 204: // No Content |
+ case 205: // Reset Content |
+ case 304: // Not Modified |
+ response_body_length_ = 0; |
+ break; |
+ } |
} |
if (request_->method == "HEAD") |
response_body_length_ = 0; |