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_http_stream.h" | 5 #include "net/spdy/spdy_http_stream.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <list> | 8 #include <list> |
9 #include <string> | 9 #include <string> |
10 | 10 |
(...skipping 17 matching lines...) Expand all Loading... |
28 : ALLOW_THIS_IN_INITIALIZER_LIST(read_callback_factory_(this)), | 28 : ALLOW_THIS_IN_INITIALIZER_LIST(read_callback_factory_(this)), |
29 stream_(NULL), | 29 stream_(NULL), |
30 spdy_session_(spdy_session), | 30 spdy_session_(spdy_session), |
31 response_info_(NULL), | 31 response_info_(NULL), |
32 download_finished_(false), | 32 download_finished_(false), |
33 response_headers_received_(false), | 33 response_headers_received_(false), |
34 user_callback_(NULL), | 34 user_callback_(NULL), |
35 user_buffer_len_(0), | 35 user_buffer_len_(0), |
36 buffered_read_callback_pending_(false), | 36 buffered_read_callback_pending_(false), |
37 more_read_data_pending_(false), | 37 more_read_data_pending_(false), |
38 direct_(direct) { } | 38 direct_(direct), |
| 39 send_last_chunk_(false) { } |
39 | 40 |
40 void SpdyHttpStream::InitializeWithExistingStream(SpdyStream* spdy_stream) { | 41 void SpdyHttpStream::InitializeWithExistingStream(SpdyStream* spdy_stream) { |
41 stream_ = spdy_stream; | 42 stream_ = spdy_stream; |
42 stream_->SetDelegate(this); | 43 stream_->SetDelegate(this); |
43 response_headers_received_ = true; | 44 response_headers_received_ = true; |
44 } | 45 } |
45 | 46 |
46 SpdyHttpStream::~SpdyHttpStream() { | 47 SpdyHttpStream::~SpdyHttpStream() { |
47 if (stream_) | 48 if (stream_) |
48 stream_->DetachDelegate(); | 49 stream_->DetachDelegate(); |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
170 } | 171 } |
171 | 172 |
172 bool SpdyHttpStream::IsConnectionReused() const { | 173 bool SpdyHttpStream::IsConnectionReused() const { |
173 return spdy_session_->IsReused(); | 174 return spdy_session_->IsReused(); |
174 } | 175 } |
175 | 176 |
176 void SpdyHttpStream::SetConnectionReused() { | 177 void SpdyHttpStream::SetConnectionReused() { |
177 // SPDY doesn't need an indicator here. | 178 // SPDY doesn't need an indicator here. |
178 } | 179 } |
179 | 180 |
| 181 void SpdyHttpStream::set_chunk_callback(ChunkCallback* callback) { |
| 182 if (request_body_stream_ != NULL) |
| 183 request_body_stream_->set_chunk_callback(callback); |
| 184 } |
| 185 |
180 int SpdyHttpStream::SendRequest(const HttpRequestHeaders& request_headers, | 186 int SpdyHttpStream::SendRequest(const HttpRequestHeaders& request_headers, |
181 UploadDataStream* request_body, | 187 UploadDataStream* request_body, |
182 HttpResponseInfo* response, | 188 HttpResponseInfo* response, |
183 CompletionCallback* callback) { | 189 CompletionCallback* callback) { |
184 base::Time request_time = base::Time::Now(); | 190 base::Time request_time = base::Time::Now(); |
185 CHECK(stream_.get()); | 191 CHECK(stream_.get()); |
186 | 192 |
187 stream_->SetDelegate(this); | 193 stream_->SetDelegate(this); |
188 | 194 |
189 linked_ptr<spdy::SpdyHeaderBlock> headers(new spdy::SpdyHeaderBlock); | 195 linked_ptr<spdy::SpdyHeaderBlock> headers(new spdy::SpdyHeaderBlock); |
190 CreateSpdyHeadersFromHttpRequest(*request_info_, request_headers, | 196 CreateSpdyHeadersFromHttpRequest(*request_info_, request_headers, |
191 headers.get(), direct_); | 197 headers.get(), direct_); |
192 stream_->set_spdy_headers(headers); | 198 stream_->set_spdy_headers(headers); |
193 | 199 |
194 stream_->SetRequestTime(request_time); | 200 stream_->SetRequestTime(request_time); |
195 // This should only get called in the case of a request occurring | 201 // This should only get called in the case of a request occurring |
196 // during server push that has already begun but hasn't finished, | 202 // during server push that has already begun but hasn't finished, |
197 // so we set the response's request time to be the actual one | 203 // so we set the response's request time to be the actual one |
198 if (response_info_) | 204 if (response_info_) |
199 response_info_->request_time = request_time; | 205 response_info_->request_time = request_time; |
200 | 206 |
201 CHECK(!request_body_stream_.get()); | 207 CHECK(!request_body_stream_.get()); |
202 if (request_body) { | 208 if (request_body) { |
203 if (request_body->size()) | 209 if (request_body->size() || request_body->is_chunked()) |
204 request_body_stream_.reset(request_body); | 210 request_body_stream_.reset(request_body); |
205 else | 211 else |
206 delete request_body; | 212 delete request_body; |
207 } | 213 } |
208 | 214 |
209 CHECK(callback); | 215 CHECK(callback); |
210 CHECK(!stream_->cancelled()); | 216 CHECK(!stream_->cancelled()); |
211 CHECK(response); | 217 CHECK(response); |
212 | 218 |
213 if (!stream_->pushed() && stream_->closed()) { | 219 if (!stream_->pushed() && stream_->closed()) { |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
257 } | 263 } |
258 | 264 |
259 bool SpdyHttpStream::OnSendHeadersComplete(int status) { | 265 bool SpdyHttpStream::OnSendHeadersComplete(int status) { |
260 if (user_callback_) | 266 if (user_callback_) |
261 DoCallback(status); | 267 DoCallback(status); |
262 return request_body_stream_.get() == NULL; | 268 return request_body_stream_.get() == NULL; |
263 } | 269 } |
264 | 270 |
265 int SpdyHttpStream::OnSendBody() { | 271 int SpdyHttpStream::OnSendBody() { |
266 CHECK(request_body_stream_.get()); | 272 CHECK(request_body_stream_.get()); |
| 273 if (send_last_chunk_) { |
| 274 return stream_->WriteStreamData(request_body_stream_->buf(), 0, |
| 275 spdy::DATA_FLAG_FIN); |
| 276 } |
| 277 |
267 int buf_len = static_cast<int>(request_body_stream_->buf_len()); | 278 int buf_len = static_cast<int>(request_body_stream_->buf_len()); |
268 if (!buf_len) | 279 if (!buf_len) |
269 return OK; | 280 return OK; |
270 return stream_->WriteStreamData(request_body_stream_->buf(), buf_len, | 281 bool is_chunked = request_body_stream_->is_chunked(); |
271 spdy::DATA_FLAG_FIN); | 282 return stream_->WriteStreamData( |
| 283 request_body_stream_->buf(), buf_len, |
| 284 is_chunked ? spdy::DATA_FLAG_NONE : spdy::DATA_FLAG_FIN); |
272 } | 285 } |
273 | 286 |
274 bool SpdyHttpStream::OnSendBodyComplete(int status) { | 287 int SpdyHttpStream::OnSendBodyComplete(int status, bool* eof) { |
275 CHECK(request_body_stream_.get()); | 288 CHECK(request_body_stream_.get()); |
| 289 |
| 290 if (send_last_chunk_) { // Indicates that the last chunk was SENT here. |
| 291 if (status != 0) { |
| 292 NOTREACHED(); |
| 293 return ERR_UNEXPECTED; |
| 294 } |
| 295 *eof = true; |
| 296 return OK; |
| 297 } |
| 298 |
276 request_body_stream_->MarkConsumedAndFillBuffer(status); | 299 request_body_stream_->MarkConsumedAndFillBuffer(status); |
277 return request_body_stream_->eof(); | 300 if (request_body_stream_->is_chunked()) { |
| 301 *eof = false; |
| 302 if (request_body_stream_->eof()) { |
| 303 send_last_chunk_ = true; |
| 304 } else { |
| 305 if (!request_body_stream_->buf_len()) |
| 306 return ERR_IO_PENDING; |
| 307 } |
| 308 } else { |
| 309 *eof = request_body_stream_->eof(); |
| 310 } |
| 311 |
| 312 return OK; |
278 } | 313 } |
279 | 314 |
280 int SpdyHttpStream::OnResponseReceived(const spdy::SpdyHeaderBlock& response, | 315 int SpdyHttpStream::OnResponseReceived(const spdy::SpdyHeaderBlock& response, |
281 base::Time response_time, | 316 base::Time response_time, |
282 int status) { | 317 int status) { |
283 if (!response_info_) { | 318 if (!response_info_) { |
284 DCHECK(stream_->pushed()); | 319 DCHECK(stream_->pushed()); |
285 push_response_info_.reset(new HttpResponseInfo); | 320 push_response_info_.reset(new HttpResponseInfo); |
286 response_info_ = push_response_info_.get(); | 321 response_info_ = push_response_info_.get(); |
287 } | 322 } |
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
436 stream_->GetSSLInfo(ssl_info, &using_npn); | 471 stream_->GetSSLInfo(ssl_info, &using_npn); |
437 } | 472 } |
438 | 473 |
439 void SpdyHttpStream::GetSSLCertRequestInfo( | 474 void SpdyHttpStream::GetSSLCertRequestInfo( |
440 SSLCertRequestInfo* cert_request_info) { | 475 SSLCertRequestInfo* cert_request_info) { |
441 DCHECK(stream_); | 476 DCHECK(stream_); |
442 stream_->GetSSLCertRequestInfo(cert_request_info); | 477 stream_->GetSSLCertRequestInfo(cert_request_info); |
443 } | 478 } |
444 | 479 |
445 } // namespace net | 480 } // namespace net |
OLD | NEW |