| 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 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 134 CHECK(!callback.is_null()); | 134 CHECK(!callback.is_null()); |
| 135 | 135 |
| 136 // If we have data buffered, complete the IO immediately. | 136 // If we have data buffered, complete the IO immediately. |
| 137 if (!response_body_queue_.IsEmpty()) { | 137 if (!response_body_queue_.IsEmpty()) { |
| 138 return response_body_queue_.Dequeue(buf->data(), buf_len); | 138 return response_body_queue_.Dequeue(buf->data(), buf_len); |
| 139 } else if (stream_closed_) { | 139 } else if (stream_closed_) { |
| 140 return closed_stream_status_; | 140 return closed_stream_status_; |
| 141 } | 141 } |
| 142 | 142 |
| 143 CHECK(callback_.is_null()); | 143 CHECK(callback_.is_null()); |
| 144 CHECK(!user_buffer_); | 144 CHECK(!user_buffer_.get()); |
| 145 CHECK_EQ(0, user_buffer_len_); | 145 CHECK_EQ(0, user_buffer_len_); |
| 146 | 146 |
| 147 callback_ = callback; | 147 callback_ = callback; |
| 148 user_buffer_ = buf; | 148 user_buffer_ = buf; |
| 149 user_buffer_len_ = buf_len; | 149 user_buffer_len_ = buf_len; |
| 150 return ERR_IO_PENDING; | 150 return ERR_IO_PENDING; |
| 151 } | 151 } |
| 152 | 152 |
| 153 void SpdyHttpStream::Close(bool not_reusable) { | 153 void SpdyHttpStream::Close(bool not_reusable) { |
| 154 // Note: the not_reusable flag has no meaning for SPDY streams. | 154 // Note: the not_reusable flag has no meaning for SPDY streams. |
| (...skipping 25 matching lines...) Expand all Loading... |
| 180 bool SpdyHttpStream::IsConnectionReusable() const { | 180 bool SpdyHttpStream::IsConnectionReusable() const { |
| 181 // SPDY streams aren't considered reusable. | 181 // SPDY streams aren't considered reusable. |
| 182 return false; | 182 return false; |
| 183 } | 183 } |
| 184 | 184 |
| 185 bool SpdyHttpStream::GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const { | 185 bool SpdyHttpStream::GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const { |
| 186 // If |stream_| has yet to be created, or does not yet have an ID, fail. | 186 // If |stream_| has yet to be created, or does not yet have an ID, fail. |
| 187 // The reused flag can only be correctly set once a stream has an ID. Streams | 187 // The reused flag can only be correctly set once a stream has an ID. Streams |
| 188 // get their IDs once the request has been successfully sent, so this does not | 188 // get their IDs once the request has been successfully sent, so this does not |
| 189 // behave that differently from other stream types. | 189 // behave that differently from other stream types. |
| 190 if (!spdy_session_ || (!stream_ && !stream_closed_)) | 190 if (!spdy_session_.get() || (!stream_ && !stream_closed_)) |
| 191 return false; | 191 return false; |
| 192 | 192 |
| 193 SpdyStreamId stream_id = | 193 SpdyStreamId stream_id = |
| 194 stream_closed_ ? closed_stream_id_ : stream_->stream_id(); | 194 stream_closed_ ? closed_stream_id_ : stream_->stream_id(); |
| 195 if (stream_id == 0) | 195 if (stream_id == 0) |
| 196 return false; | 196 return false; |
| 197 | 197 |
| 198 return spdy_session_->GetLoadTimingInfo(stream_id, load_timing_info); | 198 return spdy_session_->GetLoadTimingInfo(stream_id, load_timing_info); |
| 199 } | 199 } |
| 200 | 200 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 211 base::Time request_time = base::Time::Now(); | 211 base::Time request_time = base::Time::Now(); |
| 212 CHECK(stream_.get()); | 212 CHECK(stream_.get()); |
| 213 | 213 |
| 214 stream_->SetRequestTime(request_time); | 214 stream_->SetRequestTime(request_time); |
| 215 // 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 |
| 216 // during server push that has already begun but hasn't finished, | 216 // during server push that has already begun but hasn't finished, |
| 217 // 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 |
| 218 if (response_info_) | 218 if (response_info_) |
| 219 response_info_->request_time = request_time; | 219 response_info_->request_time = request_time; |
| 220 | 220 |
| 221 CHECK(!request_body_buf_); | 221 CHECK(!request_body_buf_.get()); |
| 222 if (HasUploadData()) { | 222 if (HasUploadData()) { |
| 223 // Use kMaxSpdyFrameChunkSize as the buffer size, since the request | 223 // Use kMaxSpdyFrameChunkSize as the buffer size, since the request |
| 224 // body data is written with this size at a time. | 224 // body data is written with this size at a time. |
| 225 request_body_buf_ = new IOBufferWithSize(kMaxSpdyFrameChunkSize); | 225 request_body_buf_ = new IOBufferWithSize(kMaxSpdyFrameChunkSize); |
| 226 // The request body buffer is empty at first. | 226 // The request body buffer is empty at first. |
| 227 request_body_buf_size_ = 0; | 227 request_body_buf_size_ = 0; |
| 228 } | 228 } |
| 229 | 229 |
| 230 CHECK(!callback.is_null()); | 230 CHECK(!callback.is_null()); |
| 231 CHECK(response); | 231 CHECK(response); |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 340 break; | 340 break; |
| 341 case SPDY3: | 341 case SPDY3: |
| 342 response_info_->connection_info = HttpResponseInfo::CONNECTION_INFO_SPDY3; | 342 response_info_->connection_info = HttpResponseInfo::CONNECTION_INFO_SPDY3; |
| 343 break; | 343 break; |
| 344 case SPDY4: | 344 case SPDY4: |
| 345 response_info_->connection_info = HttpResponseInfo::CONNECTION_INFO_SPDY4; | 345 response_info_->connection_info = HttpResponseInfo::CONNECTION_INFO_SPDY4; |
| 346 break; | 346 break; |
| 347 default: | 347 default: |
| 348 NOTREACHED(); | 348 NOTREACHED(); |
| 349 } | 349 } |
| 350 response_info_->vary_data.Init(*request_info_, *response_info_->headers); | 350 response_info_->vary_data |
| 351 .Init(*request_info_, *response_info_->headers.get()); |
| 351 // TODO(ahendrickson): This is recorded after the entire SYN_STREAM control | 352 // TODO(ahendrickson): This is recorded after the entire SYN_STREAM control |
| 352 // frame has been received and processed. Move to framer? | 353 // frame has been received and processed. Move to framer? |
| 353 response_info_->response_time = response_time; | 354 response_info_->response_time = response_time; |
| 354 | 355 |
| 355 if (!callback_.is_null()) | 356 if (!callback_.is_null()) |
| 356 DoCallback(status); | 357 DoCallback(status); |
| 357 | 358 |
| 358 return status; | 359 return status; |
| 359 } | 360 } |
| 360 | 361 |
| 361 int SpdyHttpStream::OnDataReceived(scoped_ptr<SpdyBuffer> buffer) { | 362 int SpdyHttpStream::OnDataReceived(scoped_ptr<SpdyBuffer> buffer) { |
| 362 // SpdyStream won't call us with data if the header block didn't contain a | 363 // SpdyStream won't call us with data if the header block didn't contain a |
| 363 // valid set of headers. So we don't expect to not have headers received | 364 // valid set of headers. So we don't expect to not have headers received |
| 364 // here. | 365 // here. |
| 365 if (!response_headers_received_) | 366 if (!response_headers_received_) |
| 366 return ERR_INCOMPLETE_SPDY_HEADERS; | 367 return ERR_INCOMPLETE_SPDY_HEADERS; |
| 367 | 368 |
| 368 // Note that data may be received for a SpdyStream prior to the user calling | 369 // Note that data may be received for a SpdyStream prior to the user calling |
| 369 // ReadResponseBody(), therefore user_buffer_ may be NULL. This may often | 370 // ReadResponseBody(), therefore user_buffer_ may be NULL. This may often |
| 370 // happen for server initiated streams. | 371 // happen for server initiated streams. |
| 371 DCHECK(stream_.get()); | 372 DCHECK(stream_.get()); |
| 372 DCHECK(!stream_->closed() || stream_->type() == SPDY_PUSH_STREAM); | 373 DCHECK(!stream_->closed() || stream_->type() == SPDY_PUSH_STREAM); |
| 373 if (buffer) { | 374 if (buffer) { |
| 374 response_body_queue_.Enqueue(buffer.Pass()); | 375 response_body_queue_.Enqueue(buffer.Pass()); |
| 375 | 376 |
| 376 if (user_buffer_) { | 377 if (user_buffer_.get()) { |
| 377 // Handing small chunks of data to the caller creates measurable overhead. | 378 // Handing small chunks of data to the caller creates measurable overhead. |
| 378 // We buffer data in short time-spans and send a single read notification. | 379 // We buffer data in short time-spans and send a single read notification. |
| 379 ScheduleBufferedReadCallback(); | 380 ScheduleBufferedReadCallback(); |
| 380 } | 381 } |
| 381 } | 382 } |
| 382 return OK; | 383 return OK; |
| 383 } | 384 } |
| 384 | 385 |
| 385 void SpdyHttpStream::OnDataSent() { | 386 void SpdyHttpStream::OnDataSent() { |
| 386 request_body_buf_size_ = 0; | 387 request_body_buf_size_ = 0; |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 422 } | 423 } |
| 423 | 424 |
| 424 void SpdyHttpStream::ReadAndSendRequestBodyData() { | 425 void SpdyHttpStream::ReadAndSendRequestBodyData() { |
| 425 CHECK(HasUploadData()); | 426 CHECK(HasUploadData()); |
| 426 CHECK_EQ(request_body_buf_size_, 0); | 427 CHECK_EQ(request_body_buf_size_, 0); |
| 427 | 428 |
| 428 if (request_info_->upload_data_stream->IsEOF()) | 429 if (request_info_->upload_data_stream->IsEOF()) |
| 429 return; | 430 return; |
| 430 | 431 |
| 431 // Read the data from the request body stream. | 432 // Read the data from the request body stream. |
| 432 const int rv = request_info_->upload_data_stream->Read( | 433 const int rv = request_info_->upload_data_stream |
| 433 request_body_buf_, request_body_buf_->size(), | 434 ->Read(request_body_buf_.get(), |
| 434 base::Bind( | 435 request_body_buf_->size(), |
| 435 &SpdyHttpStream::OnRequestBodyReadCompleted, | 436 base::Bind(&SpdyHttpStream::OnRequestBodyReadCompleted, |
| 436 weak_factory_.GetWeakPtr())); | 437 weak_factory_.GetWeakPtr())); |
| 437 | 438 |
| 438 if (rv != ERR_IO_PENDING) { | 439 if (rv != ERR_IO_PENDING) { |
| 439 // ERR_IO_PENDING is the only possible error. | 440 // ERR_IO_PENDING is the only possible error. |
| 440 CHECK_GE(rv, 0); | 441 CHECK_GE(rv, 0); |
| 441 OnRequestBodyReadCompleted(rv); | 442 OnRequestBodyReadCompleted(rv); |
| 442 } | 443 } |
| 443 } | 444 } |
| 444 | 445 |
| 445 void SpdyHttpStream::OnRequestBodyReadCompleted(int status) { | 446 void SpdyHttpStream::OnRequestBodyReadCompleted(int status) { |
| 446 CHECK_GE(status, 0); | 447 CHECK_GE(status, 0); |
| 447 request_body_buf_size_ = status; | 448 request_body_buf_size_ = status; |
| 448 const bool eof = request_info_->upload_data_stream->IsEOF(); | 449 const bool eof = request_info_->upload_data_stream->IsEOF(); |
| 449 if (eof) { | 450 if (eof) { |
| 450 CHECK_GE(request_body_buf_size_, 0); | 451 CHECK_GE(request_body_buf_size_, 0); |
| 451 } else { | 452 } else { |
| 452 CHECK_GT(request_body_buf_size_, 0); | 453 CHECK_GT(request_body_buf_size_, 0); |
| 453 } | 454 } |
| 454 stream_->SendData(request_body_buf_, | 455 stream_->SendData(request_body_buf_.get(), |
| 455 request_body_buf_size_, | 456 request_body_buf_size_, |
| 456 eof ? NO_MORE_DATA_TO_SEND : MORE_DATA_TO_SEND); | 457 eof ? NO_MORE_DATA_TO_SEND : MORE_DATA_TO_SEND); |
| 457 } | 458 } |
| 458 | 459 |
| 459 void SpdyHttpStream::ScheduleBufferedReadCallback() { | 460 void SpdyHttpStream::ScheduleBufferedReadCallback() { |
| 460 // If there is already a scheduled DoBufferedReadCallback, don't issue | 461 // If there is already a scheduled DoBufferedReadCallback, don't issue |
| 461 // another one. Mark that we have received more data and return. | 462 // another one. Mark that we have received more data and return. |
| 462 if (buffered_read_callback_pending_) { | 463 if (buffered_read_callback_pending_) { |
| 463 more_read_data_pending_ = true; | 464 more_read_data_pending_ = true; |
| 464 return; | 465 return; |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 501 | 502 |
| 502 // When more_read_data_pending_ is true, it means that more data has | 503 // When more_read_data_pending_ is true, it means that more data has |
| 503 // arrived since we started waiting. Wait a little longer and continue | 504 // arrived since we started waiting. Wait a little longer and continue |
| 504 // to buffer. | 505 // to buffer. |
| 505 if (more_read_data_pending_ && ShouldWaitForMoreBufferedData()) { | 506 if (more_read_data_pending_ && ShouldWaitForMoreBufferedData()) { |
| 506 ScheduleBufferedReadCallback(); | 507 ScheduleBufferedReadCallback(); |
| 507 return false; | 508 return false; |
| 508 } | 509 } |
| 509 | 510 |
| 510 int rv = 0; | 511 int rv = 0; |
| 511 if (user_buffer_) { | 512 if (user_buffer_.get()) { |
| 512 rv = ReadResponseBody(user_buffer_, user_buffer_len_, callback_); | 513 rv = ReadResponseBody(user_buffer_.get(), user_buffer_len_, callback_); |
| 513 CHECK_NE(rv, ERR_IO_PENDING); | 514 CHECK_NE(rv, ERR_IO_PENDING); |
| 514 user_buffer_ = NULL; | 515 user_buffer_ = NULL; |
| 515 user_buffer_len_ = 0; | 516 user_buffer_len_ = 0; |
| 516 DoCallback(rv); | 517 DoCallback(rv); |
| 517 return true; | 518 return true; |
| 518 } | 519 } |
| 519 return false; | 520 return false; |
| 520 } | 521 } |
| 521 | 522 |
| 522 void SpdyHttpStream::DoCallback(int rv) { | 523 void SpdyHttpStream::DoCallback(int rv) { |
| (...skipping 22 matching lines...) Expand all Loading... |
| 545 bool SpdyHttpStream::IsSpdyHttpStream() const { | 546 bool SpdyHttpStream::IsSpdyHttpStream() const { |
| 546 return true; | 547 return true; |
| 547 } | 548 } |
| 548 | 549 |
| 549 void SpdyHttpStream::Drain(HttpNetworkSession* session) { | 550 void SpdyHttpStream::Drain(HttpNetworkSession* session) { |
| 550 Close(false); | 551 Close(false); |
| 551 delete this; | 552 delete this; |
| 552 } | 553 } |
| 553 | 554 |
| 554 } // namespace net | 555 } // namespace net |
| OLD | NEW |