summaryrefslogtreecommitdiffstats
path: root/net/spdy/spdy_stream.cc
diff options
context:
space:
mode:
authorerikchen@google.com <erikchen@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2010-08-05 17:59:58 +0000
committererikchen@google.com <erikchen@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2010-08-05 17:59:58 +0000
commite3ebba0fbbfb2c7eec286a964717859aa70b9fcf (patch)
treeb2a53d996ca4537fbb6516dcddba122d1cb6cbcd /net/spdy/spdy_stream.cc
parent1b7cde151f8e0e922a8c52c6ca48f6f1c6de21ec (diff)
downloadchromium_src-e3ebba0fbbfb2c7eec286a964717859aa70b9fcf.zip
chromium_src-e3ebba0fbbfb2c7eec286a964717859aa70b9fcf.tar.gz
chromium_src-e3ebba0fbbfb2c7eec286a964717859aa70b9fcf.tar.bz2
Implement server push protocol 2.
TEST=net_unittests BUG=34761 Review URL: http://codereview.chromium.org/3020032 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@55095 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/spdy/spdy_stream.cc')
-rw-r--r--net/spdy/spdy_stream.cc69
1 files changed, 44 insertions, 25 deletions
diff --git a/net/spdy/spdy_stream.cc b/net/spdy/spdy_stream.cc
index b79cb99..5fd5f14 100644
--- a/net/spdy/spdy_stream.cc
+++ b/net/spdy/spdy_stream.cc
@@ -13,7 +13,8 @@ namespace net {
SpdyStream::SpdyStream(
SpdySession* session, spdy::SpdyStreamId stream_id, bool pushed)
- : stream_id_(stream_id),
+ : continue_buffering_data_(true),
+ stream_id_(stream_id),
priority_(0),
send_window_size_(spdy::kInitialWindowSize),
pushed_(pushed),
@@ -39,16 +40,32 @@ void SpdyStream::SetDelegate(Delegate* delegate) {
CHECK(delegate);
delegate_ = delegate;
- if (!response_->empty()) {
- // The stream already got response.
- delegate_->OnResponseReceived(*response_, response_time_, OK);
+ if (pushed_) {
+ CHECK(!response_->empty());
+ MessageLoop::current()->PostTask(
+ FROM_HERE, NewRunnableMethod(this,
+ &SpdyStream::PushedStreamReplayData));
+ } else {
+ continue_buffering_data_ = false;
}
+}
+void SpdyStream::PushedStreamReplayData() {
+ if (cancelled_ || delegate_ == NULL)
+ return;
+
+ delegate_->OnResponseReceived(*response_, response_time_, OK);
+
+ continue_buffering_data_ = false;
std::vector<scoped_refptr<IOBufferWithSize> > buffers;
buffers.swap(pending_buffers_);
for (size_t i = 0; i < buffers.size(); ++i) {
- if (delegate_)
- delegate_->OnDataReceived(buffers[i]->data(), buffers[i]->size());
+ if (delegate_){
+ if (buffers[i])
+ delegate_->OnDataReceived(buffers[i]->data(), buffers[i]->size());
+ else
+ delegate_->OnDataReceived(NULL, 0);
+ }
}
}
@@ -131,13 +148,7 @@ int SpdyStream::OnResponseReceived(const spdy::SpdyHeaderBlock& response) {
CHECK(pushed_);
io_state_ = STATE_READ_HEADERS;
} else if (io_state_ == STATE_READ_HEADERS_COMPLETE) {
- // This SpdyStream could be in this state in both true and false pushed_
- // conditions.
- // The false pushed_ condition (client request) will always go through
- // this state.
- // The true pushed_condition (server push) can be in this state when the
- // client requests an X-Associated-Content piece of content prior
- // to when the server push happens.
+ CHECK(!pushed_);
} else {
// We're not expecting a response while in this state. Error!
rv = ERR_SPDY_PROTOCOL_ERROR;
@@ -146,8 +157,8 @@ int SpdyStream::OnResponseReceived(const spdy::SpdyHeaderBlock& response) {
rv = DoLoop(rv);
if (delegate_)
rv = delegate_->OnResponseReceived(*response_, response_time_, rv);
- // if delegate_ is not yet attached, we'll return response when delegate
- // gets attached to the stream.
+ // If delegate_ is not yet attached, we'll call OnResponseReceived after the
+ // delegate gets attached to the stream.
return rv;
}
@@ -157,7 +168,20 @@ void SpdyStream::OnDataReceived(const char* data, int length) {
LOG(INFO) << "SpdyStream: Data (" << length << " bytes) received for "
<< stream_id_;
- CHECK(!response_complete_);
+ if (!delegate_ || continue_buffering_data_) {
+ // It should be valid for this to happen in the server push case.
+ // We'll return received data when delegate gets attached to the stream.
+ if (length > 0) {
+ IOBufferWithSize* buf = new IOBufferWithSize(length);
+ memcpy(buf->data(), data, length);
+ pending_buffers_.push_back(buf);
+ }
+ else
+ pending_buffers_.push_back(NULL);
+ return;
+ }
+
+ CHECK(!response_complete_);
// If we don't have a response, then the SYN_REPLY did not come through.
// We cannot pass data up to the caller unless the reply headers have been
@@ -248,16 +272,11 @@ int SpdyStream::DoSendRequest(bool has_upload_data) {
DCHECK_EQ(io_state_, STATE_NONE);
io_state_ = STATE_SEND_HEADERS;
} else {
+ // Pushed stream should not have upload data.
DCHECK(!has_upload_data);
- if (!response_->empty()) {
- // We already have response headers, so we don't need to read the header.
- // Pushed stream should not have upload data.
- // We don't need to call DoLoop() in this state.
- DCHECK_EQ(io_state_, STATE_OPEN);
- return OK;
- } else {
- io_state_ = STATE_READ_HEADERS;
- }
+ DCHECK(!response_->empty());
+ DCHECK_EQ(io_state_, STATE_OPEN);
+ return ERR_IO_PENDING;
}
return DoLoop(result);
}