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 |