13345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Copyright (c) 2010 The Chromium Authors. All rights reserved. 23345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Use of this source code is governed by a BSD-style license that can be 33345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// found in the LICENSE file. 43345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 53345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "net/http/http_response_body_drainer.h" 63345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 73345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/compiler_specific.h" 83345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/logging.h" 93345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "net/base/io_buffer.h" 103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "net/base/net_errors.h" 113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "net/http/http_network_session.h" 123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "net/http/http_stream.h" 133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merricknamespace net { 153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 163345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickHttpResponseBodyDrainer::HttpResponseBodyDrainer(HttpStream* stream) 173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick : stream_(stream), 183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick next_state_(STATE_NONE), 193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick total_read_(0), 203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ALLOW_THIS_IN_INITIALIZER_LIST( 213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick io_callback_(this, &HttpResponseBodyDrainer::OnIOComplete)), 223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick user_callback_(NULL), 233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick session_(NULL) {} 243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 253345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickHttpResponseBodyDrainer::~HttpResponseBodyDrainer() {} 263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid HttpResponseBodyDrainer::Start(HttpNetworkSession* session) { 283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick read_buf_ = new IOBuffer(kDrainBodyBufferSize); 293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick next_state_ = STATE_DRAIN_RESPONSE_BODY; 303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int rv = DoLoop(OK); 313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (rv == ERR_IO_PENDING) { 333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick timer_.Start(base::TimeDelta::FromSeconds(kTimeoutInSeconds), 343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick this, 353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick &HttpResponseBodyDrainer::OnTimerFired); 363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick session_ = session; 373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick session->AddResponseDrainer(this); 383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return; 393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick Finish(rv); 423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickint HttpResponseBodyDrainer::DoLoop(int result) { 453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK_NE(next_state_, STATE_NONE); 463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int rv = result; 483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick do { 493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick State state = next_state_; 503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick next_state_ = STATE_NONE; 513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick switch (state) { 523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick case STATE_DRAIN_RESPONSE_BODY: 533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK_EQ(OK, rv); 543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick rv = DoDrainResponseBody(); 553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick break; 563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick case STATE_DRAIN_RESPONSE_BODY_COMPLETE: 573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick rv = DoDrainResponseBodyComplete(rv); 583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick break; 593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick default: 603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick NOTREACHED() << "bad state"; 613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick rv = ERR_UNEXPECTED; 623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick break; 633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); 653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return rv; 673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickint HttpResponseBodyDrainer::DoDrainResponseBody() { 703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick next_state_ = STATE_DRAIN_RESPONSE_BODY_COMPLETE; 713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return stream_->ReadResponseBody( 733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick read_buf_, kDrainBodyBufferSize - total_read_, 743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick &io_callback_); 753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickint HttpResponseBodyDrainer::DoDrainResponseBodyComplete(int result) { 783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK_NE(ERR_IO_PENDING, result); 793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (result < 0) 813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return result; 823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (result == 0) 843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return ERR_CONNECTION_CLOSED; 853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick total_read_ += result; 873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (stream_->IsResponseBodyComplete()) 883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return OK; 893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK_LE(total_read_, kDrainBodyBufferSize); 913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (total_read_ >= kDrainBodyBufferSize) 923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return ERR_RESPONSE_BODY_TOO_BIG_TO_DRAIN; 933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick next_state_ = STATE_DRAIN_RESPONSE_BODY; 953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return OK; 963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid HttpResponseBodyDrainer::OnIOComplete(int result) { 993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int rv = DoLoop(result); 1003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (rv != ERR_IO_PENDING) { 1013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick timer_.Stop(); 1023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick Finish(rv); 1033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 1043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 1053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid HttpResponseBodyDrainer::OnTimerFired() { 1073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick Finish(ERR_TIMED_OUT); 1083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 1093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid HttpResponseBodyDrainer::Finish(int result) { 1113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK_NE(ERR_IO_PENDING, result); 1123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (session_) 1143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick session_->RemoveResponseDrainer(this); 1153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (result < 0) { 1173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick stream_->Close(true /* no keep-alive */); 1183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } else { 1193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK_EQ(OK, result); 1203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick stream_->Close(false /* keep-alive */); 1213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 1223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick delete this; 1243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 1253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} // namespace net 127