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/string_util.h" | 9 #include "base/string_util.h" |
10 #include "base/values.h" | 10 #include "base/values.h" |
(...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
241 // If we have a small request body, then we'll merge with the headers into a | 241 // If we have a small request body, then we'll merge with the headers into a |
242 // single write. | 242 // single write. |
243 bool did_merge = false; | 243 bool did_merge = false; |
244 if (ShouldMergeRequestHeadersAndBody(request, request_->upload_data_stream)) { | 244 if (ShouldMergeRequestHeadersAndBody(request, request_->upload_data_stream)) { |
245 size_t merged_size = request.size() + request_->upload_data_stream->size(); | 245 size_t merged_size = request.size() + request_->upload_data_stream->size(); |
246 scoped_refptr<IOBuffer> merged_request_headers_and_body( | 246 scoped_refptr<IOBuffer> merged_request_headers_and_body( |
247 new IOBuffer(merged_size)); | 247 new IOBuffer(merged_size)); |
248 // We'll repurpose |request_headers_| to store the merged headers and | 248 // We'll repurpose |request_headers_| to store the merged headers and |
249 // body. | 249 // body. |
250 request_headers_ = new DrainableIOBuffer( | 250 request_headers_ = new DrainableIOBuffer( |
251 merged_request_headers_and_body, merged_size); | 251 merged_request_headers_and_body.get(), merged_size); |
252 | 252 |
253 memcpy(request_headers_->data(), request.data(), request.size()); | 253 memcpy(request_headers_->data(), request.data(), request.size()); |
254 request_headers_->DidConsume(request.size()); | 254 request_headers_->DidConsume(request.size()); |
255 | 255 |
256 size_t todo = request_->upload_data_stream->size(); | 256 size_t todo = request_->upload_data_stream->size(); |
257 while (todo) { | 257 while (todo) { |
258 int consumed = request_->upload_data_stream->Read(request_headers_, todo, | 258 int consumed = request_->upload_data_stream |
259 CompletionCallback()); | 259 ->Read(request_headers_.get(), todo, CompletionCallback()); |
260 DCHECK_GT(consumed, 0); // Read() won't fail if not chunked. | 260 DCHECK_GT(consumed, 0); // Read() won't fail if not chunked. |
261 request_headers_->DidConsume(consumed); | 261 request_headers_->DidConsume(consumed); |
262 todo -= consumed; | 262 todo -= consumed; |
263 } | 263 } |
264 DCHECK(request_->upload_data_stream->IsEOF()); | 264 DCHECK(request_->upload_data_stream->IsEOF()); |
265 // Reset the offset, so the buffer can be read from the beginning. | 265 // Reset the offset, so the buffer can be read from the beginning. |
266 request_headers_->SetOffset(0); | 266 request_headers_->SetOffset(0); |
267 did_merge = true; | 267 did_merge = true; |
268 | 268 |
269 net_log_.AddEvent( | 269 net_log_.AddEvent( |
270 NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_BODY, | 270 NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_BODY, |
271 base::Bind(&NetLogSendRequestBodyCallback, | 271 base::Bind(&NetLogSendRequestBodyCallback, |
272 request_->upload_data_stream->size(), | 272 request_->upload_data_stream->size(), |
273 false, /* not chunked */ | 273 false, /* not chunked */ |
274 true /* merged */)); | 274 true /* merged */)); |
275 } | 275 } |
276 | 276 |
277 if (!did_merge) { | 277 if (!did_merge) { |
278 // If we didn't merge the body with the headers, then |request_headers_| | 278 // If we didn't merge the body with the headers, then |request_headers_| |
279 // contains just the HTTP headers. | 279 // contains just the HTTP headers. |
280 scoped_refptr<StringIOBuffer> headers_io_buf(new StringIOBuffer(request)); | 280 scoped_refptr<StringIOBuffer> headers_io_buf(new StringIOBuffer(request)); |
281 request_headers_ = new DrainableIOBuffer(headers_io_buf, | 281 request_headers_ = |
282 headers_io_buf->size()); | 282 new DrainableIOBuffer(headers_io_buf.get(), headers_io_buf->size()); |
283 } | 283 } |
284 | 284 |
285 result = DoLoop(OK); | 285 result = DoLoop(OK); |
286 if (result == ERR_IO_PENDING) | 286 if (result == ERR_IO_PENDING) |
287 callback_ = callback; | 287 callback_ = callback; |
288 | 288 |
289 return result > 0 ? OK : result; | 289 return result > 0 ? OK : result; |
290 } | 290 } |
291 | 291 |
292 int HttpStreamParser::ReadResponseHeaders(const CompletionCallback& callback) { | 292 int HttpStreamParser::ReadResponseHeaders(const CompletionCallback& callback) { |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
415 | 415 |
416 int HttpStreamParser::DoSendHeaders(int result) { | 416 int HttpStreamParser::DoSendHeaders(int result) { |
417 request_headers_->DidConsume(result); | 417 request_headers_->DidConsume(result); |
418 int bytes_remaining = request_headers_->BytesRemaining(); | 418 int bytes_remaining = request_headers_->BytesRemaining(); |
419 if (bytes_remaining > 0) { | 419 if (bytes_remaining > 0) { |
420 // Record our best estimate of the 'request time' as the time when we send | 420 // Record our best estimate of the 'request time' as the time when we send |
421 // out the first bytes of the request headers. | 421 // out the first bytes of the request headers. |
422 if (bytes_remaining == request_headers_->size()) { | 422 if (bytes_remaining == request_headers_->size()) { |
423 response_->request_time = base::Time::Now(); | 423 response_->request_time = base::Time::Now(); |
424 } | 424 } |
425 result = connection_->socket()->Write(request_headers_, | 425 result = connection_->socket() |
426 bytes_remaining, | 426 ->Write(request_headers_.get(), bytes_remaining, io_callback_); |
427 io_callback_); | |
428 } else if (request_->upload_data_stream != NULL && | 427 } else if (request_->upload_data_stream != NULL && |
429 (request_->upload_data_stream->is_chunked() || | 428 (request_->upload_data_stream->is_chunked() || |
430 // !IsEOF() indicates that the body wasn't merged. | 429 // !IsEOF() indicates that the body wasn't merged. |
431 (request_->upload_data_stream->size() > 0 && | 430 (request_->upload_data_stream->size() > 0 && |
432 !request_->upload_data_stream->IsEOF()))) { | 431 !request_->upload_data_stream->IsEOF()))) { |
433 net_log_.AddEvent( | 432 net_log_.AddEvent( |
434 NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_BODY, | 433 NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_BODY, |
435 base::Bind(&NetLogSendRequestBodyCallback, | 434 base::Bind(&NetLogSendRequestBodyCallback, |
436 request_->upload_data_stream->size(), | 435 request_->upload_data_stream->size(), |
437 request_->upload_data_stream->is_chunked(), | 436 request_->upload_data_stream->is_chunked(), |
438 false /* not merged */)); | 437 false /* not merged */)); |
439 io_state_ = STATE_SENDING_BODY; | 438 io_state_ = STATE_SENDING_BODY; |
440 result = OK; | 439 result = OK; |
441 } else { | 440 } else { |
442 io_state_ = STATE_REQUEST_SENT; | 441 io_state_ = STATE_REQUEST_SENT; |
443 } | 442 } |
444 return result; | 443 return result; |
445 } | 444 } |
446 | 445 |
447 int HttpStreamParser::DoSendBody(int result) { | 446 int HttpStreamParser::DoSendBody(int result) { |
448 // |result| is the number of bytes sent from the last call to | 447 // |result| is the number of bytes sent from the last call to |
449 // DoSendBody(), or 0 (i.e. OK). | 448 // DoSendBody(), or 0 (i.e. OK). |
450 | 449 |
451 // Send the remaining data in the request body buffer. | 450 // Send the remaining data in the request body buffer. |
452 request_body_send_buf_->DidConsume(result); | 451 request_body_send_buf_->DidConsume(result); |
453 if (request_body_send_buf_->BytesRemaining() > 0) { | 452 if (request_body_send_buf_->BytesRemaining() > 0) { |
454 return connection_->socket()->Write( | 453 return connection_->socket() |
455 request_body_send_buf_, | 454 ->Write(request_body_send_buf_.get(), |
456 request_body_send_buf_->BytesRemaining(), | 455 request_body_send_buf_->BytesRemaining(), |
457 io_callback_); | 456 io_callback_); |
458 } | 457 } |
459 | 458 |
460 if (request_->upload_data_stream->is_chunked() && sent_last_chunk_) { | 459 if (request_->upload_data_stream->is_chunked() && sent_last_chunk_) { |
461 io_state_ = STATE_REQUEST_SENT; | 460 io_state_ = STATE_REQUEST_SENT; |
462 return OK; | 461 return OK; |
463 } | 462 } |
464 | 463 |
465 request_body_read_buf_->Clear(); | 464 request_body_read_buf_->Clear(); |
466 io_state_ = STATE_SEND_REQUEST_READING_BODY; | 465 io_state_ = STATE_SEND_REQUEST_READING_BODY; |
467 return request_->upload_data_stream->Read(request_body_read_buf_, | 466 return request_->upload_data_stream->Read(request_body_read_buf_.get(), |
468 request_body_read_buf_->capacity(), | 467 request_body_read_buf_->capacity(), |
469 io_callback_); | 468 io_callback_); |
470 } | 469 } |
471 | 470 |
472 int HttpStreamParser::DoSendRequestReadingBody(int result) { | 471 int HttpStreamParser::DoSendRequestReadingBody(int result) { |
473 // |result| is the result of read from the request body from the last call to | 472 // |result| is the result of read from the request body from the last call to |
474 // DoSendBody(). | 473 // DoSendBody(). |
475 DCHECK_GE(result, 0); // There won't be errors. | 474 DCHECK_GE(result, 0); // There won't be errors. |
476 | 475 |
477 // Chunked data needs to be encoded. | 476 // Chunked data needs to be encoded. |
(...skipping 28 matching lines...) Expand all Loading... |
506 io_state_ = STATE_READ_HEADERS_COMPLETE; | 505 io_state_ = STATE_READ_HEADERS_COMPLETE; |
507 | 506 |
508 // Grow the read buffer if necessary. | 507 // Grow the read buffer if necessary. |
509 if (read_buf_->RemainingCapacity() == 0) | 508 if (read_buf_->RemainingCapacity() == 0) |
510 read_buf_->SetCapacity(read_buf_->capacity() + kHeaderBufInitialSize); | 509 read_buf_->SetCapacity(read_buf_->capacity() + kHeaderBufInitialSize); |
511 | 510 |
512 // http://crbug.com/16371: We're seeing |user_buf_->data()| return NULL. | 511 // http://crbug.com/16371: We're seeing |user_buf_->data()| return NULL. |
513 // See if the user is passing in an IOBuffer with a NULL |data_|. | 512 // See if the user is passing in an IOBuffer with a NULL |data_|. |
514 CHECK(read_buf_->data()); | 513 CHECK(read_buf_->data()); |
515 | 514 |
516 return connection_->socket()->Read(read_buf_, | 515 return connection_->socket() |
517 read_buf_->RemainingCapacity(), | 516 ->Read(read_buf_.get(), read_buf_->RemainingCapacity(), io_callback_); |
518 io_callback_); | |
519 } | 517 } |
520 | 518 |
521 int HttpStreamParser::DoReadHeadersComplete(int result) { | 519 int HttpStreamParser::DoReadHeadersComplete(int result) { |
522 if (result == 0) | 520 if (result == 0) |
523 result = ERR_CONNECTION_CLOSED; | 521 result = ERR_CONNECTION_CLOSED; |
524 | 522 |
525 if (result < 0 && result != ERR_CONNECTION_CLOSED) { | 523 if (result < 0 && result != ERR_CONNECTION_CLOSED) { |
526 io_state_ = STATE_DONE; | 524 io_state_ = STATE_DONE; |
527 return result; | 525 return result; |
528 } | 526 } |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
643 read_buf_->SetCapacity(0); | 641 read_buf_->SetCapacity(0); |
644 read_buf_unused_offset_ = 0; | 642 read_buf_unused_offset_ = 0; |
645 } | 643 } |
646 } | 644 } |
647 | 645 |
648 // Check to see if we're done reading. | 646 // Check to see if we're done reading. |
649 if (IsResponseBodyComplete()) | 647 if (IsResponseBodyComplete()) |
650 return 0; | 648 return 0; |
651 | 649 |
652 DCHECK_EQ(0, read_buf_->offset()); | 650 DCHECK_EQ(0, read_buf_->offset()); |
653 return connection_->socket()->Read(user_read_buf_, user_read_buf_len_, | 651 return connection_->socket() |
654 io_callback_); | 652 ->Read(user_read_buf_.get(), user_read_buf_len_, io_callback_); |
655 } | 653 } |
656 | 654 |
657 int HttpStreamParser::DoReadBodyComplete(int result) { | 655 int HttpStreamParser::DoReadBodyComplete(int result) { |
658 // When the connection is closed, there are numerous ways to interpret it. | 656 // When the connection is closed, there are numerous ways to interpret it. |
659 // | 657 // |
660 // - If a Content-Length header is present and the body contains exactly that | 658 // - If a Content-Length header is present and the body contains exactly that |
661 // number of bytes at connection close, the response is successful. | 659 // number of bytes at connection close, the response is successful. |
662 // | 660 // |
663 // - If a Content-Length header is present and the body contains fewer bytes | 661 // - If a Content-Length header is present and the body contains fewer bytes |
664 // than promised by the header at connection close, it may indicate that | 662 // than promised by the header at connection close, it may indicate that |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
788 read_buf_->StartOfBuffer() + read_buf_unused_offset_, end_offset)); | 786 read_buf_->StartOfBuffer() + read_buf_unused_offset_, end_offset)); |
789 } else { | 787 } else { |
790 // Enough data was read -- there is no status line. | 788 // Enough data was read -- there is no status line. |
791 headers = new HttpResponseHeaders(std::string("HTTP/0.9 200 OK")); | 789 headers = new HttpResponseHeaders(std::string("HTTP/0.9 200 OK")); |
792 } | 790 } |
793 | 791 |
794 // Check for multiple Content-Length headers with no Transfer-Encoding header. | 792 // Check for multiple Content-Length headers with no Transfer-Encoding header. |
795 // If they exist, and have distinct values, it's a potential response | 793 // If they exist, and have distinct values, it's a potential response |
796 // smuggling attack. | 794 // smuggling attack. |
797 if (!headers->HasHeader("Transfer-Encoding")) { | 795 if (!headers->HasHeader("Transfer-Encoding")) { |
798 if (HeadersContainMultipleCopiesOfField(*headers, "Content-Length")) | 796 if (HeadersContainMultipleCopiesOfField(*headers.get(), "Content-Length")) |
799 return ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH; | 797 return ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH; |
800 } | 798 } |
801 | 799 |
802 // Check for multiple Content-Disposition or Location headers. If they exist, | 800 // Check for multiple Content-Disposition or Location headers. If they exist, |
803 // it's also a potential response smuggling attack. | 801 // it's also a potential response smuggling attack. |
804 if (HeadersContainMultipleCopiesOfField(*headers, "Content-Disposition")) | 802 if (HeadersContainMultipleCopiesOfField(*headers.get(), |
| 803 "Content-Disposition")) |
805 return ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION; | 804 return ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION; |
806 if (HeadersContainMultipleCopiesOfField(*headers, "Location")) | 805 if (HeadersContainMultipleCopiesOfField(*headers.get(), "Location")) |
807 return ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION; | 806 return ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION; |
808 | 807 |
809 response_->headers = headers; | 808 response_->headers = headers; |
810 response_->connection_info = HttpResponseInfo::CONNECTION_INFO_HTTP1; | 809 response_->connection_info = HttpResponseInfo::CONNECTION_INFO_HTTP1; |
811 response_->vary_data.Init(*request_, *response_->headers); | 810 response_->vary_data.Init(*request_, *response_->headers.get()); |
812 DVLOG(1) << __FUNCTION__ << "()" | 811 DVLOG(1) << __FUNCTION__ << "()" |
813 << " content_length = \"" | 812 << " content_length = \"" << response_->headers->GetContentLength() |
814 << response_->headers->GetContentLength() << "\n\"" | 813 << "\n\"" |
815 << " headers = \"" << GetResponseHeaderLines(*response_->headers) | 814 << " headers = \"" |
816 << "\""; | 815 << GetResponseHeaderLines(*response_->headers.get()) << "\""; |
817 return OK; | 816 return OK; |
818 } | 817 } |
819 | 818 |
820 void HttpStreamParser::CalculateResponseBodySize() { | 819 void HttpStreamParser::CalculateResponseBodySize() { |
821 // Figure how to determine EOF: | 820 // Figure how to determine EOF: |
822 | 821 |
823 // For certain responses, we know the content length is always 0. From | 822 // For certain responses, we know the content length is always 0. From |
824 // RFC 2616 Section 4.3 Message Body: | 823 // RFC 2616 Section 4.3 Message Body: |
825 // | 824 // |
826 // For response messages, whether or not a message-body is included with | 825 // For response messages, whether or not a message-body is included with |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
947 request_body->IsInMemory() && | 946 request_body->IsInMemory() && |
948 request_body->size() > 0) { | 947 request_body->size() > 0) { |
949 size_t merged_size = request_headers.size() + request_body->size(); | 948 size_t merged_size = request_headers.size() + request_body->size(); |
950 if (merged_size <= kMaxMergedHeaderAndBodySize) | 949 if (merged_size <= kMaxMergedHeaderAndBodySize) |
951 return true; | 950 return true; |
952 } | 951 } |
953 return false; | 952 return false; |
954 } | 953 } |
955 | 954 |
956 } // namespace net | 955 } // namespace net |
OLD | NEW |