http_response_body_drainer.cc 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  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
  3. // found in the LICENSE file.
  4. #include "net/http/http_response_body_drainer.h"
  5. #include "base/bind.h"
  6. #include "base/check_op.h"
  7. #include "base/compiler_specific.h"
  8. #include "base/memory/ptr_util.h"
  9. #include "base/notreached.h"
  10. #include "net/base/io_buffer.h"
  11. #include "net/base/net_errors.h"
  12. #include "net/http/http_network_session.h"
  13. #include "net/http/http_stream.h"
  14. namespace net {
  15. const int HttpResponseBodyDrainer::kDrainBodyBufferSize;
  16. const int HttpResponseBodyDrainer::kTimeoutInSeconds;
  17. HttpResponseBodyDrainer::HttpResponseBodyDrainer(HttpStream* stream)
  18. : stream_(stream) {}
  19. HttpResponseBodyDrainer::~HttpResponseBodyDrainer() = default;
  20. void HttpResponseBodyDrainer::Start(HttpNetworkSession* session) {
  21. session_ = session;
  22. read_buf_ = base::MakeRefCounted<IOBuffer>(kDrainBodyBufferSize);
  23. next_state_ = STATE_DRAIN_RESPONSE_BODY;
  24. int rv = DoLoop(OK);
  25. if (rv == ERR_IO_PENDING) {
  26. timer_.Start(FROM_HERE, base::Seconds(kTimeoutInSeconds), this,
  27. &HttpResponseBodyDrainer::OnTimerFired);
  28. return;
  29. }
  30. Finish(rv);
  31. }
  32. int HttpResponseBodyDrainer::DoLoop(int result) {
  33. DCHECK_NE(next_state_, STATE_NONE);
  34. int rv = result;
  35. do {
  36. State state = next_state_;
  37. next_state_ = STATE_NONE;
  38. switch (state) {
  39. case STATE_DRAIN_RESPONSE_BODY:
  40. DCHECK_EQ(OK, rv);
  41. rv = DoDrainResponseBody();
  42. break;
  43. case STATE_DRAIN_RESPONSE_BODY_COMPLETE:
  44. rv = DoDrainResponseBodyComplete(rv);
  45. break;
  46. default:
  47. NOTREACHED() << "bad state";
  48. rv = ERR_UNEXPECTED;
  49. break;
  50. }
  51. } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
  52. return rv;
  53. }
  54. int HttpResponseBodyDrainer::DoDrainResponseBody() {
  55. next_state_ = STATE_DRAIN_RESPONSE_BODY_COMPLETE;
  56. return stream_->ReadResponseBody(
  57. read_buf_.get(), kDrainBodyBufferSize - total_read_,
  58. base::BindOnce(&HttpResponseBodyDrainer::OnIOComplete,
  59. base::Unretained(this)));
  60. }
  61. int HttpResponseBodyDrainer::DoDrainResponseBodyComplete(int result) {
  62. DCHECK_NE(ERR_IO_PENDING, result);
  63. if (result < 0)
  64. return result;
  65. total_read_ += result;
  66. if (stream_->IsResponseBodyComplete())
  67. return OK;
  68. DCHECK_LE(total_read_, kDrainBodyBufferSize);
  69. if (total_read_ >= kDrainBodyBufferSize)
  70. return ERR_RESPONSE_BODY_TOO_BIG_TO_DRAIN;
  71. if (result == 0)
  72. return ERR_CONNECTION_CLOSED;
  73. next_state_ = STATE_DRAIN_RESPONSE_BODY;
  74. return OK;
  75. }
  76. void HttpResponseBodyDrainer::OnIOComplete(int result) {
  77. int rv = DoLoop(result);
  78. if (rv != ERR_IO_PENDING) {
  79. timer_.Stop();
  80. Finish(rv);
  81. }
  82. }
  83. void HttpResponseBodyDrainer::OnTimerFired() {
  84. Finish(ERR_TIMED_OUT);
  85. }
  86. void HttpResponseBodyDrainer::Finish(int result) {
  87. DCHECK_NE(ERR_IO_PENDING, result);
  88. if (result < 0 || !stream_->CanReuseConnection()) {
  89. stream_->Close(true /* no keep-alive */);
  90. } else {
  91. DCHECK_EQ(OK, result);
  92. stream_->Close(false /* keep-alive */);
  93. }
  94. session_->RemoveResponseDrainer(this);
  95. }
  96. } // namespace net