| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/spdy/spdy_stream.h" | 5 #include "net/spdy/spdy_stream.h" |
| 6 | 6 |
| 7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "base/message_loop.h" | 8 #include "base/message_loop.h" |
| 9 #include "base/singleton.h" | 9 #include "base/singleton.h" |
| 10 #include "net/spdy/spdy_session.h" | 10 #include "net/spdy/spdy_session.h" |
| (...skipping 10 matching lines...) Expand all Loading... |
| 21 session_(session), | 21 session_(session), |
| 22 delegate_(NULL), | 22 delegate_(NULL), |
| 23 request_time_(base::Time::Now()), | 23 request_time_(base::Time::Now()), |
| 24 response_(new spdy::SpdyHeaderBlock), | 24 response_(new spdy::SpdyHeaderBlock), |
| 25 response_complete_(false), | 25 response_complete_(false), |
| 26 io_state_(STATE_NONE), | 26 io_state_(STATE_NONE), |
| 27 response_status_(OK), | 27 response_status_(OK), |
| 28 cancelled_(false), | 28 cancelled_(false), |
| 29 send_bytes_(0), | 29 send_bytes_(0), |
| 30 recv_bytes_(0), | 30 recv_bytes_(0), |
| 31 histograms_recorded_(false), | 31 histograms_recorded_(false) {} |
| 32 half_closed_client_side_(false), | |
| 33 half_closed_server_side_(false) {} | |
| 34 | 32 |
| 35 SpdyStream::~SpdyStream() { | 33 SpdyStream::~SpdyStream() { |
| 36 DLOG(INFO) << "Deleting SpdyStream for stream " << stream_id_; | 34 DLOG(INFO) << "Deleting SpdyStream for stream " << stream_id_; |
| 37 | 35 |
| 38 // When the stream_id_ is 0, we expect that it is because | 36 // When the stream_id_ is 0, we expect that it is because |
| 39 // we've cancelled or closed the stream and set the stream_id to 0. | 37 // we've cancelled or closed the stream and set the stream_id to 0. |
| 40 if (!stream_id_) | 38 if (!stream_id_) |
| 41 DCHECK(response_complete_); | 39 DCHECK(response_complete_); |
| 42 } | 40 } |
| 43 | 41 |
| 44 void SpdyStream::SetDelegate(Delegate* delegate) { | 42 void SpdyStream::SetDelegate(Delegate* delegate) { |
| 45 CHECK(delegate); | 43 CHECK(delegate); |
| 46 delegate_ = delegate; | 44 delegate_ = delegate; |
| 47 | 45 |
| 48 if (!response_->empty()) { | 46 if (!response_->empty()) { |
| 49 // The stream already got response. | 47 // The stream already got response. |
| 50 delegate_->OnResponseReceived(*response_, response_time_, OK); | 48 delegate_->OnResponseReceived(*response_, response_time_, OK); |
| 51 } | 49 } |
| 52 | 50 |
| 53 std::vector<scoped_refptr<IOBufferWithSize> > buffers; | 51 std::vector<scoped_refptr<IOBufferWithSize> > buffers; |
| 54 buffers.swap(pending_buffers_); | 52 buffers.swap(pending_buffers_); |
| 55 for (size_t i = 0; i < buffers.size(); ++i) { | 53 for (size_t i = 0; i < buffers.size(); ++i) { |
| 56 if (delegate_) | 54 if (delegate_) |
| 57 delegate_->OnDataReceived(buffers[i]->data(), buffers[i]->size()); | 55 delegate_->OnDataReceived(buffers[i]->data(), buffers[i]->size()); |
| 58 } | 56 } |
| 59 } | 57 } |
| 60 | 58 |
| 61 void SpdyStream::DetachDelegate() { | 59 void SpdyStream::DetachDelegate() { |
| 62 delegate_ = NULL; | 60 delegate_ = NULL; |
| 63 if (!half_closed_client_side()) | 61 if (!cancelled()) |
| 64 session_->CloseStream(stream_id_, ERR_ABORTED); | 62 Cancel(); |
| 65 } | 63 } |
| 66 | 64 |
| 67 const linked_ptr<spdy::SpdyHeaderBlock>& SpdyStream::spdy_headers() const { | 65 const linked_ptr<spdy::SpdyHeaderBlock>& SpdyStream::spdy_headers() const { |
| 68 return request_; | 66 return request_; |
| 69 } | 67 } |
| 70 | 68 |
| 71 void SpdyStream::set_spdy_headers( | 69 void SpdyStream::set_spdy_headers( |
| 72 const linked_ptr<spdy::SpdyHeaderBlock>& headers) { | 70 const linked_ptr<spdy::SpdyHeaderBlock>& headers) { |
| 73 request_ = headers; | 71 request_ = headers; |
| 74 } | 72 } |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 124 LOG(INFO) << "SpdyStream: Data (" << length << " bytes) received for " | 122 LOG(INFO) << "SpdyStream: Data (" << length << " bytes) received for " |
| 125 << stream_id_; | 123 << stream_id_; |
| 126 | 124 |
| 127 CHECK(!response_complete_); | 125 CHECK(!response_complete_); |
| 128 | 126 |
| 129 // If we don't have a response, then the SYN_REPLY did not come through. | 127 // If we don't have a response, then the SYN_REPLY did not come through. |
| 130 // We cannot pass data up to the caller unless the reply headers have been | 128 // We cannot pass data up to the caller unless the reply headers have been |
| 131 // received. | 129 // received. |
| 132 if (response_->empty()) { | 130 if (response_->empty()) { |
| 133 session_->CloseStream(stream_id_, ERR_SYN_REPLY_NOT_RECEIVED); | 131 session_->CloseStream(stream_id_, ERR_SYN_REPLY_NOT_RECEIVED); |
| 134 //session_->CloseStreamAndSendRst(stream_id_, ERR_SYN_REPLY_NOT_RECEIVED); | |
| 135 // TODO(erikchen): We should close the session here. | |
| 136 return; | 132 return; |
| 137 } | 133 } |
| 138 | 134 |
| 139 // A zero-length read means that the stream is being closed. | 135 // A zero-length read means that the stream is being closed. |
| 140 if (!length) { | 136 if (!length) { |
| 141 metrics_.StopStream(); | 137 metrics_.StopStream(); |
| 142 scoped_refptr<SpdyStream> self(this); | 138 scoped_refptr<SpdyStream> self(this); |
| 143 session_->CloseStream(stream_id_, net::OK); | 139 session_->CloseStream(stream_id_, net::OK); |
| 144 UpdateHistograms(); | 140 UpdateHistograms(); |
| 145 return; | 141 return; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 156 IOBufferWithSize* buf = new IOBufferWithSize(length); | 152 IOBufferWithSize* buf = new IOBufferWithSize(length); |
| 157 memcpy(buf->data(), data, length); | 153 memcpy(buf->data(), data, length); |
| 158 pending_buffers_.push_back(buf); | 154 pending_buffers_.push_back(buf); |
| 159 return; | 155 return; |
| 160 } | 156 } |
| 161 | 157 |
| 162 delegate_->OnDataReceived(data, length); | 158 delegate_->OnDataReceived(data, length); |
| 163 } | 159 } |
| 164 | 160 |
| 165 void SpdyStream::OnWriteComplete(int status) { | 161 void SpdyStream::OnWriteComplete(int status) { |
| 166 // Behavior for status==0 is undefined, and should never happen. This should | 162 // TODO(mbelshe): Check for cancellation here. If we're cancelled, we |
| 167 // have already been checked prior to calling this function. | 163 // should discontinue the DoLoop. |
| 168 DCHECK_NE(status, 0); | |
| 169 | 164 |
| 170 // It is possible that this stream was closed or cancelled while we had a | 165 // It is possible that this stream was closed while we had a write pending. |
| 171 // write pending. | 166 if (response_complete_) |
| 172 if (response_complete_ || cancelled_) | |
| 173 return; | 167 return; |
| 174 | 168 |
| 175 if (status > 0) | 169 if (status > 0) |
| 176 send_bytes_ += status; | 170 send_bytes_ += status; |
| 177 | 171 |
| 178 DoLoop(status); | 172 DoLoop(status); |
| 179 } | 173 } |
| 180 | 174 |
| 181 void SpdyStream::OnClose(int status) { | 175 void SpdyStream::OnClose(int status) { |
| 182 response_complete_ = true; | 176 response_complete_ = true; |
| 183 response_status_ = status; | 177 response_status_ = status; |
| 184 stream_id_ = 0; | 178 stream_id_ = 0; |
| 185 Delegate* delegate = delegate_; | 179 Delegate* delegate = delegate_; |
| 186 delegate_ = NULL; | 180 delegate_ = NULL; |
| 187 if (delegate) | 181 if (delegate) |
| 188 delegate->OnClose(status); | 182 delegate->OnClose(status); |
| 189 } | 183 } |
| 190 | 184 |
| 191 void SpdyStream::Cancel() { | 185 void SpdyStream::Cancel() { |
| 192 cancelled_ = true; | 186 cancelled_ = true; |
| 193 if (!half_closed_client_side()) | 187 session_->CloseStream(stream_id_, ERR_ABORTED); |
| 194 session_->CloseStreamAndSendRst(stream_id_, ERR_ABORTED); | |
| 195 } | 188 } |
| 196 | 189 |
| 197 int SpdyStream::DoSendRequest(bool has_upload_data) { | 190 int SpdyStream::DoSendRequest(bool has_upload_data) { |
| 198 CHECK(!cancelled_); | 191 CHECK(!cancelled_); |
| 199 | 192 |
| 200 if (!pushed_) { | 193 if (!pushed_) { |
| 201 spdy::SpdyControlFlags flags = spdy::CONTROL_FLAG_NONE; | 194 spdy::SpdyControlFlags flags = spdy::CONTROL_FLAG_NONE; |
| 202 if (!has_upload_data) | 195 if (!has_upload_data) |
| 203 flags = spdy::CONTROL_FLAG_FIN; | 196 flags = spdy::CONTROL_FLAG_FIN; |
| 204 | 197 |
| (...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 406 UMA_HISTOGRAM_TIMES("Net.SpdyStreamDownloadTime", | 399 UMA_HISTOGRAM_TIMES("Net.SpdyStreamDownloadTime", |
| 407 recv_last_byte_time_ - recv_first_byte_time_); | 400 recv_last_byte_time_ - recv_first_byte_time_); |
| 408 UMA_HISTOGRAM_TIMES("Net.SpdyStreamTime", | 401 UMA_HISTOGRAM_TIMES("Net.SpdyStreamTime", |
| 409 recv_last_byte_time_ - send_time_); | 402 recv_last_byte_time_ - send_time_); |
| 410 | 403 |
| 411 UMA_HISTOGRAM_COUNTS("Net.SpdySendBytes", send_bytes_); | 404 UMA_HISTOGRAM_COUNTS("Net.SpdySendBytes", send_bytes_); |
| 412 UMA_HISTOGRAM_COUNTS("Net.SpdyRecvBytes", recv_bytes_); | 405 UMA_HISTOGRAM_COUNTS("Net.SpdyRecvBytes", recv_bytes_); |
| 413 } | 406 } |
| 414 | 407 |
| 415 } // namespace net | 408 } // namespace net |
| OLD | NEW |