OLD | NEW |
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/values.h" | 9 #include "base/values.h" |
10 #include "net/spdy/spdy_session.h" | 10 #include "net/spdy/spdy_session.h" |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
44 priority_(0), | 44 priority_(0), |
45 stalled_by_flow_control_(false), | 45 stalled_by_flow_control_(false), |
46 send_window_size_(spdy::kSpdyStreamInitialWindowSize), | 46 send_window_size_(spdy::kSpdyStreamInitialWindowSize), |
47 recv_window_size_(spdy::kSpdyStreamInitialWindowSize), | 47 recv_window_size_(spdy::kSpdyStreamInitialWindowSize), |
48 pushed_(pushed), | 48 pushed_(pushed), |
49 response_received_(false), | 49 response_received_(false), |
50 session_(session), | 50 session_(session), |
51 delegate_(NULL), | 51 delegate_(NULL), |
52 request_time_(base::Time::Now()), | 52 request_time_(base::Time::Now()), |
53 response_(new spdy::SpdyHeaderBlock), | 53 response_(new spdy::SpdyHeaderBlock), |
| 54 syn_reply_received_(false), |
| 55 metrics_started_(false), |
| 56 close_pending_(false), |
54 io_state_(STATE_NONE), | 57 io_state_(STATE_NONE), |
55 response_status_(OK), | 58 response_status_(OK), |
56 cancelled_(false), | 59 cancelled_(false), |
57 has_upload_data_(false), | 60 has_upload_data_(false), |
58 net_log_(net_log), | 61 net_log_(net_log), |
59 send_bytes_(0), | 62 send_bytes_(0), |
60 recv_bytes_(0) { | 63 recv_bytes_(0) { |
61 } | 64 } |
62 | 65 |
63 SpdyStream::~SpdyStream() { | 66 SpdyStream::~SpdyStream() { |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
223 } | 226 } |
224 | 227 |
225 base::Time SpdyStream::GetRequestTime() const { | 228 base::Time SpdyStream::GetRequestTime() const { |
226 return request_time_; | 229 return request_time_; |
227 } | 230 } |
228 | 231 |
229 void SpdyStream::SetRequestTime(base::Time t) { | 232 void SpdyStream::SetRequestTime(base::Time t) { |
230 request_time_ = t; | 233 request_time_ = t; |
231 } | 234 } |
232 | 235 |
| 236 bool SpdyStream::using_sctp() { |
| 237 return session_->using_sctp(); |
| 238 } |
| 239 |
| 240 bool SpdyStream::using_sctp_control_stream() { |
| 241 return session_->using_sctp_control_stream(); |
| 242 } |
| 243 |
233 int SpdyStream::OnResponseReceived(const spdy::SpdyHeaderBlock& response) { | 244 int SpdyStream::OnResponseReceived(const spdy::SpdyHeaderBlock& response) { |
234 int rv = OK; | 245 int rv = OK; |
235 | 246 |
236 metrics_.StartStream(); | 247 // We need to avoid starting metrics a second time. If we are using SCTP |
| 248 // with a single dictionary, and the SYN_REPLY was delayed or lost, we may |
| 249 // have already started metrics when the first DATA frame arrived. |
| 250 if ( !(using_sctp() && |
| 251 using_sctp_control_stream() && |
| 252 metrics_started()) |
| 253 ) { |
| 254 set_metrics_started(); |
| 255 metrics_.StartStream(); |
| 256 } |
237 | 257 |
238 DCHECK(response_->empty()); | 258 DCHECK(response_->empty()); |
239 *response_ = response; // TODO(ukai): avoid copy. | 259 *response_ = response; // TODO(ukai): avoid copy. |
240 | 260 |
241 recv_first_byte_time_ = base::TimeTicks::Now(); | 261 recv_first_byte_time_ = base::TimeTicks::Now(); |
242 response_time_ = base::Time::Now(); | 262 response_time_ = base::Time::Now(); |
243 | 263 |
244 // If we receive a response before we are in STATE_WAITING_FOR_RESPONSE, then | 264 // If we receive a response before we are in STATE_WAITING_FOR_RESPONSE, then |
245 // the server has sent the SYN_REPLY too early. | 265 // the server has sent the SYN_REPLY too early. |
246 if (!pushed_ && io_state_ != STATE_WAITING_FOR_RESPONSE) | 266 if (!pushed_ && io_state_ != STATE_WAITING_FOR_RESPONSE) |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
279 // ERR_INCOMPLETE_SPDY_HEADERS means that we are waiting for more | 299 // ERR_INCOMPLETE_SPDY_HEADERS means that we are waiting for more |
280 // headers before the response header block is complete. | 300 // headers before the response header block is complete. |
281 if (rv == ERR_INCOMPLETE_SPDY_HEADERS) | 301 if (rv == ERR_INCOMPLETE_SPDY_HEADERS) |
282 rv = OK; | 302 rv = OK; |
283 } | 303 } |
284 return rv; | 304 return rv; |
285 } | 305 } |
286 | 306 |
287 void SpdyStream::OnDataReceived(const char* data, int length) { | 307 void SpdyStream::OnDataReceived(const char* data, int length) { |
288 DCHECK_GE(length, 0); | 308 DCHECK_GE(length, 0); |
| 309 // TODO(jtl): revisit this |
| 310 // We need to start metrics here if we are using SCTP without multiple |
| 311 // dictionaries, the SYN_REPLY has not yet arrived and metrics have not yet |
| 312 // been started. |
| 313 if (using_sctp() && |
| 314 using_sctp_control_stream() && |
| 315 !syn_reply_received() && |
| 316 !metrics_started()) { |
| 317 set_metrics_started(); |
| 318 metrics_.StartStream(); |
| 319 } |
289 | 320 |
290 // If we don't have a response, then the SYN_REPLY did not come through. | 321 // If we don't have a response, then the SYN_REPLY did not come through. |
291 // We cannot pass data up to the caller unless the reply headers have been | 322 // We cannot pass data up to the caller unless the reply headers have been |
292 // received. | 323 // received. |
293 if (!response_received()) { | 324 // Exception - when using SCTP with a single dictionary, all SPDY CONTROL |
| 325 // frames are sent on SCTP stream 0, while all SPDY DATA frames are sent on |
| 326 // SCTP stream n > 0. This means that data can arrive before a SYN_REPLY, |
| 327 // due to reordering or loss. In this case we can't require response_received |
| 328 // to be true. |
| 329 if (!response_received() && |
| 330 !(using_sctp() && using_sctp_control_stream())) { |
| 331 printf("SpdyStream::OnDataReceived: closing stream %d\n", stream_id_); |
294 session_->CloseStream(stream_id_, ERR_SYN_REPLY_NOT_RECEIVED); | 332 session_->CloseStream(stream_id_, ERR_SYN_REPLY_NOT_RECEIVED); |
295 return; | 333 return; |
296 } | 334 } |
297 | 335 |
298 if (!delegate_ || continue_buffering_data_) { | 336 if (!delegate_ || continue_buffering_data_) { |
299 // It should be valid for this to happen in the server push case. | 337 // It should be valid for this to happen in the server push case. |
300 // We'll return received data when delegate gets attached to the stream. | 338 // We'll return received data when delegate gets attached to the stream. |
301 if (length > 0) { | 339 if (length > 0) { |
302 IOBufferWithSize* buf = new IOBufferWithSize(length); | 340 IOBufferWithSize* buf = new IOBufferWithSize(length); |
303 memcpy(buf->data(), data, length); | 341 memcpy(buf->data(), data, length); |
304 pending_buffers_.push_back(make_scoped_refptr(buf)); | 342 pending_buffers_.push_back(make_scoped_refptr(buf)); |
305 } else { | 343 } else { |
306 pending_buffers_.push_back(NULL); | 344 pending_buffers_.push_back(NULL); |
307 metrics_.StopStream(); | 345 metrics_.StopStream(); |
308 // Note: we leave the stream open in the session until the stream | 346 // Note: we leave the stream open in the session until the stream |
309 // is claimed. | 347 // is claimed. |
310 } | 348 } |
311 return; | 349 return; |
312 } | 350 } |
313 | 351 |
314 CHECK(!closed()); | 352 CHECK(!closed()); |
315 | 353 |
316 // A zero-length read means that the stream is being closed. | 354 // A zero-length read means that the stream is being closed. |
317 if (!length) { | 355 // Exception - if using SCTP and sending all SPDY control framed on SCTP |
| 356 // stream 0, we can't close the stream if we haven't received the SYN_REPLY |
| 357 // yet. |
| 358 if (!length && using_sctp() && using_sctp_control_stream() && |
| 359 !syn_reply_received()) { |
| 360 printf("SpdyStream::OnDataReceived: marking stream %d as ** close_pending " |
| 361 "*** because !length.\n", stream_id_); |
| 362 set_close_pending(); // mark stream for closure once SYN_REPLY arrives. |
| 363 return; |
| 364 } else if (!length) { |
318 metrics_.StopStream(); | 365 metrics_.StopStream(); |
| 366 printf("SpdyStream::OnDataReceived: closing stream %d because !length.\n", |
| 367 stream_id_); |
319 session_->CloseStream(stream_id_, net::OK); | 368 session_->CloseStream(stream_id_, net::OK); |
320 // Note: |this| may be deleted after calling CloseStream. | 369 // Note: |this| may be deleted after calling CloseStream. |
321 return; | 370 return; |
322 } | 371 } |
323 | 372 |
324 if (session_->flow_control()) | 373 if (session_->flow_control()) |
325 DecreaseRecvWindowSize(length); | 374 DecreaseRecvWindowSize(length); |
326 | 375 |
327 // Track our bandwidth. | 376 // Track our bandwidth. |
328 metrics_.RecordBytes(length); | 377 metrics_.RecordBytes(length); |
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
590 UMA_HISTOGRAM_TIMES("Net.SpdyStreamDownloadTime", | 639 UMA_HISTOGRAM_TIMES("Net.SpdyStreamDownloadTime", |
591 recv_last_byte_time_ - recv_first_byte_time_); | 640 recv_last_byte_time_ - recv_first_byte_time_); |
592 UMA_HISTOGRAM_TIMES("Net.SpdyStreamTime", | 641 UMA_HISTOGRAM_TIMES("Net.SpdyStreamTime", |
593 recv_last_byte_time_ - send_time_); | 642 recv_last_byte_time_ - send_time_); |
594 | 643 |
595 UMA_HISTOGRAM_COUNTS("Net.SpdySendBytes", send_bytes_); | 644 UMA_HISTOGRAM_COUNTS("Net.SpdySendBytes", send_bytes_); |
596 UMA_HISTOGRAM_COUNTS("Net.SpdyRecvBytes", recv_bytes_); | 645 UMA_HISTOGRAM_COUNTS("Net.SpdyRecvBytes", recv_bytes_); |
597 } | 646 } |
598 | 647 |
599 } // namespace net | 648 } // namespace net |
OLD | NEW |