| 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/profiler/scoped_tracker.h" | 10 #include "base/profiler/scoped_tracker.h" |
| (...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 356 | 356 |
| 357 return result; | 357 return result; |
| 358 } | 358 } |
| 359 | 359 |
| 360 void HttpStreamParser::OnIOComplete(int result) { | 360 void HttpStreamParser::OnIOComplete(int result) { |
| 361 result = DoLoop(result); | 361 result = DoLoop(result); |
| 362 | 362 |
| 363 // The client callback can do anything, including destroying this class, | 363 // The client callback can do anything, including destroying this class, |
| 364 // so any pending callback must be issued after everything else is done. | 364 // so any pending callback must be issued after everything else is done. |
| 365 if (result != ERR_IO_PENDING && !callback_.is_null()) { | 365 if (result != ERR_IO_PENDING && !callback_.is_null()) { |
| 366 // TODO(vadimt): Remove ScopedTracker below once crbug.com/424359 is fixed. | |
| 367 tracked_objects::ScopedTracker tracking_profile( | |
| 368 FROM_HERE_WITH_EXPLICIT_FUNCTION( | |
| 369 "424359 HttpStreamParser::OnIOComplete callback")); | |
| 370 | |
| 371 CompletionCallback c = callback_; | 366 CompletionCallback c = callback_; |
| 372 callback_.Reset(); | 367 callback_.Reset(); |
| 373 c.Run(result); | 368 c.Run(result); |
| 374 } | 369 } |
| 375 } | 370 } |
| 376 | 371 |
| 377 int HttpStreamParser::DoLoop(int result) { | 372 int HttpStreamParser::DoLoop(int result) { |
| 378 // TODO(vadimt): Remove ScopedTracker below once crbug.com/424359 is fixed. | 373 // TODO(pkasting): Remove ScopedTracker below once crbug.com/424359 is fixed. |
| 379 tracked_objects::ScopedTracker tracking_profile( | 374 tracked_objects::ScopedTracker tracking_profile( |
| 380 FROM_HERE_WITH_EXPLICIT_FUNCTION("424359 HttpStreamParser::DoLoop")); | 375 FROM_HERE_WITH_EXPLICIT_FUNCTION("424359 HttpStreamParser::DoLoop")); |
| 381 | 376 |
| 382 do { | 377 do { |
| 383 DCHECK_NE(ERR_IO_PENDING, result); | 378 DCHECK_NE(ERR_IO_PENDING, result); |
| 384 DCHECK_NE(STATE_DONE, io_state_); | 379 DCHECK_NE(STATE_DONE, io_state_); |
| 385 DCHECK_NE(STATE_NONE, io_state_); | 380 DCHECK_NE(STATE_NONE, io_state_); |
| 386 State state = io_state_; | 381 State state = io_state_; |
| 387 io_state_ = STATE_NONE; | 382 io_state_ = STATE_NONE; |
| 388 switch (state) { | 383 switch (state) { |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 424 NOTREACHED(); | 419 NOTREACHED(); |
| 425 break; | 420 break; |
| 426 } | 421 } |
| 427 } while (result != ERR_IO_PENDING && | 422 } while (result != ERR_IO_PENDING && |
| 428 (io_state_ != STATE_DONE && io_state_ != STATE_NONE)); | 423 (io_state_ != STATE_DONE && io_state_ != STATE_NONE)); |
| 429 | 424 |
| 430 return result; | 425 return result; |
| 431 } | 426 } |
| 432 | 427 |
| 433 int HttpStreamParser::DoSendHeaders() { | 428 int HttpStreamParser::DoSendHeaders() { |
| 429 // TODO(pkasting): Remove ScopedTracker below once crbug.com/424359 is fixed. |
| 430 tracked_objects::ScopedTracker tracking_profile( |
| 431 FROM_HERE_WITH_EXPLICIT_FUNCTION( |
| 432 "424359 HttpStreamParser::DoSendHeaders")); |
| 433 |
| 434 int bytes_remaining = request_headers_->BytesRemaining(); | 434 int bytes_remaining = request_headers_->BytesRemaining(); |
| 435 DCHECK_GT(bytes_remaining, 0); | 435 DCHECK_GT(bytes_remaining, 0); |
| 436 | 436 |
| 437 // Record our best estimate of the 'request time' as the time when we send | 437 // Record our best estimate of the 'request time' as the time when we send |
| 438 // out the first bytes of the request headers. | 438 // out the first bytes of the request headers. |
| 439 if (bytes_remaining == request_headers_->size()) | 439 if (bytes_remaining == request_headers_->size()) |
| 440 response_->request_time = base::Time::Now(); | 440 response_->request_time = base::Time::Now(); |
| 441 | 441 |
| 442 io_state_ = STATE_SEND_HEADERS_COMPLETE; | 442 io_state_ = STATE_SEND_HEADERS_COMPLETE; |
| 443 return connection_->socket() | 443 return connection_->socket() |
| 444 ->Write(request_headers_.get(), bytes_remaining, io_callback_); | 444 ->Write(request_headers_.get(), bytes_remaining, io_callback_); |
| 445 } | 445 } |
| 446 | 446 |
| 447 int HttpStreamParser::DoSendHeadersComplete(int result) { | 447 int HttpStreamParser::DoSendHeadersComplete(int result) { |
| 448 // TODO(pkasting): Remove ScopedTracker below once crbug.com/424359 is fixed. |
| 449 tracked_objects::ScopedTracker tracking_profile( |
| 450 FROM_HERE_WITH_EXPLICIT_FUNCTION( |
| 451 "424359 HttpStreamParser::DoSendHeadersComplete")); |
| 452 |
| 448 if (result < 0) { | 453 if (result < 0) { |
| 449 // In the unlikely case that the headers and body were merged, all the | 454 // In the unlikely case that the headers and body were merged, all the |
| 450 // the headers were sent, but not all of the body way, and |result| is | 455 // the headers were sent, but not all of the body way, and |result| is |
| 451 // an error that this should try reading after, stash the error for now and | 456 // an error that this should try reading after, stash the error for now and |
| 452 // act like the request was successfully sent. | 457 // act like the request was successfully sent. |
| 453 if (request_headers_->BytesConsumed() >= request_headers_length_ && | 458 if (request_headers_->BytesConsumed() >= request_headers_length_ && |
| 454 ShouldTryReadingOnUploadError(result)) { | 459 ShouldTryReadingOnUploadError(result)) { |
| 455 upload_error_ = result; | 460 upload_error_ = result; |
| 456 return OK; | 461 return OK; |
| 457 } | 462 } |
| (...skipping 19 matching lines...) Expand all Loading... |
| 477 false /* not merged */)); | 482 false /* not merged */)); |
| 478 io_state_ = STATE_SEND_BODY; | 483 io_state_ = STATE_SEND_BODY; |
| 479 return OK; | 484 return OK; |
| 480 } | 485 } |
| 481 | 486 |
| 482 // Finished sending the request. | 487 // Finished sending the request. |
| 483 return OK; | 488 return OK; |
| 484 } | 489 } |
| 485 | 490 |
| 486 int HttpStreamParser::DoSendBody() { | 491 int HttpStreamParser::DoSendBody() { |
| 492 // TODO(pkasting): Remove ScopedTracker below once crbug.com/424359 is fixed. |
| 493 tracked_objects::ScopedTracker tracking_profile( |
| 494 FROM_HERE_WITH_EXPLICIT_FUNCTION("424359 HttpStreamParser::DoSendBody")); |
| 495 |
| 487 if (request_body_send_buf_->BytesRemaining() > 0) { | 496 if (request_body_send_buf_->BytesRemaining() > 0) { |
| 488 io_state_ = STATE_SEND_BODY_COMPLETE; | 497 io_state_ = STATE_SEND_BODY_COMPLETE; |
| 489 return connection_->socket() | 498 return connection_->socket() |
| 490 ->Write(request_body_send_buf_.get(), | 499 ->Write(request_body_send_buf_.get(), |
| 491 request_body_send_buf_->BytesRemaining(), | 500 request_body_send_buf_->BytesRemaining(), |
| 492 io_callback_); | 501 io_callback_); |
| 493 } | 502 } |
| 494 | 503 |
| 495 if (request_->upload_data_stream->is_chunked() && sent_last_chunk_) { | 504 if (request_->upload_data_stream->is_chunked() && sent_last_chunk_) { |
| 496 // Finished sending the request. | 505 // Finished sending the request. |
| 497 return OK; | 506 return OK; |
| 498 } | 507 } |
| 499 | 508 |
| 500 request_body_read_buf_->Clear(); | 509 request_body_read_buf_->Clear(); |
| 501 io_state_ = STATE_SEND_REQUEST_READ_BODY_COMPLETE; | 510 io_state_ = STATE_SEND_REQUEST_READ_BODY_COMPLETE; |
| 502 return request_->upload_data_stream->Read(request_body_read_buf_.get(), | 511 return request_->upload_data_stream->Read(request_body_read_buf_.get(), |
| 503 request_body_read_buf_->capacity(), | 512 request_body_read_buf_->capacity(), |
| 504 io_callback_); | 513 io_callback_); |
| 505 } | 514 } |
| 506 | 515 |
| 507 int HttpStreamParser::DoSendBodyComplete(int result) { | 516 int HttpStreamParser::DoSendBodyComplete(int result) { |
| 517 // TODO(pkasting): Remove ScopedTracker below once crbug.com/424359 is fixed. |
| 518 tracked_objects::ScopedTracker tracking_profile( |
| 519 FROM_HERE_WITH_EXPLICIT_FUNCTION( |
| 520 "424359 HttpStreamParser::DoSendBodyComplete")); |
| 521 |
| 508 if (result < 0) { | 522 if (result < 0) { |
| 509 // If |result| is an error that this should try reading after, stash the | 523 // If |result| is an error that this should try reading after, stash the |
| 510 // error for now and act like the request was successfully sent. | 524 // error for now and act like the request was successfully sent. |
| 511 if (ShouldTryReadingOnUploadError(result)) { | 525 if (ShouldTryReadingOnUploadError(result)) { |
| 512 upload_error_ = result; | 526 upload_error_ = result; |
| 513 return OK; | 527 return OK; |
| 514 } | 528 } |
| 515 return result; | 529 return result; |
| 516 } | 530 } |
| 517 | 531 |
| 518 request_body_send_buf_->DidConsume(result); | 532 request_body_send_buf_->DidConsume(result); |
| 519 | 533 |
| 520 io_state_ = STATE_SEND_BODY; | 534 io_state_ = STATE_SEND_BODY; |
| 521 return OK; | 535 return OK; |
| 522 } | 536 } |
| 523 | 537 |
| 524 int HttpStreamParser::DoSendRequestReadBodyComplete(int result) { | 538 int HttpStreamParser::DoSendRequestReadBodyComplete(int result) { |
| 539 // TODO(pkasting): Remove ScopedTracker below once crbug.com/424359 is fixed. |
| 540 tracked_objects::ScopedTracker tracking_profile( |
| 541 FROM_HERE_WITH_EXPLICIT_FUNCTION( |
| 542 "424359 HttpStreamParser::DoSendRequestReadBodyComplete")); |
| 543 |
| 525 // |result| is the result of read from the request body from the last call to | 544 // |result| is the result of read from the request body from the last call to |
| 526 // DoSendBody(). | 545 // DoSendBody(). |
| 527 DCHECK_GE(result, 0); // There won't be errors. | 546 DCHECK_GE(result, 0); // There won't be errors. |
| 528 | 547 |
| 529 // Chunked data needs to be encoded. | 548 // Chunked data needs to be encoded. |
| 530 if (request_->upload_data_stream->is_chunked()) { | 549 if (request_->upload_data_stream->is_chunked()) { |
| 531 if (result == 0) { // Reached the end. | 550 if (result == 0) { // Reached the end. |
| 532 DCHECK(request_->upload_data_stream->IsEOF()); | 551 DCHECK(request_->upload_data_stream->IsEOF()); |
| 533 sent_last_chunk_ = true; | 552 sent_last_chunk_ = true; |
| 534 } | 553 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 548 // Finished sending the request. | 567 // Finished sending the request. |
| 549 } else if (result > 0) { | 568 } else if (result > 0) { |
| 550 request_body_send_buf_->DidAppend(result); | 569 request_body_send_buf_->DidAppend(result); |
| 551 result = 0; | 570 result = 0; |
| 552 io_state_ = STATE_SEND_BODY; | 571 io_state_ = STATE_SEND_BODY; |
| 553 } | 572 } |
| 554 return result; | 573 return result; |
| 555 } | 574 } |
| 556 | 575 |
| 557 int HttpStreamParser::DoReadHeaders() { | 576 int HttpStreamParser::DoReadHeaders() { |
| 577 // TODO(pkasting): Remove ScopedTracker below once crbug.com/424359 is fixed. |
| 578 tracked_objects::ScopedTracker tracking_profile( |
| 579 FROM_HERE_WITH_EXPLICIT_FUNCTION( |
| 580 "424359 HttpStreamParser::DoReadHeaders")); |
| 581 |
| 558 io_state_ = STATE_READ_HEADERS_COMPLETE; | 582 io_state_ = STATE_READ_HEADERS_COMPLETE; |
| 559 | 583 |
| 560 // Grow the read buffer if necessary. | 584 // Grow the read buffer if necessary. |
| 561 if (read_buf_->RemainingCapacity() == 0) | 585 if (read_buf_->RemainingCapacity() == 0) |
| 562 read_buf_->SetCapacity(read_buf_->capacity() + kHeaderBufInitialSize); | 586 read_buf_->SetCapacity(read_buf_->capacity() + kHeaderBufInitialSize); |
| 563 | 587 |
| 564 // http://crbug.com/16371: We're seeing |user_buf_->data()| return NULL. | 588 // http://crbug.com/16371: We're seeing |user_buf_->data()| return NULL. |
| 565 // See if the user is passing in an IOBuffer with a NULL |data_|. | 589 // See if the user is passing in an IOBuffer with a NULL |data_|. |
| 566 CHECK(read_buf_->data()); | 590 CHECK(read_buf_->data()); |
| 567 | 591 |
| 568 return connection_->socket() | 592 return connection_->socket() |
| 569 ->Read(read_buf_.get(), read_buf_->RemainingCapacity(), io_callback_); | 593 ->Read(read_buf_.get(), read_buf_->RemainingCapacity(), io_callback_); |
| 570 } | 594 } |
| 571 | 595 |
| 572 int HttpStreamParser::DoReadHeadersComplete(int result) { | 596 int HttpStreamParser::DoReadHeadersComplete(int result) { |
| 597 // TODO(pkasting): Remove ScopedTracker below once crbug.com/424359 is fixed. |
| 598 tracked_objects::ScopedTracker tracking_profile( |
| 599 FROM_HERE_WITH_EXPLICIT_FUNCTION( |
| 600 "424359 HttpStreamParser::DoReadHeadersComplete")); |
| 601 |
| 573 result = HandleReadHeaderResult(result); | 602 result = HandleReadHeaderResult(result); |
| 574 | 603 |
| 575 // TODO(mmenke): The code below is ugly and hacky. A much better and more | 604 // TODO(mmenke): The code below is ugly and hacky. A much better and more |
| 576 // flexible long term solution would be to separate out the read and write | 605 // flexible long term solution would be to separate out the read and write |
| 577 // loops, though this would involve significant changes, both here and | 606 // loops, though this would involve significant changes, both here and |
| 578 // elsewhere (WebSockets, for instance). | 607 // elsewhere (WebSockets, for instance). |
| 579 | 608 |
| 580 // If still reading the headers, or there was no error uploading the request | 609 // If still reading the headers, or there was no error uploading the request |
| 581 // body, just return the result. | 610 // body, just return the result. |
| 582 if (io_state_ == STATE_READ_HEADERS || upload_error_ == OK) | 611 if (io_state_ == STATE_READ_HEADERS || upload_error_ == OK) |
| (...skipping 27 matching lines...) Expand all Loading... |
| 610 // make sure the consumer has some indication there was an error. | 639 // make sure the consumer has some indication there was an error. |
| 611 | 640 |
| 612 // Nothing else to do. | 641 // Nothing else to do. |
| 613 io_state_ = STATE_DONE; | 642 io_state_ = STATE_DONE; |
| 614 // Don't let caller see the headers. | 643 // Don't let caller see the headers. |
| 615 response_->headers = NULL; | 644 response_->headers = NULL; |
| 616 return upload_error_; | 645 return upload_error_; |
| 617 } | 646 } |
| 618 | 647 |
| 619 int HttpStreamParser::DoReadBody() { | 648 int HttpStreamParser::DoReadBody() { |
| 649 // TODO(pkasting): Remove ScopedTracker below once crbug.com/424359 is fixed. |
| 650 tracked_objects::ScopedTracker tracking_profile( |
| 651 FROM_HERE_WITH_EXPLICIT_FUNCTION("424359 HttpStreamParser::DoReadBody")); |
| 652 |
| 620 io_state_ = STATE_READ_BODY_COMPLETE; | 653 io_state_ = STATE_READ_BODY_COMPLETE; |
| 621 | 654 |
| 622 // There may be some data left over from reading the response headers. | 655 // There may be some data left over from reading the response headers. |
| 623 if (read_buf_->offset()) { | 656 if (read_buf_->offset()) { |
| 624 int available = read_buf_->offset() - read_buf_unused_offset_; | 657 int available = read_buf_->offset() - read_buf_unused_offset_; |
| 625 if (available) { | 658 if (available) { |
| 626 CHECK_GT(available, 0); | 659 CHECK_GT(available, 0); |
| 627 int bytes_from_buffer = std::min(available, user_read_buf_len_); | 660 int bytes_from_buffer = std::min(available, user_read_buf_len_); |
| 628 memcpy(user_read_buf_->data(), | 661 memcpy(user_read_buf_->data(), |
| 629 read_buf_->StartOfBuffer() + read_buf_unused_offset_, | 662 read_buf_->StartOfBuffer() + read_buf_unused_offset_, |
| (...skipping 13 matching lines...) Expand all Loading... |
| 643 // Check to see if we're done reading. | 676 // Check to see if we're done reading. |
| 644 if (IsResponseBodyComplete()) | 677 if (IsResponseBodyComplete()) |
| 645 return 0; | 678 return 0; |
| 646 | 679 |
| 647 DCHECK_EQ(0, read_buf_->offset()); | 680 DCHECK_EQ(0, read_buf_->offset()); |
| 648 return connection_->socket() | 681 return connection_->socket() |
| 649 ->Read(user_read_buf_.get(), user_read_buf_len_, io_callback_); | 682 ->Read(user_read_buf_.get(), user_read_buf_len_, io_callback_); |
| 650 } | 683 } |
| 651 | 684 |
| 652 int HttpStreamParser::DoReadBodyComplete(int result) { | 685 int HttpStreamParser::DoReadBodyComplete(int result) { |
| 686 // TODO(pkasting): Remove ScopedTracker below once crbug.com/424359 is fixed. |
| 687 tracked_objects::ScopedTracker tracking_profile( |
| 688 FROM_HERE_WITH_EXPLICIT_FUNCTION( |
| 689 "424359 HttpStreamParser::DoReadBodyComplete")); |
| 690 |
| 653 // When the connection is closed, there are numerous ways to interpret it. | 691 // When the connection is closed, there are numerous ways to interpret it. |
| 654 // | 692 // |
| 655 // - If a Content-Length header is present and the body contains exactly that | 693 // - If a Content-Length header is present and the body contains exactly that |
| 656 // number of bytes at connection close, the response is successful. | 694 // number of bytes at connection close, the response is successful. |
| 657 // | 695 // |
| 658 // - If a Content-Length header is present and the body contains fewer bytes | 696 // - If a Content-Length header is present and the body contains fewer bytes |
| 659 // than promised by the header at connection close, it may indicate that | 697 // than promised by the header at connection close, it may indicate that |
| 660 // the connection was closed prematurely, or it may indicate that the | 698 // the connection was closed prematurely, or it may indicate that the |
| 661 // server sent an invalid Content-Length header. Unfortunately, the invalid | 699 // server sent an invalid Content-Length header. Unfortunately, the invalid |
| 662 // Content-Length header case does occur in practice and other browsers are | 700 // Content-Length header case does occur in practice and other browsers are |
| (...skipping 392 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1055 request_body->IsInMemory() && | 1093 request_body->IsInMemory() && |
| 1056 request_body->size() > 0) { | 1094 request_body->size() > 0) { |
| 1057 uint64 merged_size = request_headers.size() + request_body->size(); | 1095 uint64 merged_size = request_headers.size() + request_body->size(); |
| 1058 if (merged_size <= kMaxMergedHeaderAndBodySize) | 1096 if (merged_size <= kMaxMergedHeaderAndBodySize) |
| 1059 return true; | 1097 return true; |
| 1060 } | 1098 } |
| 1061 return false; | 1099 return false; |
| 1062 } | 1100 } |
| 1063 | 1101 |
| 1064 } // namespace net | 1102 } // namespace net |
| OLD | NEW |