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 |