| Index: net/spdy/spdy_http_stream.cc
|
| ===================================================================
|
| --- net/spdy/spdy_http_stream.cc (revision 145922)
|
| +++ net/spdy/spdy_http_stream.cc (working copy)
|
| @@ -36,7 +36,8 @@
|
| user_buffer_len_(0),
|
| buffered_read_callback_pending_(false),
|
| more_read_data_pending_(false),
|
| - direct_(direct) { }
|
| + direct_(direct),
|
| + waiting_for_chunk_(false) { }
|
|
|
| void SpdyHttpStream::InitializeWithExistingStream(SpdyStream* spdy_stream) {
|
| stream_ = spdy_stream;
|
| @@ -45,6 +46,8 @@
|
| }
|
|
|
| SpdyHttpStream::~SpdyHttpStream() {
|
| + if (request_body_stream_ != NULL)
|
| + request_body_stream_->set_chunk_callback(NULL);
|
| if (stream_)
|
| stream_->DetachDelegate();
|
| }
|
| @@ -182,11 +185,6 @@
|
| return false;
|
| }
|
|
|
| -void SpdyHttpStream::set_chunk_callback(ChunkCallback* callback) {
|
| - if (request_body_stream_ != NULL)
|
| - request_body_stream_->set_chunk_callback(callback);
|
| -}
|
| -
|
| int SpdyHttpStream::SendRequest(const HttpRequestHeaders& request_headers,
|
| scoped_ptr<UploadDataStream> request_body,
|
| HttpResponseInfo* response,
|
| @@ -213,6 +211,7 @@
|
| if (request_body != NULL) {
|
| if (request_body->size() || request_body->is_chunked()) {
|
| request_body_stream_.reset(request_body.release());
|
| + request_body_stream_->set_chunk_callback(this);
|
| // Use kMaxSpdyFrameChunkSize as the buffer size, since the request
|
| // body data is written with this size at a time.
|
| raw_request_body_buf_ = new IOBufferWithSize(kMaxSpdyFrameChunkSize);
|
| @@ -241,9 +240,9 @@
|
| if (push_response_info_.get()) {
|
| *response = *(push_response_info_.get());
|
| push_response_info_.reset();
|
| + } else {
|
| + DCHECK_EQ(static_cast<HttpResponseInfo*>(NULL), response_info_);
|
| }
|
| - else
|
| - DCHECK_EQ(static_cast<HttpResponseInfo*>(NULL), response_info_);
|
|
|
| response_info_ = response;
|
|
|
| @@ -271,6 +270,35 @@
|
| stream_->Cancel();
|
| }
|
|
|
| +int SpdyHttpStream::SendData() {
|
| + CHECK(request_body_stream_.get());
|
| + CHECK_EQ(0, request_body_buf_->BytesRemaining());
|
| +
|
| + // Read the data from the request body stream.
|
| + const int bytes_read = request_body_stream_->Read(
|
| + raw_request_body_buf_, raw_request_body_buf_->size());
|
| + DCHECK(!waiting_for_chunk_ || bytes_read != ERR_IO_PENDING);
|
| +
|
| + if (request_body_stream_->is_chunked() && bytes_read == ERR_IO_PENDING) {
|
| + waiting_for_chunk_ = true;
|
| + return ERR_IO_PENDING;
|
| + }
|
| +
|
| + waiting_for_chunk_ = false;
|
| +
|
| + // ERR_IO_PENDING with chunked encoding is the only possible error.
|
| + DCHECK_GE(bytes_read, 0);
|
| +
|
| + request_body_buf_ = new DrainableIOBuffer(raw_request_body_buf_,
|
| + bytes_read);
|
| +
|
| + const bool eof = request_body_stream_->IsEOF();
|
| + return stream_->WriteStreamData(
|
| + request_body_buf_,
|
| + request_body_buf_->BytesRemaining(),
|
| + eof ? DATA_FLAG_FIN : DATA_FLAG_NONE);
|
| +}
|
| +
|
| bool SpdyHttpStream::OnSendHeadersComplete(int status) {
|
| if (!callback_.is_null())
|
| DoCallback(status);
|
| @@ -279,20 +307,19 @@
|
|
|
| int SpdyHttpStream::OnSendBody() {
|
| CHECK(request_body_stream_.get());
|
| + const bool eof = request_body_stream_->IsEOF();
|
| + if (request_body_buf_->BytesRemaining() > 0) {
|
| + return stream_->WriteStreamData(
|
| + request_body_buf_,
|
| + request_body_buf_->BytesRemaining(),
|
| + eof ? DATA_FLAG_FIN : DATA_FLAG_NONE);
|
| + }
|
|
|
| - // TODO(satorux): Clean up the logic here. This behavior is weird. Reading
|
| - // of upload data should happen in OnSendBody(). crbug.com/113107.
|
| - //
|
| - // Nothing to send. This happens when OnSendBody() is first called.
|
| - // A read of the upload data stream is initiated in OnSendBodyComplete().
|
| - if (request_body_buf_->BytesRemaining() == 0)
|
| + // The entire body data has been sent.
|
| + if (eof)
|
| return OK;
|
|
|
| - const bool eof = request_body_stream_->IsEOF();
|
| - return stream_->WriteStreamData(
|
| - request_body_buf_,
|
| - request_body_buf_->BytesRemaining(),
|
| - eof ? DATA_FLAG_FIN : DATA_FLAG_NONE);
|
| + return SendData();
|
| }
|
|
|
| int SpdyHttpStream::OnSendBodyComplete(int status, bool* eof) {
|
| @@ -311,19 +338,6 @@
|
| // Check if the entire body data has been sent.
|
| *eof = (request_body_stream_->IsEOF() &&
|
| !request_body_buf_->BytesRemaining());
|
| - if (*eof)
|
| - return OK;
|
| -
|
| - // Read the data from the request body stream.
|
| - const int bytes_read = request_body_stream_->Read(
|
| - raw_request_body_buf_, raw_request_body_buf_->size());
|
| - if (request_body_stream_->is_chunked() && bytes_read == ERR_IO_PENDING)
|
| - return ERR_IO_PENDING;
|
| - // ERR_IO_PENDING with chunked encoding is the only possible error.
|
| - DCHECK_GE(bytes_read, 0);
|
| -
|
| - request_body_buf_ = new DrainableIOBuffer(raw_request_body_buf_,
|
| - bytes_read);
|
| return OK;
|
| }
|
|
|
| @@ -406,6 +420,8 @@
|
|
|
| void SpdyHttpStream::OnClose(int status) {
|
| bool invoked_callback = false;
|
| + if (request_body_stream_ != NULL)
|
| + request_body_stream_->set_chunk_callback(NULL);
|
| if (status == net::OK) {
|
| // We need to complete any pending buffered read now.
|
| invoked_callback = DoBufferedReadCallback();
|
| @@ -414,6 +430,13 @@
|
| DoCallback(status);
|
| }
|
|
|
| +void SpdyHttpStream::OnChunkAvailable() {
|
| + if (!waiting_for_chunk_)
|
| + return;
|
| + DCHECK(request_body_stream_->is_chunked());
|
| + SendData();
|
| +}
|
| +
|
| void SpdyHttpStream::ScheduleBufferedReadCallback() {
|
| // If there is already a scheduled DoBufferedReadCallback, don't issue
|
| // another one. Mark that we have received more data and return.
|
|
|