summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/spdy/spdy_stream.cc45
-rw-r--r--net/spdy/spdy_stream.h33
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_;