Chromium Code Reviews| Index: net/spdy/spdy_stream.cc |
| diff --git a/net/spdy/spdy_stream.cc b/net/spdy/spdy_stream.cc |
| index 8a45ad80afd39ed2cf1aefdde400f6ee19e2a803..4470dfc3d70d6c04ac88fd29582189d2dda6c427 100644 |
| --- a/net/spdy/spdy_stream.cc |
| +++ b/net/spdy/spdy_stream.cc |
| @@ -78,14 +78,15 @@ class SpdyStream::SynStreamBufferProducer : public SpdyBufferProducer { |
| const base::WeakPtr<SpdyStream> stream_; |
| }; |
| -SpdyStream::SpdyStream(SpdySession* session, |
| +SpdyStream::SpdyStream(SpdyStreamType type, |
| + SpdySession* session, |
| const std::string& path, |
| RequestPriority priority, |
| int32 initial_send_window_size, |
| int32 initial_recv_window_size, |
| - bool pushed, |
| const BoundNetLog& net_log) |
| - : weak_ptr_factory_(this), |
| + : type_(type), |
| + weak_ptr_factory_(this), |
| in_do_loop_(false), |
| continue_buffering_data_(true), |
| stream_id_(0), |
| @@ -96,11 +97,12 @@ SpdyStream::SpdyStream(SpdySession* session, |
| send_window_size_(initial_send_window_size), |
| recv_window_size_(initial_recv_window_size), |
| unacked_recv_window_bytes_(0), |
| - pushed_(pushed), |
| response_received_(false), |
| session_(session), |
| delegate_(NULL), |
| - send_status_(MORE_DATA_TO_SEND), |
| + send_status_( |
| + (type_ == SPDY_PUSH_STREAM) ? |
| + NO_MORE_DATA_TO_SEND : MORE_DATA_TO_SEND), |
| request_time_(base::Time::Now()), |
| response_(new SpdyHeaderBlock), |
| io_state_(STATE_NONE), |
| @@ -122,7 +124,7 @@ void SpdyStream::SetDelegate(Delegate* delegate) { |
| CHECK(delegate); |
| delegate_ = delegate; |
| - if (pushed_) { |
| + if (type_ == SPDY_PUSH_STREAM) { |
| CHECK(response_received()); |
| base::MessageLoop::current()->PostTask( |
| FROM_HERE, |
| @@ -379,9 +381,9 @@ int SpdyStream::OnResponseReceived(const SpdyHeaderBlock& response) { |
| // If we receive a response before we are in STATE_WAITING_FOR_RESPONSE, then |
| // the server has sent the SYN_REPLY too early. |
| - if (!pushed_ && io_state_ != STATE_WAITING_FOR_RESPONSE) |
| + if (type_ != SPDY_PUSH_STREAM && io_state_ != STATE_WAITING_FOR_RESPONSE) |
| return ERR_SPDY_PROTOCOL_ERROR; |
| - if (pushed_) |
| + if (type_ == SPDY_PUSH_STREAM) |
| CHECK_EQ(io_state_, STATE_NONE); |
| io_state_ = STATE_OPEN; |
| @@ -563,21 +565,13 @@ void SpdyStream::Close() { |
| int SpdyStream::SendRequestHeaders(scoped_ptr<SpdyHeaderBlock> headers, |
| SpdySendStatus send_status) { |
| + CHECK_NE(type_, SPDY_PUSH_STREAM); |
|
Ryan Hamilton
2013/05/26 15:33:49
I don't think this is right, is it? When a reques
|
| CHECK_EQ(send_status_, MORE_DATA_TO_SEND); |
| CHECK(!request_); |
| + CHECK(!pending_send_data_); |
| + CHECK_EQ(io_state_, STATE_NONE); |
| request_ = headers.Pass(); |
| - // Pushed streams do not send any data, and should always be |
| - // idle. However, we still want to return IO_PENDING to mimic |
| - // non-push behavior. |
| send_status_ = send_status; |
| - if (pushed_) { |
| - DCHECK(is_idle()); |
| - DCHECK_EQ(send_status_, NO_MORE_DATA_TO_SEND); |
| - DCHECK(response_received()); |
| - send_time_ = base::TimeTicks::Now(); |
| - return ERR_IO_PENDING; |
| - } |
| - CHECK_EQ(STATE_NONE, io_state_); |
| io_state_ = STATE_GET_DOMAIN_BOUND_CERT; |
| return DoLoop(OK); |
| } |
| @@ -585,7 +579,9 @@ int SpdyStream::SendRequestHeaders(scoped_ptr<SpdyHeaderBlock> headers, |
| void SpdyStream::SendStreamData(IOBuffer* data, |
| int length, |
| SpdySendStatus send_status) { |
| + CHECK_NE(type_, SPDY_PUSH_STREAM); |
| CHECK_EQ(send_status_, MORE_DATA_TO_SEND); |
| + CHECK_GE(io_state_, STATE_SEND_BODY); |
| CHECK(!pending_send_data_); |
| pending_send_data_ = new DrainableIOBuffer(data, length); |
| send_status_ = send_status; |
| @@ -621,7 +617,7 @@ base::WeakPtr<SpdyStream> SpdyStream::GetWeakPtr() { |
| } |
| bool SpdyStream::HasUrl() const { |
| - if (pushed_) |
| + if (type_ == SPDY_PUSH_STREAM) |
| return response_received(); |
| return request_.get() != NULL; |
| } |
| @@ -629,12 +625,14 @@ bool SpdyStream::HasUrl() const { |
| GURL SpdyStream::GetUrl() const { |
| DCHECK(HasUrl()); |
| - const SpdyHeaderBlock& headers = (pushed_) ? *response_ : *request_; |
| - return GetUrlFromHeaderBlock(headers, GetProtocolVersion(), pushed_); |
| + const SpdyHeaderBlock& headers = |
| + (type_ == SPDY_PUSH_STREAM) ? *response_ : *request_; |
| + return GetUrlFromHeaderBlock(headers, GetProtocolVersion(), |
| + type_ == SPDY_PUSH_STREAM); |
| } |
| void SpdyStream::OnGetDomainBoundCertComplete(int result) { |
| - DCHECK_EQ(STATE_GET_DOMAIN_BOUND_CERT_COMPLETE, io_state_); |
| + DCHECK_EQ(io_state_, STATE_GET_DOMAIN_BOUND_CERT_COMPLETE); |
| DoLoop(result); |
| } |
| @@ -719,8 +717,9 @@ int SpdyStream::DoLoop(int result) { |
| int SpdyStream::DoGetDomainBoundCert() { |
| CHECK(request_.get()); |
| + DCHECK_NE(type_, SPDY_PUSH_STREAM); |
| GURL url = GetUrl(); |
| - if (!session_->NeedsCredentials() || pushed_ || !url.SchemeIs("https")) { |
| + if (!session_->NeedsCredentials() || !url.SchemeIs("https")) { |
| // Proceed directly to sending the request headers |
| io_state_ = STATE_SEND_REQUEST_HEADERS; |
| return OK; |
| @@ -747,6 +746,7 @@ int SpdyStream::DoGetDomainBoundCert() { |
| } |
| int SpdyStream::DoGetDomainBoundCertComplete(int result) { |
| + DCHECK_NE(type_, SPDY_PUSH_STREAM); |
| if (result != OK) |
| return result; |
| @@ -756,8 +756,9 @@ int SpdyStream::DoGetDomainBoundCertComplete(int result) { |
| } |
| int SpdyStream::DoSendDomainBoundCert() { |
| - io_state_ = STATE_SEND_DOMAIN_BOUND_CERT_COMPLETE; |
| CHECK(request_.get()); |
| + DCHECK_NE(type_, SPDY_PUSH_STREAM); |
| + io_state_ = STATE_SEND_DOMAIN_BOUND_CERT_COMPLETE; |
| std::string origin = GetUrl().GetOrigin().spec(); |
| DCHECK(origin[origin.length() - 1] == '/'); |
| @@ -788,6 +789,7 @@ int SpdyStream::DoSendDomainBoundCert() { |
| } |
| int SpdyStream::DoSendDomainBoundCertComplete(int result) { |
| + DCHECK_NE(type_, SPDY_PUSH_STREAM); |
| if (result != OK) |
| return result; |
| @@ -797,6 +799,7 @@ int SpdyStream::DoSendDomainBoundCertComplete(int result) { |
| } |
| int SpdyStream::DoSendRequestHeaders() { |
| + DCHECK_NE(type_, SPDY_PUSH_STREAM); |
| io_state_ = STATE_SEND_REQUEST_HEADERS_COMPLETE; |
| session_->EnqueueStreamWrite( |
| @@ -807,18 +810,32 @@ int SpdyStream::DoSendRequestHeaders() { |
| } |
| int SpdyStream::DoSendRequestHeadersComplete() { |
| + DCHECK_NE(type_, SPDY_PUSH_STREAM); |
| DCHECK_EQ(just_completed_frame_type_, SYN_STREAM); |
| DCHECK_NE(stream_id_, 0u); |
| if (!delegate_) |
| return ERR_UNEXPECTED; |
| - // We don't store the return value in |send_status_|; see comments |
| - // in spdy_stream.h for OnSendRequestHeadersComplete(). |
| - SpdySendStatus send_status = delegate_->OnSendRequestHeadersComplete(); |
| + delegate_->OnSendRequestHeadersComplete(); |
| - io_state_ = |
| - (send_status == MORE_DATA_TO_SEND) ? |
| - STATE_SEND_BODY : STATE_WAITING_FOR_RESPONSE; |
| + switch (type_) { |
| + case SPDY_BIDIRECTIONAL_STREAM: |
| + DCHECK_EQ(send_status_, MORE_DATA_TO_SEND); |
| + io_state_ = STATE_WAITING_FOR_RESPONSE; |
| + break; |
| + |
| + case SPDY_REQUEST_RESPONSE_STREAM: |
| + io_state_ = |
| + (send_status_ == MORE_DATA_TO_SEND) ? |
| + STATE_SEND_BODY : STATE_WAITING_FOR_RESPONSE; |
| + break; |
| + |
| + case SPDY_PUSH_STREAM: |
| + // Fall through. |
| + default: |
| + NOTREACHED(); |
| + return ERR_UNEXPECTED; |
| + } |
| return OK; |
| } |
| @@ -826,6 +843,7 @@ int SpdyStream::DoSendRequestHeadersComplete() { |
| // DoSendBody is called to send the optional body for the request. This call |
| // will also be called as each write of a chunk of the body completes. |
| int SpdyStream::DoSendBody() { |
| + DCHECK_NE(type_, SPDY_PUSH_STREAM); |
| io_state_ = STATE_SEND_BODY_COMPLETE; |
| CHECK(delegate_); |
| delegate_->OnSendBody(); |
| @@ -833,6 +851,7 @@ int SpdyStream::DoSendBody() { |
| } |
| int SpdyStream::DoSendBodyComplete(int result) { |
| + DCHECK_NE(type_, SPDY_PUSH_STREAM); |
| result = ProcessJustCompletedFrame(result, STATE_SEND_BODY_COMPLETE); |
| if (result != OK) |
| @@ -902,17 +921,30 @@ int SpdyStream::ProcessJustCompletedFrame(int result, State io_pending_state) { |
| } |
| void SpdyStream::UpdateHistograms() { |
| - // We need all timers to be filled in, otherwise metrics can be bogus. |
| - if (send_time_.is_null() || recv_first_byte_time_.is_null() || |
| - recv_last_byte_time_.is_null()) |
| + // We need at least the receive timers to be filled in, as otherwise |
| + // metrics can be bogus. |
| + if (recv_first_byte_time_.is_null() || recv_last_byte_time_.is_null()) |
| return; |
| + base::TimeTicks effective_send_time; |
| + if (type_ == SPDY_PUSH_STREAM) { |
| + // Push streams shouldn't have |send_time_| filled in. |
| + DCHECK(send_time_.is_null()); |
| + effective_send_time = recv_first_byte_time_; |
| + } else { |
| + // For non-push streams, we also need |send_time_| to be filled |
| + // in. |
| + if (send_time_.is_null()) |
| + return; |
| + effective_send_time = send_time_; |
| + } |
| + |
| UMA_HISTOGRAM_TIMES("Net.SpdyStreamTimeToFirstByte", |
| - recv_first_byte_time_ - send_time_); |
| + recv_first_byte_time_ - effective_send_time); |
| UMA_HISTOGRAM_TIMES("Net.SpdyStreamDownloadTime", |
| - recv_last_byte_time_ - recv_first_byte_time_); |
| + recv_last_byte_time_ - recv_first_byte_time_); |
| UMA_HISTOGRAM_TIMES("Net.SpdyStreamTime", |
| - recv_last_byte_time_ - send_time_); |
| + recv_last_byte_time_ - effective_send_time); |
| UMA_HISTOGRAM_COUNTS("Net.SpdySendBytes", send_bytes_); |
| UMA_HISTOGRAM_COUNTS("Net.SpdyRecvBytes", recv_bytes_); |