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