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/spdy/spdy_http_stream.h" | 5 #include "net/spdy/spdy_http_stream.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <list> | 8 #include <list> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
128 IOBuffer* buf, int buf_len, const CompletionCallback& callback) { | 128 IOBuffer* buf, int buf_len, const CompletionCallback& callback) { |
129 if (stream_) { | 129 if (stream_) { |
130 CHECK(stream_->is_idle()); | 130 CHECK(stream_->is_idle()); |
131 CHECK(!stream_->closed()); | 131 CHECK(!stream_->closed()); |
132 } | 132 } |
133 CHECK(buf); | 133 CHECK(buf); |
134 CHECK(buf_len); | 134 CHECK(buf_len); |
135 CHECK(!callback.is_null()); | 135 CHECK(!callback.is_null()); |
136 | 136 |
137 // If we have data buffered, complete the IO immediately. | 137 // If we have data buffered, complete the IO immediately. |
138 if (!response_body_queue_.IsEmpty()) { | 138 if (!response_body_.empty()) { |
139 size_t bytes_consumed = response_body_queue_.Dequeue(buf->data(), buf_len); | 139 int bytes_read = 0; |
| 140 while (!response_body_.empty() && buf_len > 0) { |
| 141 scoped_refptr<IOBufferWithSize> data = response_body_.front(); |
| 142 const int bytes_to_copy = std::min(buf_len, data->size()); |
| 143 memcpy(&(buf->data()[bytes_read]), data->data(), bytes_to_copy); |
| 144 buf_len -= bytes_to_copy; |
| 145 if (bytes_to_copy == data->size()) { |
| 146 response_body_.pop_front(); |
| 147 } else { |
| 148 const int bytes_remaining = data->size() - bytes_to_copy; |
| 149 IOBufferWithSize* new_buffer = new IOBufferWithSize(bytes_remaining); |
| 150 memcpy(new_buffer->data(), &(data->data()[bytes_to_copy]), |
| 151 bytes_remaining); |
| 152 response_body_.pop_front(); |
| 153 response_body_.push_front(make_scoped_refptr(new_buffer)); |
| 154 } |
| 155 bytes_read += bytes_to_copy; |
| 156 } |
140 if (stream_) | 157 if (stream_) |
141 stream_->IncreaseRecvWindowSize(bytes_consumed); | 158 stream_->IncreaseRecvWindowSize(bytes_read); |
142 return bytes_consumed; | 159 return bytes_read; |
143 } else if (stream_closed_) { | 160 } else if (stream_closed_) { |
144 return closed_stream_status_; | 161 return closed_stream_status_; |
145 } | 162 } |
146 | 163 |
147 CHECK(callback_.is_null()); | 164 CHECK(callback_.is_null()); |
148 CHECK(!user_buffer_); | 165 CHECK(!user_buffer_); |
149 CHECK_EQ(0, user_buffer_len_); | 166 CHECK_EQ(0, user_buffer_len_); |
150 | 167 |
151 callback_ = callback; | 168 callback_ = callback; |
152 user_buffer_ = buf; | 169 user_buffer_ = buf; |
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
410 DoCallback(status); | 427 DoCallback(status); |
411 | 428 |
412 return status; | 429 return status; |
413 } | 430 } |
414 | 431 |
415 void SpdyHttpStream::OnHeadersSent() { | 432 void SpdyHttpStream::OnHeadersSent() { |
416 // For HTTP streams, no HEADERS frame is sent from the client. | 433 // For HTTP streams, no HEADERS frame is sent from the client. |
417 NOTREACHED(); | 434 NOTREACHED(); |
418 } | 435 } |
419 | 436 |
420 int SpdyHttpStream::OnDataReceived(scoped_ptr<SpdyBuffer> buffer) { | 437 int SpdyHttpStream::OnDataReceived(const char* data, int length) { |
421 // SpdyStream won't call us with data if the header block didn't contain a | 438 // SpdyStream won't call us with data if the header block didn't contain a |
422 // valid set of headers. So we don't expect to not have headers received | 439 // valid set of headers. So we don't expect to not have headers received |
423 // here. | 440 // here. |
424 if (!response_headers_received_) | 441 if (!response_headers_received_) |
425 return ERR_INCOMPLETE_SPDY_HEADERS; | 442 return ERR_INCOMPLETE_SPDY_HEADERS; |
426 | 443 |
427 // Note that data may be received for a SpdyStream prior to the user calling | 444 // Note that data may be received for a SpdyStream prior to the user calling |
428 // ReadResponseBody(), therefore user_buffer_ may be NULL. This may often | 445 // ReadResponseBody(), therefore user_buffer_ may be NULL. This may often |
429 // happen for server initiated streams. | 446 // happen for server initiated streams. |
430 DCHECK(stream_.get()); | 447 DCHECK(stream_.get()); |
431 DCHECK(!stream_->closed() || stream_->pushed()); | 448 DCHECK(!stream_->closed() || stream_->pushed()); |
432 if (buffer) { | 449 if (length > 0) { |
433 response_body_queue_.Enqueue(buffer.Pass()); | 450 // Save the received data. |
| 451 IOBufferWithSize* io_buffer = new IOBufferWithSize(length); |
| 452 memcpy(io_buffer->data(), data, length); |
| 453 response_body_.push_back(make_scoped_refptr(io_buffer)); |
434 | 454 |
435 if (user_buffer_) { | 455 if (user_buffer_) { |
436 // Handing small chunks of data to the caller creates measurable overhead. | 456 // Handing small chunks of data to the caller creates measurable overhead. |
437 // We buffer data in short time-spans and send a single read notification. | 457 // We buffer data in short time-spans and send a single read notification. |
438 ScheduleBufferedReadCallback(); | 458 ScheduleBufferedReadCallback(); |
439 } | 459 } |
440 } | 460 } |
441 return OK; | 461 return OK; |
442 } | 462 } |
443 | 463 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
482 kBufferTime); | 502 kBufferTime); |
483 } | 503 } |
484 | 504 |
485 // Checks to see if we should wait for more buffered data before notifying | 505 // Checks to see if we should wait for more buffered data before notifying |
486 // the caller. Returns true if we should wait, false otherwise. | 506 // the caller. Returns true if we should wait, false otherwise. |
487 bool SpdyHttpStream::ShouldWaitForMoreBufferedData() const { | 507 bool SpdyHttpStream::ShouldWaitForMoreBufferedData() const { |
488 // If the response is complete, there is no point in waiting. | 508 // If the response is complete, there is no point in waiting. |
489 if (stream_closed_) | 509 if (stream_closed_) |
490 return false; | 510 return false; |
491 | 511 |
492 DCHECK_GT(user_buffer_len_, 0); | 512 int bytes_buffered = 0; |
493 return response_body_queue_.GetTotalSize() < | 513 std::list<scoped_refptr<IOBufferWithSize> >::const_iterator it; |
494 static_cast<size_t>(user_buffer_len_); | 514 for (it = response_body_.begin(); |
| 515 it != response_body_.end() && bytes_buffered < user_buffer_len_; |
| 516 ++it) |
| 517 bytes_buffered += (*it)->size(); |
| 518 |
| 519 return bytes_buffered < user_buffer_len_; |
495 } | 520 } |
496 | 521 |
497 bool SpdyHttpStream::DoBufferedReadCallback() { | 522 bool SpdyHttpStream::DoBufferedReadCallback() { |
498 buffered_read_callback_pending_ = false; | 523 buffered_read_callback_pending_ = false; |
499 | 524 |
500 // If the transaction is cancelled or errored out, we don't need to complete | 525 // If the transaction is cancelled or errored out, we don't need to complete |
501 // the read. | 526 // the read. |
502 if (!stream_ && !stream_closed_) | 527 if (!stream_ && !stream_closed_) |
503 return false; | 528 return false; |
504 | 529 |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
568 bool SpdyHttpStream::IsSpdyHttpStream() const { | 593 bool SpdyHttpStream::IsSpdyHttpStream() const { |
569 return true; | 594 return true; |
570 } | 595 } |
571 | 596 |
572 void SpdyHttpStream::Drain(HttpNetworkSession* session) { | 597 void SpdyHttpStream::Drain(HttpNetworkSession* session) { |
573 Close(false); | 598 Close(false); |
574 delete this; | 599 delete this; |
575 } | 600 } |
576 | 601 |
577 } // namespace net | 602 } // namespace net |
OLD | NEW |