Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(45)

Side by Side Diff: net/spdy/spdy_stream.cc

Issue 3020032: Implement server push protocol 2. (Closed)
Patch Set: nits. Created 10 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/spdy/spdy_stream.h ('k') | net/spdy/spdy_test_util.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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_stream.h" 5 #include "net/spdy/spdy_stream.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "base/message_loop.h" 8 #include "base/message_loop.h"
9 #include "base/singleton.h" 9 #include "base/singleton.h"
10 #include "net/spdy/spdy_session.h" 10 #include "net/spdy/spdy_session.h"
11 11
12 namespace net { 12 namespace net {
13 13
14 SpdyStream::SpdyStream( 14 SpdyStream::SpdyStream(
15 SpdySession* session, spdy::SpdyStreamId stream_id, bool pushed) 15 SpdySession* session, spdy::SpdyStreamId stream_id, bool pushed)
16 : stream_id_(stream_id), 16 : continue_buffering_data_(true),
17 stream_id_(stream_id),
17 priority_(0), 18 priority_(0),
18 send_window_size_(spdy::kInitialWindowSize), 19 send_window_size_(spdy::kInitialWindowSize),
19 pushed_(pushed), 20 pushed_(pushed),
20 metrics_(Singleton<BandwidthMetrics>::get()), 21 metrics_(Singleton<BandwidthMetrics>::get()),
21 syn_reply_received_(false), 22 syn_reply_received_(false),
22 session_(session), 23 session_(session),
23 delegate_(NULL), 24 delegate_(NULL),
24 request_time_(base::Time::Now()), 25 request_time_(base::Time::Now()),
25 response_(new spdy::SpdyHeaderBlock), 26 response_(new spdy::SpdyHeaderBlock),
26 response_complete_(false), 27 response_complete_(false),
27 io_state_(STATE_NONE), 28 io_state_(STATE_NONE),
28 response_status_(OK), 29 response_status_(OK),
29 cancelled_(false), 30 cancelled_(false),
30 send_bytes_(0), 31 send_bytes_(0),
31 recv_bytes_(0), 32 recv_bytes_(0),
32 histograms_recorded_(false) {} 33 histograms_recorded_(false) {}
33 34
34 SpdyStream::~SpdyStream() { 35 SpdyStream::~SpdyStream() {
35 DLOG(INFO) << "Deleting SpdyStream for stream " << stream_id_; 36 DLOG(INFO) << "Deleting SpdyStream for stream " << stream_id_;
36 } 37 }
37 38
38 void SpdyStream::SetDelegate(Delegate* delegate) { 39 void SpdyStream::SetDelegate(Delegate* delegate) {
39 CHECK(delegate); 40 CHECK(delegate);
40 delegate_ = delegate; 41 delegate_ = delegate;
41 42
42 if (!response_->empty()) { 43 if (pushed_) {
43 // The stream already got response. 44 CHECK(!response_->empty());
44 delegate_->OnResponseReceived(*response_, response_time_, OK); 45 MessageLoop::current()->PostTask(
46 FROM_HERE, NewRunnableMethod(this,
47 &SpdyStream::PushedStreamReplayData));
48 } else {
49 continue_buffering_data_ = false;
45 } 50 }
51 }
46 52
53 void SpdyStream::PushedStreamReplayData() {
54 if (cancelled_ || delegate_ == NULL)
55 return;
56
57 delegate_->OnResponseReceived(*response_, response_time_, OK);
58
59 continue_buffering_data_ = false;
47 std::vector<scoped_refptr<IOBufferWithSize> > buffers; 60 std::vector<scoped_refptr<IOBufferWithSize> > buffers;
48 buffers.swap(pending_buffers_); 61 buffers.swap(pending_buffers_);
49 for (size_t i = 0; i < buffers.size(); ++i) { 62 for (size_t i = 0; i < buffers.size(); ++i) {
50 if (delegate_) 63 if (delegate_){
51 delegate_->OnDataReceived(buffers[i]->data(), buffers[i]->size()); 64 if (buffers[i])
65 delegate_->OnDataReceived(buffers[i]->data(), buffers[i]->size());
66 else
67 delegate_->OnDataReceived(NULL, 0);
68 }
52 } 69 }
53 } 70 }
54 71
55 void SpdyStream::DetachDelegate() { 72 void SpdyStream::DetachDelegate() {
56 delegate_ = NULL; 73 delegate_ = NULL;
57 if (!response_complete_) 74 if (!response_complete_)
58 Cancel(); 75 Cancel();
59 } 76 }
60 77
61 const linked_ptr<spdy::SpdyHeaderBlock>& SpdyStream::spdy_headers() const { 78 const linked_ptr<spdy::SpdyHeaderBlock>& SpdyStream::spdy_headers() const {
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
124 DCHECK(response_->empty()); 141 DCHECK(response_->empty());
125 *response_ = response; // TODO(ukai): avoid copy. 142 *response_ = response; // TODO(ukai): avoid copy.
126 143
127 recv_first_byte_time_ = base::TimeTicks::Now(); 144 recv_first_byte_time_ = base::TimeTicks::Now();
128 response_time_ = base::Time::Now(); 145 response_time_ = base::Time::Now();
129 146
130 if (io_state_ == STATE_NONE) { 147 if (io_state_ == STATE_NONE) {
131 CHECK(pushed_); 148 CHECK(pushed_);
132 io_state_ = STATE_READ_HEADERS; 149 io_state_ = STATE_READ_HEADERS;
133 } else if (io_state_ == STATE_READ_HEADERS_COMPLETE) { 150 } else if (io_state_ == STATE_READ_HEADERS_COMPLETE) {
134 // This SpdyStream could be in this state in both true and false pushed_ 151 CHECK(!pushed_);
135 // conditions.
136 // The false pushed_ condition (client request) will always go through
137 // this state.
138 // The true pushed_condition (server push) can be in this state when the
139 // client requests an X-Associated-Content piece of content prior
140 // to when the server push happens.
141 } else { 152 } else {
142 // We're not expecting a response while in this state. Error! 153 // We're not expecting a response while in this state. Error!
143 rv = ERR_SPDY_PROTOCOL_ERROR; 154 rv = ERR_SPDY_PROTOCOL_ERROR;
144 } 155 }
145 156
146 rv = DoLoop(rv); 157 rv = DoLoop(rv);
147 if (delegate_) 158 if (delegate_)
148 rv = delegate_->OnResponseReceived(*response_, response_time_, rv); 159 rv = delegate_->OnResponseReceived(*response_, response_time_, rv);
149 // if delegate_ is not yet attached, we'll return response when delegate 160 // If delegate_ is not yet attached, we'll call OnResponseReceived after the
150 // gets attached to the stream. 161 // delegate gets attached to the stream.
151 162
152 return rv; 163 return rv;
153 } 164 }
154 165
155 void SpdyStream::OnDataReceived(const char* data, int length) { 166 void SpdyStream::OnDataReceived(const char* data, int length) {
156 DCHECK_GE(length, 0); 167 DCHECK_GE(length, 0);
157 LOG(INFO) << "SpdyStream: Data (" << length << " bytes) received for " 168 LOG(INFO) << "SpdyStream: Data (" << length << " bytes) received for "
158 << stream_id_; 169 << stream_id_;
159 170
160 CHECK(!response_complete_); 171 if (!delegate_ || continue_buffering_data_) {
172 // It should be valid for this to happen in the server push case.
173 // We'll return received data when delegate gets attached to the stream.
174 if (length > 0) {
175 IOBufferWithSize* buf = new IOBufferWithSize(length);
176 memcpy(buf->data(), data, length);
177 pending_buffers_.push_back(buf);
178 }
179 else
180 pending_buffers_.push_back(NULL);
181 return;
182 }
183
184 CHECK(!response_complete_);
161 185
162 // If we don't have a response, then the SYN_REPLY did not come through. 186 // If we don't have a response, then the SYN_REPLY did not come through.
163 // We cannot pass data up to the caller unless the reply headers have been 187 // We cannot pass data up to the caller unless the reply headers have been
164 // received. 188 // received.
165 if (response_->empty()) { 189 if (response_->empty()) {
166 session_->CloseStream(stream_id_, ERR_SYN_REPLY_NOT_RECEIVED); 190 session_->CloseStream(stream_id_, ERR_SYN_REPLY_NOT_RECEIVED);
167 return; 191 return;
168 } 192 }
169 193
170 // A zero-length read means that the stream is being closed. 194 // A zero-length read means that the stream is being closed.
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
241 return result; 265 return result;
242 } 266 }
243 267
244 send_time_ = base::TimeTicks::Now(); 268 send_time_ = base::TimeTicks::Now();
245 269
246 int result = OK; 270 int result = OK;
247 if (!pushed_) { 271 if (!pushed_) {
248 DCHECK_EQ(io_state_, STATE_NONE); 272 DCHECK_EQ(io_state_, STATE_NONE);
249 io_state_ = STATE_SEND_HEADERS; 273 io_state_ = STATE_SEND_HEADERS;
250 } else { 274 } else {
275 // Pushed stream should not have upload data.
251 DCHECK(!has_upload_data); 276 DCHECK(!has_upload_data);
252 if (!response_->empty()) { 277 DCHECK(!response_->empty());
253 // We already have response headers, so we don't need to read the header. 278 DCHECK_EQ(io_state_, STATE_OPEN);
254 // Pushed stream should not have upload data. 279 return ERR_IO_PENDING;
255 // We don't need to call DoLoop() in this state.
256 DCHECK_EQ(io_state_, STATE_OPEN);
257 return OK;
258 } else {
259 io_state_ = STATE_READ_HEADERS;
260 }
261 } 280 }
262 return DoLoop(result); 281 return DoLoop(result);
263 } 282 }
264 283
265 int SpdyStream::DoReadResponseHeaders() { 284 int SpdyStream::DoReadResponseHeaders() {
266 CHECK(!cancelled_); 285 CHECK(!cancelled_);
267 286
268 // The SYN_REPLY has already been received. 287 // The SYN_REPLY has already been received.
269 if (!response_->empty()) { 288 if (!response_->empty()) {
270 CHECK_EQ(STATE_OPEN, io_state_); 289 CHECK_EQ(STATE_OPEN, io_state_);
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
447 UMA_HISTOGRAM_TIMES("Net.SpdyStreamDownloadTime", 466 UMA_HISTOGRAM_TIMES("Net.SpdyStreamDownloadTime",
448 recv_last_byte_time_ - recv_first_byte_time_); 467 recv_last_byte_time_ - recv_first_byte_time_);
449 UMA_HISTOGRAM_TIMES("Net.SpdyStreamTime", 468 UMA_HISTOGRAM_TIMES("Net.SpdyStreamTime",
450 recv_last_byte_time_ - send_time_); 469 recv_last_byte_time_ - send_time_);
451 470
452 UMA_HISTOGRAM_COUNTS("Net.SpdySendBytes", send_bytes_); 471 UMA_HISTOGRAM_COUNTS("Net.SpdySendBytes", send_bytes_);
453 UMA_HISTOGRAM_COUNTS("Net.SpdyRecvBytes", recv_bytes_); 472 UMA_HISTOGRAM_COUNTS("Net.SpdyRecvBytes", recv_bytes_);
454 } 473 }
455 474
456 } // namespace net 475 } // namespace net
OLDNEW
« no previous file with comments | « net/spdy/spdy_stream.h ('k') | net/spdy/spdy_test_util.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698