diff options
Diffstat (limited to 'net/spdy/spdy_stream.cc')
-rw-r--r-- | net/spdy/spdy_stream.cc | 161 |
1 files changed, 90 insertions, 71 deletions
diff --git a/net/spdy/spdy_stream.cc b/net/spdy/spdy_stream.cc index baff2b9..3fbde08 100644 --- a/net/spdy/spdy_stream.cc +++ b/net/spdy/spdy_stream.cc @@ -7,8 +7,6 @@ #include "base/logging.h" #include "base/message_loop.h" #include "base/singleton.h" -#include "net/http/http_request_info.h" -#include "net/http/http_response_info.h" #include "net/spdy/spdy_session.h" namespace net { @@ -20,8 +18,9 @@ SpdyStream::SpdyStream( pushed_(pushed), metrics_(Singleton<BandwidthMetrics>::get()), session_(session), + delegate_(NULL), request_time_(base::Time::Now()), - response_(NULL), + response_(new spdy::SpdyHeaderBlock), response_complete_(false), io_state_(STATE_NONE), response_status_(OK), @@ -39,23 +38,36 @@ SpdyStream::~SpdyStream() { DCHECK(response_complete_); } -const HttpResponseInfo* SpdyStream::GetResponseInfo() const { - return response_; +void SpdyStream::SetDelegate(Delegate* delegate) { + CHECK(delegate); + delegate_ = delegate; + + if (!response_->empty()) { + // The stream already got response. + delegate_->OnResponseReceived(*response_, response_time_, OK); + } + + std::vector<scoped_refptr<IOBufferWithSize> > buffers; + buffers.swap(pending_buffers_); + for (size_t i = 0; i < buffers.size(); ++i) { + if (delegate_) + delegate_->OnDataReceived(buffers[i]->data(), buffers[i]->size()); + } } -void SpdyStream::SetPushResponse(HttpResponseInfo* response_info) { - DCHECK(!response_); - DCHECK(!push_response_.get()); - push_response_.reset(response_info); - response_ = response_info; +void SpdyStream::DetachDelegate() { + delegate_ = NULL; + if (!cancelled()) + Cancel(); } -const HttpRequestInfo* SpdyStream::GetRequestInfo() const { - return &request_; +const linked_ptr<spdy::SpdyHeaderBlock>& SpdyStream::spdy_headers() const { + return request_; } -void SpdyStream::SetRequestInfo(const HttpRequestInfo& request) { - request_ = request; +void SpdyStream::set_spdy_headers( + const linked_ptr<spdy::SpdyHeaderBlock>& headers) { + request_ = headers; } base::Time SpdyStream::GetRequestTime() const { @@ -64,25 +76,20 @@ base::Time SpdyStream::GetRequestTime() const { void SpdyStream::SetRequestTime(base::Time t) { request_time_ = t; - - // This should only get called in the case of a request occuring - // during server push that has already begun but hasn't finished, - // so we set the response's request time to be the actual one - if (response_) - response_->request_time = request_time_; } -int SpdyStream::DoOnResponseReceived(const HttpResponseInfo& response) { +int SpdyStream::OnResponseReceived(const spdy::SpdyHeaderBlock& response) { int rv = OK; + LOG(INFO) << "OnResponseReceived"; metrics_.StartStream(); - CHECK(!response_->headers); - - *response_ = response; // TODO(mbelshe): avoid copy. - DCHECK(response_->headers); + DCHECK(response_->empty()); + *response_ = response; // TODO(ukai): avoid copy. + DCHECK(!response_->empty()); recv_first_byte_time_ = base::TimeTicks::Now(); + response_time_ = base::Time::Now(); if (io_state_ == STATE_NONE) { CHECK(pushed_); @@ -101,11 +108,15 @@ int SpdyStream::DoOnResponseReceived(const HttpResponseInfo& response) { } rv = DoLoop(rv); + if (delegate_) + rv = delegate_->OnResponseReceived(*response_, response_time_, rv); + // if delegate_ is not yet attached, we'll return response when delegate + // gets attached to the stream. return rv; } -bool SpdyStream::DoOnDataReceived(const char* data, int length) { +void SpdyStream::OnDataReceived(const char* data, int length) { DCHECK_GE(length, 0); LOG(INFO) << "SpdyStream: Data (" << length << " bytes) received for " << stream_id_; @@ -115,9 +126,9 @@ bool SpdyStream::DoOnDataReceived(const char* data, int length) { // If we don't have a response, then the SYN_REPLY did not come through. // We cannot pass data up to the caller unless the reply headers have been // received. - if (!response_->headers) { + if (response_->empty()) { session_->CloseStream(stream_id_, ERR_SYN_REPLY_NOT_RECEIVED); - return false; + return; } // A zero-length read means that the stream is being closed. @@ -126,7 +137,7 @@ bool SpdyStream::DoOnDataReceived(const char* data, int length) { scoped_refptr<SpdyStream> self(this); session_->CloseStream(stream_id_, net::OK); UpdateHistograms(); - return true; + return; } // Track our bandwidth. @@ -134,10 +145,19 @@ bool SpdyStream::DoOnDataReceived(const char* data, int length) { recv_bytes_ += length; recv_last_byte_time_ = base::TimeTicks::Now(); - return true; + if (!delegate_) { + // 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. + IOBufferWithSize* buf = new IOBufferWithSize(length); + memcpy(buf->data(), data, length); + pending_buffers_.push_back(buf); + return; + } + + delegate_->OnDataReceived(data, length); } -void SpdyStream::DoOnWriteComplete(int status) { +void SpdyStream::OnWriteComplete(int status) { // TODO(mbelshe): Check for cancellation here. If we're cancelled, we // should discontinue the DoLoop. @@ -151,45 +171,35 @@ void SpdyStream::DoOnWriteComplete(int status) { DoLoop(status); } -void SpdyStream::DoOnClose(int status) { +void SpdyStream::OnClose(int status) { response_complete_ = true; response_status_ = status; stream_id_ = 0; + Delegate* delegate = delegate_; + delegate_ = NULL; + if (delegate) + delegate->OnClose(status); } -void SpdyStream::DoCancel() { +void SpdyStream::Cancel() { cancelled_ = true; session_->CloseStream(stream_id_, ERR_ABORTED); } -int SpdyStream::DoSendRequest(UploadDataStream* upload_data, - HttpResponseInfo* response) { +int SpdyStream::DoSendRequest(bool has_upload_data) { CHECK(!cancelled_); - CHECK(response); - - // SendRequest can be called in two cases. - // - // a) A client initiated request. In this case, response_ should be NULL - // to start with. - // b) A client request which matches a response that the server has already - // pushed. In this case, the value of |*push_response_| is copied over to - // the new response object |*response|. |push_response_| is cleared - // and |*push_response_| is deleted, and |response_| is reset to - // |response|. - if (push_response_.get()) { - *response = *push_response_; - push_response_.reset(NULL); - response_ = NULL; - } - - DCHECK_EQ(static_cast<HttpResponseInfo*>(NULL), response_); - response_ = response; - if (upload_data) { - if (upload_data->size()) - request_body_stream_.reset(upload_data); - else - delete upload_data; + if (!pushed_) { + spdy::SpdyControlFlags flags = spdy::CONTROL_FLAG_NONE; + if (!has_upload_data) + flags = spdy::CONTROL_FLAG_FIN; + + CHECK(request_.get()); + int result = session_->WriteSynStream( + stream_id_, static_cast<RequestPriority>(priority_), flags, + request_); + if (result != ERR_IO_PENDING) + return result; } send_time_ = base::TimeTicks::Now(); @@ -198,7 +208,7 @@ int SpdyStream::DoSendRequest(UploadDataStream* upload_data, if (!pushed_) io_state_ = STATE_SEND_HEADERS; else { - if (response_->headers) { + if (!response_->empty()) { io_state_ = STATE_READ_BODY; } else { io_state_ = STATE_READ_HEADERS; @@ -212,7 +222,7 @@ int SpdyStream::DoReadResponseHeaders() { CHECK(!cancelled_); // The SYN_REPLY has already been received. - if (response_->headers) + if (!response_->empty()) return OK; io_state_ = STATE_READ_HEADERS; @@ -220,6 +230,14 @@ int SpdyStream::DoReadResponseHeaders() { return ERR_IO_PENDING; } +int SpdyStream::WriteStreamData(IOBuffer* data, int length) { + return session_->WriteStreamData(stream_id_, data, length); +} + +bool SpdyStream::GetSSLInfo(SSLInfo* ssl_info, bool* was_npn_negotiated) { + return session_->GetSSLInfo(ssl_info, was_npn_negotiated); +} + int SpdyStream::DoLoop(int result) { do { State state = io_state_; @@ -295,8 +313,11 @@ int SpdyStream::DoSendHeadersComplete(int result) { CHECK_GT(result, 0); + if (!delegate_) + return ERR_UNEXPECTED; + // There is no body, skip that state. - if (!request_body_stream_.get()) { + if (delegate_->OnSendHeadersComplete(result)) { io_state_ = STATE_READ_HEADERS; return OK; } @@ -314,12 +335,9 @@ int SpdyStream::DoSendBody() { // the number of bytes in the frame that were written, only consume the // data portion, of course. io_state_ = STATE_SEND_BODY_COMPLETE; - int buf_len = static_cast<int>(request_body_stream_->buf_len()); - if (!buf_len) - return OK; - return session_->WriteStreamData(stream_id_, - request_body_stream_->buf(), - buf_len); + if (!delegate_) + return ERR_UNEXPECTED; + return delegate_->OnSendBody(); } int SpdyStream::DoSendBodyComplete(int result) { @@ -328,9 +346,10 @@ int SpdyStream::DoSendBodyComplete(int result) { CHECK_NE(result, 0); - request_body_stream_->DidConsume(result); + if (!delegate_) + return ERR_UNEXPECTED; - if (!request_body_stream_->eof()) + if (!delegate_->OnSendBodyComplete(result)) io_state_ = STATE_SEND_BODY; else io_state_ = STATE_READ_HEADERS; @@ -340,7 +359,7 @@ int SpdyStream::DoSendBodyComplete(int result) { int SpdyStream::DoReadHeaders() { io_state_ = STATE_READ_HEADERS_COMPLETE; - return response_->headers ? OK : ERR_IO_PENDING; + return !response_->empty() ? OK : ERR_IO_PENDING; } int SpdyStream::DoReadHeadersComplete(int result) { |