| 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 |