diff options
-rw-r--r-- | net/spdy/spdy_stream.cc | 45 | ||||
-rw-r--r-- | net/spdy/spdy_stream.h | 33 |
2 files changed, 43 insertions, 35 deletions
diff --git a/net/spdy/spdy_stream.cc b/net/spdy/spdy_stream.cc index 32e494c..f3b1447 100644 --- a/net/spdy/spdy_stream.cc +++ b/net/spdy/spdy_stream.cc @@ -97,7 +97,7 @@ SpdyStream::SpdyStream(SpdyStreamType type, unacked_recv_window_bytes_(0), session_(session), delegate_(NULL), - send_status_( + pending_send_status_( (type_ == SPDY_PUSH_STREAM) ? NO_MORE_DATA_TO_SEND : MORE_DATA_TO_SEND), request_time_(base::Time::Now()), @@ -131,11 +131,11 @@ void SpdyStream::SetDelegate(Delegate* delegate) { DCHECK(continue_buffering_data_); base::MessageLoop::current()->PostTask( FROM_HERE, - base::Bind(&SpdyStream::PushedStreamReplayData, GetWeakPtr())); + base::Bind(&SpdyStream::PushedStreamReplay, GetWeakPtr())); } } -void SpdyStream::PushedStreamReplayData() { +void SpdyStream::PushedStreamReplay() { DCHECK_EQ(type_, SPDY_PUSH_STREAM); DCHECK_NE(stream_id_, 0u); DCHECK(continue_buffering_data_); @@ -155,7 +155,7 @@ void SpdyStream::PushedStreamReplayData() { // we're waiting for another HEADERS frame, and we had better not // have any pending data frames. CHECK(weak_this); - if (!pending_buffers_.empty()) { + if (!pending_recv_data_.empty()) { LogStreamError(ERR_SPDY_PROTOCOL_ERROR, "Data received with incomplete headers."); session_->CloseActiveStream(stream_id_, ERR_SPDY_PROTOCOL_ERROR); @@ -169,10 +169,10 @@ void SpdyStream::PushedStreamReplayData() { response_headers_status_ = RESPONSE_HEADERS_ARE_COMPLETE; - while (!pending_buffers_.empty()) { - // Take ownership of the first element of |pending_buffers_|. - scoped_ptr<SpdyBuffer> buffer(pending_buffers_.front()); - pending_buffers_.weak_erase(pending_buffers_.begin()); + while (!pending_recv_data_.empty()) { + // Take ownership of the first element of |pending_recv_data_|. + scoped_ptr<SpdyBuffer> buffer(pending_recv_data_.front()); + pending_recv_data_.weak_erase(pending_recv_data_.begin()); bool eof = (buffer == NULL); @@ -184,10 +184,10 @@ void SpdyStream::PushedStreamReplayData() { return; if (eof) { - DCHECK(pending_buffers_.empty()); + DCHECK(pending_recv_data_.empty()); session_->CloseActiveStream(stream_id_, OK); DCHECK(!weak_this); - // |pending_buffers_| is invalid at this point. + // |pending_recv_data_| is invalid at this point. break; } } @@ -199,7 +199,7 @@ scoped_ptr<SpdyFrame> SpdyStream::ProduceSynStreamFrame() { CHECK_GT(stream_id_, 0u); SpdyControlFlags flags = - (send_status_ == NO_MORE_DATA_TO_SEND) ? + (pending_send_status_ == NO_MORE_DATA_TO_SEND) ? CONTROL_FLAG_FIN : CONTROL_FLAG_NONE; scoped_ptr<SpdyFrame> frame(session_->CreateSynStream( stream_id_, priority_, flags, *request_headers_)); @@ -409,7 +409,8 @@ int SpdyStream::OnInitialResponseHeadersReceived( // For a request/response stream, we're ready for the response // headers once we've finished sending the request headers and // the request body (if we have one). - if ((io_state_ < STATE_IDLE) || (send_status_ == MORE_DATA_TO_SEND) || + if ((io_state_ < STATE_IDLE) || + (pending_send_status_ == MORE_DATA_TO_SEND) || pending_send_data_.get()) { session_->ResetStream(stream_id_, RST_STREAM_PROTOCOL_ERROR, "Response received before request sent"); @@ -419,7 +420,7 @@ int SpdyStream::OnInitialResponseHeadersReceived( case SPDY_PUSH_STREAM: // For a push stream, we're ready immediately. - DCHECK_EQ(send_status_, NO_MORE_DATA_TO_SEND); + DCHECK_EQ(pending_send_status_, NO_MORE_DATA_TO_SEND); DCHECK_EQ(io_state_, STATE_IDLE); break; } @@ -461,9 +462,9 @@ void SpdyStream::OnDataReceived(scoped_ptr<SpdyBuffer> buffer) { // 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 (buffer) { - pending_buffers_.push_back(buffer.release()); + pending_recv_data_.push_back(buffer.release()); } else { - pending_buffers_.push_back(NULL); + pending_recv_data_.push_back(NULL); metrics_.StopStream(); // Note: we leave the stream open in the session until the stream // is claimed. @@ -577,12 +578,12 @@ base::WeakPtr<SpdyStream> SpdyStream::GetWeakPtr() { int SpdyStream::SendRequestHeaders(scoped_ptr<SpdyHeaderBlock> request_headers, SpdySendStatus send_status) { CHECK_NE(type_, SPDY_PUSH_STREAM); - CHECK_EQ(send_status_, MORE_DATA_TO_SEND); + CHECK_EQ(pending_send_status_, MORE_DATA_TO_SEND); CHECK(!request_headers_); CHECK(!pending_send_data_.get()); CHECK_EQ(io_state_, STATE_NONE); request_headers_ = request_headers.Pass(); - send_status_ = send_status; + pending_send_status_ = send_status; io_state_ = STATE_SEND_REQUEST_HEADERS; return DoLoop(OK); } @@ -591,11 +592,11 @@ void SpdyStream::SendData(IOBuffer* data, int length, SpdySendStatus send_status) { CHECK_NE(type_, SPDY_PUSH_STREAM); - CHECK_EQ(send_status_, MORE_DATA_TO_SEND); + CHECK_EQ(pending_send_status_, MORE_DATA_TO_SEND); CHECK_GE(io_state_, STATE_SEND_REQUEST_HEADERS_COMPLETE); CHECK(!pending_send_data_.get()); pending_send_data_ = new DrainableIOBuffer(data, length); - send_status_ = send_status; + pending_send_status_ = send_status; QueueNextDataFrame(); } @@ -758,7 +759,7 @@ int SpdyStream::DoSendRequestHeadersComplete() { // check in the destructor. delegate_->OnRequestHeadersSent(); - return GetOpenStateResult(type_, send_status_); + return GetOpenStateResult(type_, pending_send_status_); } int SpdyStream::DoOpen() { @@ -799,7 +800,7 @@ int SpdyStream::DoOpen() { // |in_do_loop_| check in the destructor. delegate_->OnDataSent(); - return GetOpenStateResult(type_, send_status_); + return GetOpenStateResult(type_, pending_send_status_); } void SpdyStream::UpdateHistograms() { @@ -841,7 +842,7 @@ void SpdyStream::QueueNextDataFrame() { CHECK_GT(pending_send_data_->BytesRemaining(), 0); SpdyDataFlags flags = - (send_status_ == NO_MORE_DATA_TO_SEND) ? + (pending_send_status_ == NO_MORE_DATA_TO_SEND) ? DATA_FLAG_FIN : DATA_FLAG_NONE; scoped_ptr<SpdyBuffer> data_buffer( session_->CreateDataBuffer(stream_id_, diff --git a/net/spdy/spdy_stream.h b/net/spdy/spdy_stream.h index 6010e81..6031dc8 100644 --- a/net/spdy/spdy_stream.h +++ b/net/spdy/spdy_stream.h @@ -124,6 +124,9 @@ class NET_EXPORT_PRIVATE SpdyStream { // // TODO(akalin): Treat headers received after data has been // received as a protocol error for non-bidirectional streams. + // TODO(jgraettinger): This should be at the semantic (HTTP) rather + // than stream layer. Streams shouldn't have a notion of header + // completeness. Move to SpdyHttpStream/SpdyWebsocketStream. virtual SpdyResponseHeadersStatus OnResponseHeadersUpdated( const SpdyHeaderBlock& response_headers) = 0; @@ -430,18 +433,20 @@ class NET_EXPORT_PRIVATE SpdyStream { // The implementations of each state of the state machine. int DoSendRequestHeaders(); int DoSendRequestHeadersComplete(); - int DoReadHeaders(); - int DoReadHeadersComplete(int result); int DoOpen(); // Update the histograms. Can safely be called repeatedly, but should only // be called after the stream has completed. void UpdateHistograms(); - // When a server-pushed stream is first created, this function is - // posted on the current MessageLoop to replay the data that the - // server has already sent. - void PushedStreamReplayData(); + // When a server-push stream is claimed by SetDelegate(), this function is + // posted on the current MessageLoop to replay everything the server has sent. + // From the perspective of SpdyStream's state machine, headers, data, and + // FIN states received prior to the delegate being attached have not yet been + // read. While buffered by |pending_recv_data_| it's not until + // PushedStreamReplay() is invoked that reads are considered + // to have occurred, driving the state machine forward. + void PushedStreamReplay(); // Produces the SYN_STREAM frame for the stream. The stream must // already be activated. @@ -493,17 +498,22 @@ class NET_EXPORT_PRIVATE SpdyStream { // The transaction should own the delegate. SpdyStream::Delegate* delegate_; - // Whether or not we have more data to send on this stream. - SpdySendStatus send_status_; - // The headers for the request to send. // // TODO(akalin): Hang onto this only until we send it. This // necessitates stashing the URL separately. scoped_ptr<SpdyHeaderBlock> request_headers_; - // The data waiting to be sent. + // Data waiting to be sent, and the close state of the local endpoint + // after the data is fully written. scoped_refptr<DrainableIOBuffer> pending_send_data_; + SpdySendStatus pending_send_status_; + + // Data waiting to be received, and the close state of the remote endpoint + // after the data is fully read. Specifically, data received before the + // delegate is attached must be buffered and later replayed. A remote FIN + // is represented by a final, zero-length buffer. + ScopedVector<SpdyBuffer> pending_recv_data_; // The time at which the request was made that resulted in this response. // For cached responses, this time could be "far" in the past. @@ -534,9 +544,6 @@ class NET_EXPORT_PRIVATE SpdyStream { int send_bytes_; int recv_bytes_; - // Data received before delegate is attached. - ScopedVector<SpdyBuffer> pending_buffers_; - std::string domain_bound_private_key_; std::string domain_bound_cert_; ServerBoundCertService::RequestHandle domain_bound_cert_request_handle_; |