Clean up MFYI by adding suppressions for new bugs
[chromium-blink-merge.git] / net / http / http_response_body_drainer.cc
bloba1ba35ad31e49125d5f2d593ad8d042cffaa1bd9
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.
5 #include "net/http/http_response_body_drainer.h"
7 #include "base/compiler_specific.h"
8 #include "base/logging.h"
9 #include "net/base/io_buffer.h"
10 #include "net/base/net_errors.h"
11 #include "net/http/http_network_session.h"
12 #include "net/http/http_stream_base.h"
14 namespace net {
16 HttpResponseBodyDrainer::HttpResponseBodyDrainer(HttpStreamBase* stream)
17 : read_size_(0),
18 stream_(stream),
19 next_state_(STATE_NONE),
20 total_read_(0),
21 session_(NULL) {}
23 HttpResponseBodyDrainer::~HttpResponseBodyDrainer() {}
25 void HttpResponseBodyDrainer::Start(HttpNetworkSession* session) {
26 StartWithSize(session, kDrainBodyBufferSize);
29 void HttpResponseBodyDrainer::StartWithSize(HttpNetworkSession* session,
30 int num_bytes_to_drain) {
31 DCHECK_LE(0, num_bytes_to_drain);
32 // TODO(simonjam): Consider raising this limit if we're pipelining. If we have
33 // a bunch of responses in the pipeline, we should be less willing to give up
34 // while draining.
35 if (num_bytes_to_drain > kDrainBodyBufferSize) {
36 Finish(ERR_RESPONSE_BODY_TOO_BIG_TO_DRAIN);
37 return;
38 } else if (num_bytes_to_drain == 0) {
39 Finish(OK);
40 return;
43 read_size_ = num_bytes_to_drain;
44 read_buf_ = new IOBuffer(read_size_);
45 next_state_ = STATE_DRAIN_RESPONSE_BODY;
46 int rv = DoLoop(OK);
48 if (rv == ERR_IO_PENDING) {
49 timer_.Start(FROM_HERE,
50 base::TimeDelta::FromSeconds(kTimeoutInSeconds),
51 this,
52 &HttpResponseBodyDrainer::OnTimerFired);
53 session_ = session;
54 session->AddResponseDrainer(this);
55 return;
58 Finish(rv);
61 int HttpResponseBodyDrainer::DoLoop(int result) {
62 DCHECK_NE(next_state_, STATE_NONE);
64 int rv = result;
65 do {
66 State state = next_state_;
67 next_state_ = STATE_NONE;
68 switch (state) {
69 case STATE_DRAIN_RESPONSE_BODY:
70 DCHECK_EQ(OK, rv);
71 rv = DoDrainResponseBody();
72 break;
73 case STATE_DRAIN_RESPONSE_BODY_COMPLETE:
74 rv = DoDrainResponseBodyComplete(rv);
75 break;
76 default:
77 NOTREACHED() << "bad state";
78 rv = ERR_UNEXPECTED;
79 break;
81 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
83 return rv;
86 int HttpResponseBodyDrainer::DoDrainResponseBody() {
87 next_state_ = STATE_DRAIN_RESPONSE_BODY_COMPLETE;
89 return stream_->ReadResponseBody(
90 read_buf_.get(),
91 read_size_ - total_read_,
92 base::Bind(&HttpResponseBodyDrainer::OnIOComplete,
93 base::Unretained(this)));
96 int HttpResponseBodyDrainer::DoDrainResponseBodyComplete(int result) {
97 DCHECK_NE(ERR_IO_PENDING, result);
99 if (result < 0)
100 return result;
102 total_read_ += result;
103 if (stream_->IsResponseBodyComplete())
104 return OK;
106 DCHECK_LE(total_read_, kDrainBodyBufferSize);
107 if (total_read_ >= kDrainBodyBufferSize)
108 return ERR_RESPONSE_BODY_TOO_BIG_TO_DRAIN;
110 if (result == 0)
111 return ERR_CONNECTION_CLOSED;
113 next_state_ = STATE_DRAIN_RESPONSE_BODY;
114 return OK;
117 void HttpResponseBodyDrainer::OnIOComplete(int result) {
118 int rv = DoLoop(result);
119 if (rv != ERR_IO_PENDING) {
120 timer_.Stop();
121 Finish(rv);
125 void HttpResponseBodyDrainer::OnTimerFired() {
126 Finish(ERR_TIMED_OUT);
129 void HttpResponseBodyDrainer::Finish(int result) {
130 DCHECK_NE(ERR_IO_PENDING, result);
132 if (session_)
133 session_->RemoveResponseDrainer(this);
135 if (result < 0) {
136 stream_->Close(true /* no keep-alive */);
137 } else {
138 DCHECK_EQ(OK, result);
139 stream_->Close(false /* keep-alive */);
142 delete this;
145 } // namespace net