summaryrefslogtreecommitdiffstats
path: root/net/spdy/spdy_stream.cc
diff options
context:
space:
mode:
Diffstat (limited to 'net/spdy/spdy_stream.cc')
-rw-r--r--net/spdy/spdy_stream.cc161
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) {