OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 15 matching lines...) Expand all Loading... |
26 namespace net { | 26 namespace net { |
27 | 27 |
28 SpdyHttpStream::SpdyHttpStream(SpdySession* spdy_session, | 28 SpdyHttpStream::SpdyHttpStream(SpdySession* spdy_session, |
29 bool direct) | 29 bool direct) |
30 : weak_factory_(this), | 30 : weak_factory_(this), |
31 spdy_session_(spdy_session), | 31 spdy_session_(spdy_session), |
32 stream_closed_(false), | 32 stream_closed_(false), |
33 closed_stream_status_(ERR_FAILED), | 33 closed_stream_status_(ERR_FAILED), |
34 closed_stream_id_(0), | 34 closed_stream_id_(0), |
35 request_info_(NULL), | 35 request_info_(NULL), |
36 has_upload_data_(false), | |
37 response_info_(NULL), | 36 response_info_(NULL), |
38 response_headers_received_(false), | 37 response_headers_received_(false), |
39 user_buffer_len_(0), | 38 user_buffer_len_(0), |
40 raw_request_body_buf_size_(0), | 39 request_body_buf_size_(0), |
41 buffered_read_callback_pending_(false), | 40 buffered_read_callback_pending_(false), |
42 more_read_data_pending_(false), | 41 more_read_data_pending_(false), |
43 direct_(direct) {} | 42 direct_(direct) {} |
44 | 43 |
45 void SpdyHttpStream::InitializeWithExistingStream( | 44 void SpdyHttpStream::InitializeWithExistingStream( |
46 const base::WeakPtr<SpdyStream>& spdy_stream) { | 45 const base::WeakPtr<SpdyStream>& spdy_stream) { |
47 stream_ = spdy_stream; | 46 stream_ = spdy_stream; |
48 stream_->SetDelegate(this); | 47 stream_->SetDelegate(this); |
49 response_headers_received_ = true; | 48 response_headers_received_ = true; |
50 } | 49 } |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
91 } | 90 } |
92 | 91 |
93 return rv; | 92 return rv; |
94 } | 93 } |
95 | 94 |
96 const HttpResponseInfo* SpdyHttpStream::GetResponseInfo() const { | 95 const HttpResponseInfo* SpdyHttpStream::GetResponseInfo() const { |
97 return response_info_; | 96 return response_info_; |
98 } | 97 } |
99 | 98 |
100 UploadProgress SpdyHttpStream::GetUploadProgress() const { | 99 UploadProgress SpdyHttpStream::GetUploadProgress() const { |
101 if (!request_info_ || !request_info_->upload_data_stream) | 100 if (!HasUploadData()) |
102 return UploadProgress(); | 101 return UploadProgress(); |
103 | 102 |
104 return UploadProgress(request_info_->upload_data_stream->position(), | 103 return UploadProgress(request_info_->upload_data_stream->position(), |
105 request_info_->upload_data_stream->size()); | 104 request_info_->upload_data_stream->size()); |
106 } | 105 } |
107 | 106 |
108 int SpdyHttpStream::ReadResponseHeaders(const CompletionCallback& callback) { | 107 int SpdyHttpStream::ReadResponseHeaders(const CompletionCallback& callback) { |
109 CHECK(!callback.is_null()); | 108 CHECK(!callback.is_null()); |
110 if (stream_closed_) | 109 if (stream_closed_) |
111 return closed_stream_status_; | 110 return closed_stream_status_; |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
212 base::Time request_time = base::Time::Now(); | 211 base::Time request_time = base::Time::Now(); |
213 CHECK(stream_.get()); | 212 CHECK(stream_.get()); |
214 | 213 |
215 stream_->SetRequestTime(request_time); | 214 stream_->SetRequestTime(request_time); |
216 // This should only get called in the case of a request occurring | 215 // This should only get called in the case of a request occurring |
217 // during server push that has already begun but hasn't finished, | 216 // during server push that has already begun but hasn't finished, |
218 // so we set the response's request time to be the actual one | 217 // so we set the response's request time to be the actual one |
219 if (response_info_) | 218 if (response_info_) |
220 response_info_->request_time = request_time; | 219 response_info_->request_time = request_time; |
221 | 220 |
222 CHECK(!has_upload_data_); | 221 CHECK(!request_body_buf_); |
223 has_upload_data_ = request_info_->upload_data_stream && | 222 if (HasUploadData()) { |
224 (request_info_->upload_data_stream->size() || | |
225 request_info_->upload_data_stream->is_chunked()); | |
226 if (has_upload_data_) { | |
227 // Use kMaxSpdyFrameChunkSize as the buffer size, since the request | 223 // Use kMaxSpdyFrameChunkSize as the buffer size, since the request |
228 // body data is written with this size at a time. | 224 // body data is written with this size at a time. |
229 raw_request_body_buf_ = new IOBufferWithSize(kMaxSpdyFrameChunkSize); | 225 request_body_buf_ = new IOBufferWithSize(kMaxSpdyFrameChunkSize); |
230 // The request body buffer is empty at first. | 226 // The request body buffer is empty at first. |
231 raw_request_body_buf_size_ = 0; | 227 request_body_buf_size_ = 0; |
232 } | 228 } |
233 | 229 |
234 CHECK(!callback.is_null()); | 230 CHECK(!callback.is_null()); |
235 CHECK(response); | 231 CHECK(response); |
236 | 232 |
237 // SendRequest can be called in two cases. | 233 // SendRequest can be called in two cases. |
238 // | 234 // |
239 // a) A client initiated request. In this case, |response_info_| should be | 235 // a) A client initiated request. In this case, |response_info_| should be |
240 // NULL to start with. | 236 // NULL to start with. |
241 // b) A client request which matches a response that the server has already | 237 // b) A client request which matches a response that the server has already |
(...skipping 25 matching lines...) Expand all Loading... |
267 CreateSpdyHeadersFromHttpRequest( | 263 CreateSpdyHeadersFromHttpRequest( |
268 *request_info_, request_headers, | 264 *request_info_, request_headers, |
269 headers.get(), stream_->GetProtocolVersion(), | 265 headers.get(), stream_->GetProtocolVersion(), |
270 direct_); | 266 direct_); |
271 stream_->net_log().AddEvent( | 267 stream_->net_log().AddEvent( |
272 NetLog::TYPE_HTTP_TRANSACTION_SPDY_SEND_REQUEST_HEADERS, | 268 NetLog::TYPE_HTTP_TRANSACTION_SPDY_SEND_REQUEST_HEADERS, |
273 base::Bind(&SpdyHeaderBlockNetLogCallback, headers.get())); | 269 base::Bind(&SpdyHeaderBlockNetLogCallback, headers.get())); |
274 result = | 270 result = |
275 stream_->SendRequestHeaders( | 271 stream_->SendRequestHeaders( |
276 headers.Pass(), | 272 headers.Pass(), |
277 has_upload_data_ ? MORE_DATA_TO_SEND : NO_MORE_DATA_TO_SEND); | 273 HasUploadData() ? MORE_DATA_TO_SEND : NO_MORE_DATA_TO_SEND); |
278 } | 274 } |
279 | 275 |
280 if (result == ERR_IO_PENDING) { | 276 if (result == ERR_IO_PENDING) { |
281 CHECK(callback_.is_null()); | 277 CHECK(callback_.is_null()); |
282 callback_ = callback; | 278 callback_ = callback; |
283 } | 279 } |
284 return result; | 280 return result; |
285 } | 281 } |
286 | 282 |
287 void SpdyHttpStream::Cancel() { | 283 void SpdyHttpStream::Cancel() { |
288 callback_.Reset(); | 284 callback_.Reset(); |
289 if (stream_) { | 285 if (stream_) { |
290 stream_->Cancel(); | 286 stream_->Cancel(); |
291 DCHECK(!stream_); | 287 DCHECK(!stream_); |
292 } | 288 } |
293 } | 289 } |
294 | 290 |
295 void SpdyHttpStream::OnSendRequestHeadersComplete() { | 291 void SpdyHttpStream::OnRequestHeadersSent() { |
296 if (!callback_.is_null()) | 292 if (!callback_.is_null()) |
297 DoCallback(OK); | 293 DoCallback(OK); |
| 294 |
| 295 if (HasUploadData()) |
| 296 ReadAndSendRequestBodyData(); |
298 } | 297 } |
299 | 298 |
300 void SpdyHttpStream::OnSendBody() { | 299 int SpdyHttpStream::OnResponseHeadersReceived(const SpdyHeaderBlock& response, |
301 CHECK(request_info_ && request_info_->upload_data_stream); | 300 base::Time response_time, |
302 if (raw_request_body_buf_size_ > 0) { | 301 int status) { |
303 SendRequestBodyData(); | |
304 } else { | |
305 // We shouldn't be called if there's no more data to read. | |
306 CHECK(!request_info_->upload_data_stream->IsEOF()); | |
307 ReadAndSendRequestBodyData(); | |
308 } | |
309 } | |
310 | |
311 void SpdyHttpStream::OnSendBodyComplete() { | |
312 // |status| is the number of bytes written to the SPDY stream. | |
313 CHECK(request_info_ && request_info_->upload_data_stream); | |
314 raw_request_body_buf_size_ = 0; | |
315 } | |
316 | |
317 int SpdyHttpStream::OnResponseReceived(const SpdyHeaderBlock& response, | |
318 base::Time response_time, | |
319 int status) { | |
320 if (!response_info_) { | 302 if (!response_info_) { |
321 DCHECK_EQ(stream_->type(), SPDY_PUSH_STREAM); | 303 DCHECK_EQ(stream_->type(), SPDY_PUSH_STREAM); |
322 push_response_info_.reset(new HttpResponseInfo); | 304 push_response_info_.reset(new HttpResponseInfo); |
323 response_info_ = push_response_info_.get(); | 305 response_info_ = push_response_info_.get(); |
324 } | 306 } |
325 | 307 |
326 // If the response is already received, these headers are too late. | 308 // If the response is already received, these headers are too late. |
327 if (response_headers_received_) { | 309 if (response_headers_received_) { |
328 LOG(WARNING) << "SpdyHttpStream headers received after response started."; | 310 LOG(WARNING) << "SpdyHttpStream headers received after response started."; |
329 return OK; | 311 return OK; |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
392 if (user_buffer_) { | 374 if (user_buffer_) { |
393 // Handing small chunks of data to the caller creates measurable overhead. | 375 // Handing small chunks of data to the caller creates measurable overhead. |
394 // We buffer data in short time-spans and send a single read notification. | 376 // We buffer data in short time-spans and send a single read notification. |
395 ScheduleBufferedReadCallback(); | 377 ScheduleBufferedReadCallback(); |
396 } | 378 } |
397 } | 379 } |
398 return OK; | 380 return OK; |
399 } | 381 } |
400 | 382 |
401 void SpdyHttpStream::OnDataSent() { | 383 void SpdyHttpStream::OnDataSent() { |
402 // For HTTP streams, no data is sent from the client while in the OPEN state, | 384 request_body_buf_size_ = 0; |
403 // so it is never called. | 385 ReadAndSendRequestBodyData(); |
404 CHECK(false); | |
405 } | 386 } |
406 | 387 |
407 void SpdyHttpStream::OnClose(int status) { | 388 void SpdyHttpStream::OnClose(int status) { |
408 if (stream_) { | 389 if (stream_) { |
409 stream_closed_ = true; | 390 stream_closed_ = true; |
410 closed_stream_status_ = status; | 391 closed_stream_status_ = status; |
411 closed_stream_id_ = stream_->stream_id(); | 392 closed_stream_id_ = stream_->stream_id(); |
412 } | 393 } |
413 stream_.reset(); | 394 stream_.reset(); |
414 bool invoked_callback = false; | 395 bool invoked_callback = false; |
415 if (status == net::OK) { | 396 if (status == net::OK) { |
416 // We need to complete any pending buffered read now. | 397 // We need to complete any pending buffered read now. |
417 invoked_callback = DoBufferedReadCallback(); | 398 invoked_callback = DoBufferedReadCallback(); |
418 } | 399 } |
419 if (!invoked_callback && !callback_.is_null()) | 400 if (!invoked_callback && !callback_.is_null()) |
420 DoCallback(status); | 401 DoCallback(status); |
421 } | 402 } |
422 | 403 |
| 404 bool SpdyHttpStream::HasUploadData() const { |
| 405 CHECK(request_info_); |
| 406 return |
| 407 request_info_->upload_data_stream && |
| 408 ((request_info_->upload_data_stream->size() > 0) || |
| 409 request_info_->upload_data_stream->is_chunked()); |
| 410 } |
| 411 |
423 void SpdyHttpStream::OnStreamCreated( | 412 void SpdyHttpStream::OnStreamCreated( |
424 const CompletionCallback& callback, | 413 const CompletionCallback& callback, |
425 int rv) { | 414 int rv) { |
426 if (rv == OK) { | 415 if (rv == OK) { |
427 stream_ = stream_request_.ReleaseStream(); | 416 stream_ = stream_request_.ReleaseStream(); |
428 stream_->SetDelegate(this); | 417 stream_->SetDelegate(this); |
429 } | 418 } |
430 callback.Run(rv); | 419 callback.Run(rv); |
431 } | 420 } |
432 | 421 |
433 void SpdyHttpStream::ReadAndSendRequestBodyData() { | 422 void SpdyHttpStream::ReadAndSendRequestBodyData() { |
434 CHECK(request_info_ && request_info_->upload_data_stream); | 423 CHECK(HasUploadData()); |
435 CHECK_EQ(raw_request_body_buf_size_, 0); | 424 CHECK_EQ(request_body_buf_size_, 0); |
| 425 |
| 426 if (request_info_->upload_data_stream->IsEOF()) |
| 427 return; |
436 | 428 |
437 // Read the data from the request body stream. | 429 // Read the data from the request body stream. |
438 const int rv = request_info_->upload_data_stream->Read( | 430 const int rv = request_info_->upload_data_stream->Read( |
439 raw_request_body_buf_, raw_request_body_buf_->size(), | 431 request_body_buf_, request_body_buf_->size(), |
440 base::Bind( | 432 base::Bind( |
441 &SpdyHttpStream::OnRequestBodyReadCompleted, | 433 &SpdyHttpStream::OnRequestBodyReadCompleted, |
442 weak_factory_.GetWeakPtr())); | 434 weak_factory_.GetWeakPtr())); |
443 | 435 |
444 if (rv != ERR_IO_PENDING) { | 436 if (rv != ERR_IO_PENDING) { |
445 // ERR_IO_PENDING is the only possible error. | 437 // ERR_IO_PENDING is the only possible error. |
446 CHECK_GE(rv, 0); | 438 CHECK_GE(rv, 0); |
447 OnRequestBodyReadCompleted(rv); | 439 OnRequestBodyReadCompleted(rv); |
448 } | 440 } |
449 } | 441 } |
450 | 442 |
451 void SpdyHttpStream::OnRequestBodyReadCompleted(int status) { | 443 void SpdyHttpStream::OnRequestBodyReadCompleted(int status) { |
452 CHECK_GE(status, 0); | 444 CHECK_GE(status, 0); |
453 raw_request_body_buf_size_ = status; | 445 request_body_buf_size_ = status; |
454 SendRequestBodyData(); | |
455 } | |
456 | |
457 void SpdyHttpStream::SendRequestBodyData() { | |
458 const bool eof = request_info_->upload_data_stream->IsEOF(); | 446 const bool eof = request_info_->upload_data_stream->IsEOF(); |
459 if (eof) { | 447 if (eof) { |
460 CHECK_GE(raw_request_body_buf_size_, 0); | 448 CHECK_GE(request_body_buf_size_, 0); |
461 } else { | 449 } else { |
462 CHECK_GT(raw_request_body_buf_size_, 0); | 450 CHECK_GT(request_body_buf_size_, 0); |
463 } | 451 } |
464 stream_->SendStreamData(raw_request_body_buf_, | 452 stream_->SendData(request_body_buf_, |
465 raw_request_body_buf_size_, | 453 request_body_buf_size_, |
466 eof ? NO_MORE_DATA_TO_SEND : MORE_DATA_TO_SEND); | 454 eof ? NO_MORE_DATA_TO_SEND : MORE_DATA_TO_SEND); |
467 } | 455 } |
468 | 456 |
469 void SpdyHttpStream::ScheduleBufferedReadCallback() { | 457 void SpdyHttpStream::ScheduleBufferedReadCallback() { |
470 // If there is already a scheduled DoBufferedReadCallback, don't issue | 458 // If there is already a scheduled DoBufferedReadCallback, don't issue |
471 // another one. Mark that we have received more data and return. | 459 // another one. Mark that we have received more data and return. |
472 if (buffered_read_callback_pending_) { | 460 if (buffered_read_callback_pending_) { |
473 more_read_data_pending_ = true; | 461 more_read_data_pending_ = true; |
474 return; | 462 return; |
475 } | 463 } |
476 | 464 |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
555 bool SpdyHttpStream::IsSpdyHttpStream() const { | 543 bool SpdyHttpStream::IsSpdyHttpStream() const { |
556 return true; | 544 return true; |
557 } | 545 } |
558 | 546 |
559 void SpdyHttpStream::Drain(HttpNetworkSession* session) { | 547 void SpdyHttpStream::Drain(HttpNetworkSession* session) { |
560 Close(false); | 548 Close(false); |
561 delete this; | 549 delete this; |
562 } | 550 } |
563 | 551 |
564 } // namespace net | 552 } // namespace net |
OLD | NEW |