| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/http/http_stream_parser.h" | 5 #include "net/http/http_stream_parser.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/compiler_specific.h" | 8 #include "base/compiler_specific.h" |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/strings/string_util.h" | 10 #include "base/strings/string_util.h" |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 103 // // data() points to the end of the consumed bytes (exclusive). | 103 // // data() points to the end of the consumed bytes (exclusive). |
| 104 // | 104 // |
| 105 // // If you want to reuse the buffer, be sure to clear the buffer. | 105 // // If you want to reuse the buffer, be sure to clear the buffer. |
| 106 // buf->Clear(); | 106 // buf->Clear(); |
| 107 // // size() == BytesRemaining() == BytesConsumed() == 0. | 107 // // size() == BytesRemaining() == BytesConsumed() == 0. |
| 108 // // data() points to the beginning of the buffer. | 108 // // data() points to the beginning of the buffer. |
| 109 // | 109 // |
| 110 class HttpStreamParser::SeekableIOBuffer : public IOBuffer { | 110 class HttpStreamParser::SeekableIOBuffer : public IOBuffer { |
| 111 public: | 111 public: |
| 112 explicit SeekableIOBuffer(int capacity) | 112 explicit SeekableIOBuffer(int capacity) |
| 113 : IOBuffer(capacity), | 113 : IOBuffer(capacity), |
| 114 real_data_(data_), | 114 real_data_(data_), |
| 115 capacity_(capacity), | 115 capacity_(capacity), |
| 116 size_(0), | 116 size_(0), |
| 117 used_(0) { | 117 used_(0) {} |
| 118 } | |
| 119 | 118 |
| 120 // DidConsume() changes the |data_| pointer so that |data_| always points | 119 // DidConsume() changes the |data_| pointer so that |data_| always points |
| 121 // to the first unconsumed byte. | 120 // to the first unconsumed byte. |
| 122 void DidConsume(int bytes) { | 121 void DidConsume(int bytes) { SetOffset(used_ + bytes); } |
| 123 SetOffset(used_ + bytes); | |
| 124 } | |
| 125 | 122 |
| 126 // Returns the number of unconsumed bytes. | 123 // Returns the number of unconsumed bytes. |
| 127 int BytesRemaining() const { | 124 int BytesRemaining() const { return size_ - used_; } |
| 128 return size_ - used_; | |
| 129 } | |
| 130 | 125 |
| 131 // Seeks to an arbitrary point in the buffer. The notion of bytes consumed | 126 // Seeks to an arbitrary point in the buffer. The notion of bytes consumed |
| 132 // and remaining are updated appropriately. | 127 // and remaining are updated appropriately. |
| 133 void SetOffset(int bytes) { | 128 void SetOffset(int bytes) { |
| 134 DCHECK_GE(bytes, 0); | 129 DCHECK_GE(bytes, 0); |
| 135 DCHECK_LE(bytes, size_); | 130 DCHECK_LE(bytes, size_); |
| 136 used_ = bytes; | 131 used_ = bytes; |
| 137 data_ = real_data_ + used_; | 132 data_ = real_data_ + used_; |
| 138 } | 133 } |
| 139 | 134 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 151 size_ = 0; | 146 size_ = 0; |
| 152 SetOffset(0); | 147 SetOffset(0); |
| 153 } | 148 } |
| 154 | 149 |
| 155 // Returns the logical size of the buffer (i.e the number of bytes of data | 150 // Returns the logical size of the buffer (i.e the number of bytes of data |
| 156 // in the buffer). | 151 // in the buffer). |
| 157 int size() const { return size_; } | 152 int size() const { return size_; } |
| 158 | 153 |
| 159 // Returns the capacity of the buffer. The capacity is the size used when | 154 // Returns the capacity of the buffer. The capacity is the size used when |
| 160 // the object is created. | 155 // the object is created. |
| 161 int capacity() const { return capacity_; }; | 156 int capacity() const { |
| 157 return capacity_; |
| 158 }; |
| 162 | 159 |
| 163 private: | 160 private: |
| 164 virtual ~SeekableIOBuffer() { | 161 virtual ~SeekableIOBuffer() { |
| 165 // data_ will be deleted in IOBuffer::~IOBuffer(). | 162 // data_ will be deleted in IOBuffer::~IOBuffer(). |
| 166 data_ = real_data_; | 163 data_ = real_data_; |
| 167 } | 164 } |
| 168 | 165 |
| 169 char* real_data_; | 166 char* real_data_; |
| 170 const int capacity_; | 167 const int capacity_; |
| 171 int size_; | 168 int size_; |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 205 | 202 |
| 206 int HttpStreamParser::SendRequest(const std::string& request_line, | 203 int HttpStreamParser::SendRequest(const std::string& request_line, |
| 207 const HttpRequestHeaders& headers, | 204 const HttpRequestHeaders& headers, |
| 208 HttpResponseInfo* response, | 205 HttpResponseInfo* response, |
| 209 const CompletionCallback& callback) { | 206 const CompletionCallback& callback) { |
| 210 DCHECK_EQ(STATE_NONE, io_state_); | 207 DCHECK_EQ(STATE_NONE, io_state_); |
| 211 DCHECK(callback_.is_null()); | 208 DCHECK(callback_.is_null()); |
| 212 DCHECK(!callback.is_null()); | 209 DCHECK(!callback.is_null()); |
| 213 DCHECK(response); | 210 DCHECK(response); |
| 214 | 211 |
| 215 net_log_.AddEvent( | 212 net_log_.AddEvent(NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS, |
| 216 NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS, | 213 base::Bind(&HttpRequestHeaders::NetLogCallback, |
| 217 base::Bind(&HttpRequestHeaders::NetLogCallback, | 214 base::Unretained(&headers), |
| 218 base::Unretained(&headers), | 215 &request_line)); |
| 219 &request_line)); | |
| 220 | 216 |
| 221 DVLOG(1) << __FUNCTION__ << "()" | 217 DVLOG(1) << __FUNCTION__ << "()" |
| 222 << " request_line = \"" << request_line << "\"" | 218 << " request_line = \"" << request_line << "\"" |
| 223 << " headers = \"" << headers.ToString() << "\""; | 219 << " headers = \"" << headers.ToString() << "\""; |
| 224 response_ = response; | 220 response_ = response; |
| 225 | 221 |
| 226 // Put the peer's IP address and port into the response. | 222 // Put the peer's IP address and port into the response. |
| 227 IPEndPoint ip_endpoint; | 223 IPEndPoint ip_endpoint; |
| 228 int result = connection_->socket()->GetPeerAddress(&ip_endpoint); | 224 int result = connection_->socket()->GetPeerAddress(&ip_endpoint); |
| 229 if (result != OK) | 225 if (result != OK) |
| (...skipping 29 matching lines...) Expand all Loading... |
| 259 // We'll repurpose |request_headers_| to store the merged headers and | 255 // We'll repurpose |request_headers_| to store the merged headers and |
| 260 // body. | 256 // body. |
| 261 request_headers_ = new DrainableIOBuffer( | 257 request_headers_ = new DrainableIOBuffer( |
| 262 merged_request_headers_and_body.get(), merged_size); | 258 merged_request_headers_and_body.get(), merged_size); |
| 263 | 259 |
| 264 memcpy(request_headers_->data(), request.data(), request_headers_length_); | 260 memcpy(request_headers_->data(), request.data(), request_headers_length_); |
| 265 request_headers_->DidConsume(request_headers_length_); | 261 request_headers_->DidConsume(request_headers_length_); |
| 266 | 262 |
| 267 size_t todo = request_->upload_data_stream->size(); | 263 size_t todo = request_->upload_data_stream->size(); |
| 268 while (todo) { | 264 while (todo) { |
| 269 int consumed = request_->upload_data_stream | 265 int consumed = request_->upload_data_stream->Read( |
| 270 ->Read(request_headers_.get(), todo, CompletionCallback()); | 266 request_headers_.get(), todo, CompletionCallback()); |
| 271 DCHECK_GT(consumed, 0); // Read() won't fail if not chunked. | 267 DCHECK_GT(consumed, 0); // Read() won't fail if not chunked. |
| 272 request_headers_->DidConsume(consumed); | 268 request_headers_->DidConsume(consumed); |
| 273 todo -= consumed; | 269 todo -= consumed; |
| 274 } | 270 } |
| 275 DCHECK(request_->upload_data_stream->IsEOF()); | 271 DCHECK(request_->upload_data_stream->IsEOF()); |
| 276 // Reset the offset, so the buffer can be read from the beginning. | 272 // Reset the offset, so the buffer can be read from the beginning. |
| 277 request_headers_->SetOffset(0); | 273 request_headers_->SetOffset(0); |
| 278 did_merge = true; | 274 did_merge = true; |
| 279 | 275 |
| 280 net_log_.AddEvent( | 276 net_log_.AddEvent(NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_BODY, |
| 281 NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_BODY, | 277 base::Bind(&NetLogSendRequestBodyCallback, |
| 282 base::Bind(&NetLogSendRequestBodyCallback, | 278 request_->upload_data_stream->size(), |
| 283 request_->upload_data_stream->size(), | 279 false, /* not chunked */ |
| 284 false, /* not chunked */ | 280 true /* merged */)); |
| 285 true /* merged */)); | |
| 286 } | 281 } |
| 287 | 282 |
| 288 if (!did_merge) { | 283 if (!did_merge) { |
| 289 // If we didn't merge the body with the headers, then |request_headers_| | 284 // If we didn't merge the body with the headers, then |request_headers_| |
| 290 // contains just the HTTP headers. | 285 // contains just the HTTP headers. |
| 291 scoped_refptr<StringIOBuffer> headers_io_buf(new StringIOBuffer(request)); | 286 scoped_refptr<StringIOBuffer> headers_io_buf(new StringIOBuffer(request)); |
| 292 request_headers_ = | 287 request_headers_ = |
| 293 new DrainableIOBuffer(headers_io_buf.get(), headers_io_buf->size()); | 288 new DrainableIOBuffer(headers_io_buf.get(), headers_io_buf->size()); |
| 294 } | 289 } |
| 295 | 290 |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 328 | 323 |
| 329 return result > 0 ? OK : result; | 324 return result > 0 ? OK : result; |
| 330 } | 325 } |
| 331 | 326 |
| 332 void HttpStreamParser::Close(bool not_reusable) { | 327 void HttpStreamParser::Close(bool not_reusable) { |
| 333 if (not_reusable && connection_->socket()) | 328 if (not_reusable && connection_->socket()) |
| 334 connection_->socket()->Disconnect(); | 329 connection_->socket()->Disconnect(); |
| 335 connection_->Reset(); | 330 connection_->Reset(); |
| 336 } | 331 } |
| 337 | 332 |
| 338 int HttpStreamParser::ReadResponseBody(IOBuffer* buf, int buf_len, | 333 int HttpStreamParser::ReadResponseBody(IOBuffer* buf, |
| 334 int buf_len, |
| 339 const CompletionCallback& callback) { | 335 const CompletionCallback& callback) { |
| 340 DCHECK(io_state_ == STATE_NONE || io_state_ == STATE_DONE); | 336 DCHECK(io_state_ == STATE_NONE || io_state_ == STATE_DONE); |
| 341 DCHECK(callback_.is_null()); | 337 DCHECK(callback_.is_null()); |
| 342 DCHECK(!callback.is_null()); | 338 DCHECK(!callback.is_null()); |
| 343 DCHECK_LE(buf_len, kMaxBufSize); | 339 DCHECK_LE(buf_len, kMaxBufSize); |
| 344 | 340 |
| 345 if (io_state_ == STATE_DONE) | 341 if (io_state_ == STATE_DONE) |
| 346 return OK; | 342 return OK; |
| 347 | 343 |
| 348 // Must have response headers with a non-1xx error code. | 344 // Must have response headers with a non-1xx error code. |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 426 int HttpStreamParser::DoSendHeaders() { | 422 int HttpStreamParser::DoSendHeaders() { |
| 427 int bytes_remaining = request_headers_->BytesRemaining(); | 423 int bytes_remaining = request_headers_->BytesRemaining(); |
| 428 DCHECK_GT(bytes_remaining, 0); | 424 DCHECK_GT(bytes_remaining, 0); |
| 429 | 425 |
| 430 // Record our best estimate of the 'request time' as the time when we send | 426 // Record our best estimate of the 'request time' as the time when we send |
| 431 // out the first bytes of the request headers. | 427 // out the first bytes of the request headers. |
| 432 if (bytes_remaining == request_headers_->size()) | 428 if (bytes_remaining == request_headers_->size()) |
| 433 response_->request_time = base::Time::Now(); | 429 response_->request_time = base::Time::Now(); |
| 434 | 430 |
| 435 io_state_ = STATE_SEND_HEADERS_COMPLETE; | 431 io_state_ = STATE_SEND_HEADERS_COMPLETE; |
| 436 return connection_->socket() | 432 return connection_->socket()->Write( |
| 437 ->Write(request_headers_.get(), bytes_remaining, io_callback_); | 433 request_headers_.get(), bytes_remaining, io_callback_); |
| 438 } | 434 } |
| 439 | 435 |
| 440 int HttpStreamParser::DoSendHeadersComplete(int result) { | 436 int HttpStreamParser::DoSendHeadersComplete(int result) { |
| 441 if (result < 0) { | 437 if (result < 0) { |
| 442 // In the unlikely case that the headers and body were merged, all the | 438 // In the unlikely case that the headers and body were merged, all the |
| 443 // the headers were sent, but not all of the body way, and |result| is | 439 // the headers were sent, but not all of the body way, and |result| is |
| 444 // an error that this should try reading after, stash the error for now and | 440 // an error that this should try reading after, stash the error for now and |
| 445 // act like the request was successfully sent. | 441 // act like the request was successfully sent. |
| 446 if (request_headers_->BytesConsumed() >= request_headers_length_ && | 442 if (request_headers_->BytesConsumed() >= request_headers_length_ && |
| 447 ShouldTryReadingOnUploadError(result)) { | 443 ShouldTryReadingOnUploadError(result)) { |
| 448 upload_error_ = result; | 444 upload_error_ = result; |
| 449 return OK; | 445 return OK; |
| 450 } | 446 } |
| 451 return result; | 447 return result; |
| 452 } | 448 } |
| 453 | 449 |
| 454 request_headers_->DidConsume(result); | 450 request_headers_->DidConsume(result); |
| 455 if (request_headers_->BytesRemaining() > 0) { | 451 if (request_headers_->BytesRemaining() > 0) { |
| 456 io_state_ = STATE_SEND_HEADERS; | 452 io_state_ = STATE_SEND_HEADERS; |
| 457 return OK; | 453 return OK; |
| 458 } | 454 } |
| 459 | 455 |
| 460 if (request_->upload_data_stream != NULL && | 456 if (request_->upload_data_stream != NULL && |
| 461 (request_->upload_data_stream->is_chunked() || | 457 (request_->upload_data_stream->is_chunked() || |
| 462 // !IsEOF() indicates that the body wasn't merged. | 458 // !IsEOF() indicates that the body wasn't merged. |
| 463 (request_->upload_data_stream->size() > 0 && | 459 (request_->upload_data_stream->size() > 0 && |
| 464 !request_->upload_data_stream->IsEOF()))) { | 460 !request_->upload_data_stream->IsEOF()))) { |
| 465 net_log_.AddEvent( | 461 net_log_.AddEvent(NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_BODY, |
| 466 NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_BODY, | 462 base::Bind(&NetLogSendRequestBodyCallback, |
| 467 base::Bind(&NetLogSendRequestBodyCallback, | 463 request_->upload_data_stream->size(), |
| 468 request_->upload_data_stream->size(), | 464 request_->upload_data_stream->is_chunked(), |
| 469 request_->upload_data_stream->is_chunked(), | 465 false /* not merged */)); |
| 470 false /* not merged */)); | |
| 471 io_state_ = STATE_SEND_BODY; | 466 io_state_ = STATE_SEND_BODY; |
| 472 return OK; | 467 return OK; |
| 473 } | 468 } |
| 474 | 469 |
| 475 // Finished sending the request. | 470 // Finished sending the request. |
| 476 return OK; | 471 return OK; |
| 477 } | 472 } |
| 478 | 473 |
| 479 int HttpStreamParser::DoSendBody() { | 474 int HttpStreamParser::DoSendBody() { |
| 480 if (request_body_send_buf_->BytesRemaining() > 0) { | 475 if (request_body_send_buf_->BytesRemaining() > 0) { |
| 481 io_state_ = STATE_SEND_BODY_COMPLETE; | 476 io_state_ = STATE_SEND_BODY_COMPLETE; |
| 482 return connection_->socket() | 477 return connection_->socket()->Write( |
| 483 ->Write(request_body_send_buf_.get(), | 478 request_body_send_buf_.get(), |
| 484 request_body_send_buf_->BytesRemaining(), | 479 request_body_send_buf_->BytesRemaining(), |
| 485 io_callback_); | 480 io_callback_); |
| 486 } | 481 } |
| 487 | 482 |
| 488 if (request_->upload_data_stream->is_chunked() && sent_last_chunk_) { | 483 if (request_->upload_data_stream->is_chunked() && sent_last_chunk_) { |
| 489 // Finished sending the request. | 484 // Finished sending the request. |
| 490 return OK; | 485 return OK; |
| 491 } | 486 } |
| 492 | 487 |
| 493 request_body_read_buf_->Clear(); | 488 request_body_read_buf_->Clear(); |
| 494 io_state_ = STATE_SEND_REQUEST_READ_BODY_COMPLETE; | 489 io_state_ = STATE_SEND_REQUEST_READ_BODY_COMPLETE; |
| 495 return request_->upload_data_stream->Read(request_body_read_buf_.get(), | 490 return request_->upload_data_stream->Read(request_body_read_buf_.get(), |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 551 io_state_ = STATE_READ_HEADERS_COMPLETE; | 546 io_state_ = STATE_READ_HEADERS_COMPLETE; |
| 552 | 547 |
| 553 // Grow the read buffer if necessary. | 548 // Grow the read buffer if necessary. |
| 554 if (read_buf_->RemainingCapacity() == 0) | 549 if (read_buf_->RemainingCapacity() == 0) |
| 555 read_buf_->SetCapacity(read_buf_->capacity() + kHeaderBufInitialSize); | 550 read_buf_->SetCapacity(read_buf_->capacity() + kHeaderBufInitialSize); |
| 556 | 551 |
| 557 // http://crbug.com/16371: We're seeing |user_buf_->data()| return NULL. | 552 // http://crbug.com/16371: We're seeing |user_buf_->data()| return NULL. |
| 558 // See if the user is passing in an IOBuffer with a NULL |data_|. | 553 // See if the user is passing in an IOBuffer with a NULL |data_|. |
| 559 CHECK(read_buf_->data()); | 554 CHECK(read_buf_->data()); |
| 560 | 555 |
| 561 return connection_->socket() | 556 return connection_->socket()->Read( |
| 562 ->Read(read_buf_.get(), read_buf_->RemainingCapacity(), io_callback_); | 557 read_buf_.get(), read_buf_->RemainingCapacity(), io_callback_); |
| 563 } | 558 } |
| 564 | 559 |
| 565 int HttpStreamParser::DoReadHeadersComplete(int result) { | 560 int HttpStreamParser::DoReadHeadersComplete(int result) { |
| 566 result = HandleReadHeaderResult(result); | 561 result = HandleReadHeaderResult(result); |
| 567 | 562 |
| 568 // TODO(mmenke): The code below is ugly and hacky. A much better and more | 563 // TODO(mmenke): The code below is ugly and hacky. A much better and more |
| 569 // flexible long term solution would be to separate out the read and write | 564 // flexible long term solution would be to separate out the read and write |
| 570 // loops, though this would involve significant changes, both here and | 565 // loops, though this would involve significant changes, both here and |
| 571 // elsewhere (WebSockets, for instance). | 566 // elsewhere (WebSockets, for instance). |
| 572 | 567 |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 631 read_buf_->SetCapacity(0); | 626 read_buf_->SetCapacity(0); |
| 632 read_buf_unused_offset_ = 0; | 627 read_buf_unused_offset_ = 0; |
| 633 } | 628 } |
| 634 } | 629 } |
| 635 | 630 |
| 636 // Check to see if we're done reading. | 631 // Check to see if we're done reading. |
| 637 if (IsResponseBodyComplete()) | 632 if (IsResponseBodyComplete()) |
| 638 return 0; | 633 return 0; |
| 639 | 634 |
| 640 DCHECK_EQ(0, read_buf_->offset()); | 635 DCHECK_EQ(0, read_buf_->offset()); |
| 641 return connection_->socket() | 636 return connection_->socket()->Read( |
| 642 ->Read(user_read_buf_.get(), user_read_buf_len_, io_callback_); | 637 user_read_buf_.get(), user_read_buf_len_, io_callback_); |
| 643 } | 638 } |
| 644 | 639 |
| 645 int HttpStreamParser::DoReadBodyComplete(int result) { | 640 int HttpStreamParser::DoReadBodyComplete(int result) { |
| 646 // When the connection is closed, there are numerous ways to interpret it. | 641 // When the connection is closed, there are numerous ways to interpret it. |
| 647 // | 642 // |
| 648 // - If a Content-Length header is present and the body contains exactly that | 643 // - If a Content-Length header is present and the body contains exactly that |
| 649 // number of bytes at connection close, the response is successful. | 644 // number of bytes at connection close, the response is successful. |
| 650 // | 645 // |
| 651 // - If a Content-Length header is present and the body contains fewer bytes | 646 // - If a Content-Length header is present and the body contains fewer bytes |
| 652 // than promised by the header at connection close, it may indicate that | 647 // than promised by the header at connection close, it may indicate that |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 716 } | 711 } |
| 717 } | 712 } |
| 718 | 713 |
| 719 CHECK_LE(save_amount + additional_save_amount, kMaxBufSize); | 714 CHECK_LE(save_amount + additional_save_amount, kMaxBufSize); |
| 720 if (read_buf_->capacity() < save_amount + additional_save_amount) { | 715 if (read_buf_->capacity() < save_amount + additional_save_amount) { |
| 721 read_buf_->SetCapacity(save_amount + additional_save_amount); | 716 read_buf_->SetCapacity(save_amount + additional_save_amount); |
| 722 } | 717 } |
| 723 | 718 |
| 724 if (save_amount) { | 719 if (save_amount) { |
| 725 received_bytes_ -= save_amount; | 720 received_bytes_ -= save_amount; |
| 726 memcpy(read_buf_->StartOfBuffer(), user_read_buf_->data() + result, | 721 memcpy(read_buf_->StartOfBuffer(), |
| 722 user_read_buf_->data() + result, |
| 727 save_amount); | 723 save_amount); |
| 728 } | 724 } |
| 729 read_buf_->set_offset(save_amount); | 725 read_buf_->set_offset(save_amount); |
| 730 if (additional_save_amount) { | 726 if (additional_save_amount) { |
| 731 memmove(read_buf_->data(), | 727 memmove(read_buf_->data(), |
| 732 read_buf_->StartOfBuffer() + read_buf_unused_offset_, | 728 read_buf_->StartOfBuffer() + read_buf_unused_offset_, |
| 733 additional_save_amount); | 729 additional_save_amount); |
| 734 read_buf_->set_offset(save_amount + additional_save_amount); | 730 read_buf_->set_offset(save_amount + additional_save_amount); |
| 735 } | 731 } |
| 736 read_buf_unused_offset_ = 0; | 732 read_buf_unused_offset_ = 0; |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 790 end_offset = 0; | 786 end_offset = 0; |
| 791 } | 787 } |
| 792 int rv = DoParseResponseHeaders(end_offset); | 788 int rv = DoParseResponseHeaders(end_offset); |
| 793 if (rv < 0) | 789 if (rv < 0) |
| 794 return rv; | 790 return rv; |
| 795 return result; | 791 return result; |
| 796 } | 792 } |
| 797 | 793 |
| 798 read_buf_->set_offset(read_buf_->offset() + result); | 794 read_buf_->set_offset(read_buf_->offset() + result); |
| 799 DCHECK_LE(read_buf_->offset(), read_buf_->capacity()); | 795 DCHECK_LE(read_buf_->offset(), read_buf_->capacity()); |
| 800 DCHECK_GE(result, 0); | 796 DCHECK_GE(result, 0); |
| 801 | 797 |
| 802 int end_of_header_offset = ParseResponseHeaders(); | 798 int end_of_header_offset = ParseResponseHeaders(); |
| 803 | 799 |
| 804 // Note: -1 is special, it indicates we haven't found the end of headers. | 800 // Note: -1 is special, it indicates we haven't found the end of headers. |
| 805 // Anything less than -1 is a net::Error, so we bail out. | 801 // Anything less than -1 is a net::Error, so we bail out. |
| 806 if (end_of_header_offset < -1) | 802 if (end_of_header_offset < -1) |
| 807 return end_of_header_offset; | 803 return end_of_header_offset; |
| 808 | 804 |
| 809 if (end_of_header_offset == -1) { | 805 if (end_of_header_offset == -1) { |
| 810 io_state_ = STATE_READ_HEADERS; | 806 io_state_ = STATE_READ_HEADERS; |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 878 return rv; | 874 return rv; |
| 879 return end_offset; | 875 return end_offset; |
| 880 } | 876 } |
| 881 | 877 |
| 882 int HttpStreamParser::DoParseResponseHeaders(int end_offset) { | 878 int HttpStreamParser::DoParseResponseHeaders(int end_offset) { |
| 883 scoped_refptr<HttpResponseHeaders> headers; | 879 scoped_refptr<HttpResponseHeaders> headers; |
| 884 DCHECK_EQ(0, read_buf_unused_offset_); | 880 DCHECK_EQ(0, read_buf_unused_offset_); |
| 885 | 881 |
| 886 if (response_header_start_offset_ >= 0) { | 882 if (response_header_start_offset_ >= 0) { |
| 887 received_bytes_ += end_offset; | 883 received_bytes_ += end_offset; |
| 888 headers = new HttpResponseHeaders(HttpUtil::AssembleRawHeaders( | 884 headers = new HttpResponseHeaders( |
| 889 read_buf_->StartOfBuffer(), end_offset)); | 885 HttpUtil::AssembleRawHeaders(read_buf_->StartOfBuffer(), end_offset)); |
| 890 } else { | 886 } else { |
| 891 // Enough data was read -- there is no status line. | 887 // Enough data was read -- there is no status line. |
| 892 headers = new HttpResponseHeaders(std::string("HTTP/0.9 200 OK")); | 888 headers = new HttpResponseHeaders(std::string("HTTP/0.9 200 OK")); |
| 893 } | 889 } |
| 894 | 890 |
| 895 // Check for multiple Content-Length headers with no Transfer-Encoding header. | 891 // Check for multiple Content-Length headers with no Transfer-Encoding header. |
| 896 // If they exist, and have distinct values, it's a potential response | 892 // If they exist, and have distinct values, it's a potential response |
| 897 // smuggling attack. | 893 // smuggling attack. |
| 898 if (!headers->HasHeader("Transfer-Encoding")) { | 894 if (!headers->HasHeader("Transfer-Encoding")) { |
| 899 if (HeadersContainMultipleCopiesOfField(*headers.get(), "Content-Length")) | 895 if (HeadersContainMultipleCopiesOfField(*headers.get(), "Content-Length")) |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1020 } | 1016 } |
| 1021 | 1017 |
| 1022 int HttpStreamParser::EncodeChunk(const base::StringPiece& payload, | 1018 int HttpStreamParser::EncodeChunk(const base::StringPiece& payload, |
| 1023 char* output, | 1019 char* output, |
| 1024 size_t output_size) { | 1020 size_t output_size) { |
| 1025 if (output_size < payload.size() + kChunkHeaderFooterSize) | 1021 if (output_size < payload.size() + kChunkHeaderFooterSize) |
| 1026 return ERR_INVALID_ARGUMENT; | 1022 return ERR_INVALID_ARGUMENT; |
| 1027 | 1023 |
| 1028 char* cursor = output; | 1024 char* cursor = output; |
| 1029 // Add the header. | 1025 // Add the header. |
| 1030 const int num_chars = base::snprintf(output, output_size, | 1026 const int num_chars = base::snprintf( |
| 1031 "%X\r\n", | 1027 output, output_size, "%X\r\n", static_cast<int>(payload.size())); |
| 1032 static_cast<int>(payload.size())); | |
| 1033 cursor += num_chars; | 1028 cursor += num_chars; |
| 1034 // Add the payload if any. | 1029 // Add the payload if any. |
| 1035 if (payload.size() > 0) { | 1030 if (payload.size() > 0) { |
| 1036 memcpy(cursor, payload.data(), payload.size()); | 1031 memcpy(cursor, payload.data(), payload.size()); |
| 1037 cursor += payload.size(); | 1032 cursor += payload.size(); |
| 1038 } | 1033 } |
| 1039 // Add the trailing CRLF. | 1034 // Add the trailing CRLF. |
| 1040 memcpy(cursor, "\r\n", 2); | 1035 memcpy(cursor, "\r\n", 2); |
| 1041 cursor += 2; | 1036 cursor += 2; |
| 1042 | 1037 |
| 1043 return cursor - output; | 1038 return cursor - output; |
| 1044 } | 1039 } |
| 1045 | 1040 |
| 1046 // static | 1041 // static |
| 1047 bool HttpStreamParser::ShouldMergeRequestHeadersAndBody( | 1042 bool HttpStreamParser::ShouldMergeRequestHeadersAndBody( |
| 1048 const std::string& request_headers, | 1043 const std::string& request_headers, |
| 1049 const UploadDataStream* request_body) { | 1044 const UploadDataStream* request_body) { |
| 1050 if (request_body != NULL && | 1045 if (request_body != NULL && |
| 1051 // IsInMemory() ensures that the request body is not chunked. | 1046 // IsInMemory() ensures that the request body is not chunked. |
| 1052 request_body->IsInMemory() && | 1047 request_body->IsInMemory() && |
| 1053 request_body->size() > 0) { | 1048 request_body->size() > 0) { |
| 1054 size_t merged_size = request_headers.size() + request_body->size(); | 1049 size_t merged_size = request_headers.size() + request_body->size(); |
| 1055 if (merged_size <= kMaxMergedHeaderAndBodySize) | 1050 if (merged_size <= kMaxMergedHeaderAndBodySize) |
| 1056 return true; | 1051 return true; |
| 1057 } | 1052 } |
| 1058 return false; | 1053 return false; |
| 1059 } | 1054 } |
| 1060 | 1055 |
| 1061 } // namespace net | 1056 } // namespace net |
| OLD | NEW |