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 |