| 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_stream.h" | 5 #include "net/spdy/spdy_stream.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "base/message_loop.h" | 9 #include "base/message_loop.h" |
| 10 #include "base/stringprintf.h" | 10 #include "base/stringprintf.h" |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 121 } else { | 121 } else { |
| 122 delegate_->OnDataReceived(NULL, 0); | 122 delegate_->OnDataReceived(NULL, 0); |
| 123 session_->CloseStream(stream_id_, net::OK); | 123 session_->CloseStream(stream_id_, net::OK); |
| 124 // Note: |this| may be deleted after calling CloseStream. | 124 // Note: |this| may be deleted after calling CloseStream. |
| 125 DCHECK_EQ(buffers.size() - 1, i); | 125 DCHECK_EQ(buffers.size() - 1, i); |
| 126 } | 126 } |
| 127 } | 127 } |
| 128 } | 128 } |
| 129 | 129 |
| 130 void SpdyStream::DetachDelegate() { | 130 void SpdyStream::DetachDelegate() { |
| 131 if (delegate_) | |
| 132 delegate_->set_chunk_callback(NULL); | |
| 133 delegate_ = NULL; | 131 delegate_ = NULL; |
| 134 if (!closed()) | 132 if (!closed()) |
| 135 Cancel(); | 133 Cancel(); |
| 136 } | 134 } |
| 137 | 135 |
| 138 const linked_ptr<SpdyHeaderBlock>& SpdyStream::spdy_headers() const { | 136 const linked_ptr<SpdyHeaderBlock>& SpdyStream::spdy_headers() const { |
| 139 return request_; | 137 return request_; |
| 140 } | 138 } |
| 141 | 139 |
| 142 void SpdyStream::set_spdy_headers( | 140 void SpdyStream::set_spdy_headers( |
| (...skipping 15 matching lines...) Expand all Loading... |
| 158 | 156 |
| 159 void SpdyStream::AdjustSendWindowSize(int32 delta_window_size) { | 157 void SpdyStream::AdjustSendWindowSize(int32 delta_window_size) { |
| 160 send_window_size_ += delta_window_size; | 158 send_window_size_ += delta_window_size; |
| 161 PossiblyResumeIfStalled(); | 159 PossiblyResumeIfStalled(); |
| 162 } | 160 } |
| 163 | 161 |
| 164 void SpdyStream::IncreaseSendWindowSize(int32 delta_window_size) { | 162 void SpdyStream::IncreaseSendWindowSize(int32 delta_window_size) { |
| 165 DCHECK(session_->is_flow_control_enabled()); | 163 DCHECK(session_->is_flow_control_enabled()); |
| 166 DCHECK_GE(delta_window_size, 1); | 164 DCHECK_GE(delta_window_size, 1); |
| 167 | 165 |
| 168 int32 new_window_size = send_window_size_ + delta_window_size; | 166 // Ignore late WINDOW_UPDATEs. |
| 167 if (closed()) |
| 168 return; |
| 169 | 169 |
| 170 // We should ignore WINDOW_UPDATEs received before or after this state, | 170 // We should ignore WINDOW_UPDATEs received before or after this state, |
| 171 // since before means we've not written SYN_STREAM yet (i.e. it's too | 171 // since before means we've not written SYN_STREAM yet (i.e. it's too |
| 172 // early) and after means we've written a DATA frame with FIN bit. | 172 // early) and after means we've written a DATA frame with FIN bit. |
| 173 if (io_state_ != STATE_SEND_BODY_COMPLETE) | 173 if (io_state_ != STATE_SEND_BODY_COMPLETE) { |
| 174 std::string desc = base::StringPrintf( |
| 175 "Received unexpected WINDOW_UPDATE [delta: %d] for stream %d.", |
| 176 delta_window_size, stream_id_); |
| 177 session_->ResetStream(stream_id_, FLOW_CONTROL_ERROR, desc); |
| 174 return; | 178 return; |
| 179 } |
| 175 | 180 |
| 176 // it's valid for send_window_size_ to become negative (via an incoming | 181 int32 new_window_size = send_window_size_ + delta_window_size; |
| 182 |
| 183 // It's valid for send_window_size_ to become negative (via an incoming |
| 177 // SETTINGS), in which case incoming WINDOW_UPDATEs will eventually make | 184 // SETTINGS), in which case incoming WINDOW_UPDATEs will eventually make |
| 178 // it positive; however, if send_window_size_ is positive and incoming | 185 // it positive; however, if send_window_size_ is positive and incoming |
| 179 // WINDOW_UPDATE makes it negative, we have an overflow. | 186 // WINDOW_UPDATE makes it negative, we have an overflow. |
| 180 if (send_window_size_ > 0 && new_window_size < 0) { | 187 if (send_window_size_ > 0 && new_window_size < 0) { |
| 181 std::string desc = base::StringPrintf( | 188 std::string desc = base::StringPrintf( |
| 182 "Received WINDOW_UPDATE [delta: %d] for stream %d overflows " | 189 "Received WINDOW_UPDATE [delta: %d] for stream %d overflows " |
| 183 "send_window_size_ [current: %d]", delta_window_size, stream_id_, | 190 "send_window_size_ [current: %d]", delta_window_size, stream_id_, |
| 184 send_window_size_); | 191 send_window_size_); |
| 185 session_->ResetStream(stream_id_, FLOW_CONTROL_ERROR, desc); | 192 session_->ResetStream(stream_id_, FLOW_CONTROL_ERROR, desc); |
| 186 return; | 193 return; |
| 187 } | 194 } |
| 188 | 195 |
| 189 send_window_size_ = new_window_size; | 196 send_window_size_ = new_window_size; |
| 190 | 197 |
| 191 net_log_.AddEvent( | 198 net_log_.AddEvent( |
| 192 NetLog::TYPE_SPDY_STREAM_UPDATE_SEND_WINDOW, | 199 NetLog::TYPE_SPDY_STREAM_UPDATE_SEND_WINDOW, |
| 193 base::Bind(&NetLogSpdyStreamWindowUpdateCallback, | 200 base::Bind(&NetLogSpdyStreamWindowUpdateCallback, |
| 194 stream_id_, delta_window_size, send_window_size_)); | 201 stream_id_, delta_window_size, send_window_size_)); |
| 202 |
| 195 PossiblyResumeIfStalled(); | 203 PossiblyResumeIfStalled(); |
| 196 } | 204 } |
| 197 | 205 |
| 198 void SpdyStream::DecreaseSendWindowSize(int32 delta_window_size) { | 206 void SpdyStream::DecreaseSendWindowSize(int32 delta_window_size) { |
| 199 // we only call this method when sending a frame, therefore | 207 // we only call this method when sending a frame, therefore |
| 200 // |delta_window_size| should be within the valid frame size range. | 208 // |delta_window_size| should be within the valid frame size range. |
| 201 DCHECK(session_->is_flow_control_enabled()); | 209 DCHECK(session_->is_flow_control_enabled()); |
| 202 DCHECK_GE(delta_window_size, 1); | 210 DCHECK_GE(delta_window_size, 1); |
| 203 DCHECK_LE(delta_window_size, kMaxSpdyFrameChunkSize); | 211 DCHECK_LE(delta_window_size, kMaxSpdyFrameChunkSize); |
| 204 | 212 |
| (...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 427 | 435 |
| 428 // This function is only called when an entire frame is written. | 436 // This function is only called when an entire frame is written. |
| 429 void SpdyStream::OnWriteComplete(int bytes) { | 437 void SpdyStream::OnWriteComplete(int bytes) { |
| 430 DCHECK_LE(0, bytes); | 438 DCHECK_LE(0, bytes); |
| 431 send_bytes_ += bytes; | 439 send_bytes_ += bytes; |
| 432 if (cancelled() || closed()) | 440 if (cancelled() || closed()) |
| 433 return; | 441 return; |
| 434 DoLoop(bytes); | 442 DoLoop(bytes); |
| 435 } | 443 } |
| 436 | 444 |
| 437 void SpdyStream::OnChunkAvailable() { | |
| 438 DCHECK(io_state_ == STATE_SEND_HEADERS || io_state_ == STATE_SEND_BODY || | |
| 439 io_state_ == STATE_SEND_BODY_COMPLETE); | |
| 440 if (io_state_ == STATE_SEND_BODY) | |
| 441 OnWriteComplete(0); | |
| 442 } | |
| 443 | |
| 444 int SpdyStream::GetProtocolVersion() const { | 445 int SpdyStream::GetProtocolVersion() const { |
| 445 return session_->GetProtocolVersion(); | 446 return session_->GetProtocolVersion(); |
| 446 } | 447 } |
| 447 | 448 |
| 448 void SpdyStream::LogStreamError(int status, const std::string& description) { | 449 void SpdyStream::LogStreamError(int status, const std::string& description) { |
| 449 net_log_.AddEvent(NetLog::TYPE_SPDY_STREAM_ERROR, | 450 net_log_.AddEvent(NetLog::TYPE_SPDY_STREAM_ERROR, |
| 450 base::Bind(&NetLogSpdyStreamErrorCallback, | 451 base::Bind(&NetLogSpdyStreamErrorCallback, |
| 451 stream_id_, status, &description)); | 452 stream_id_, status, &description)); |
| 452 } | 453 } |
| 453 | 454 |
| 454 void SpdyStream::OnClose(int status) { | 455 void SpdyStream::OnClose(int status) { |
| 455 io_state_ = STATE_DONE; | 456 io_state_ = STATE_DONE; |
| 456 response_status_ = status; | 457 response_status_ = status; |
| 457 Delegate* delegate = delegate_; | 458 Delegate* delegate = delegate_; |
| 458 delegate_ = NULL; | 459 delegate_ = NULL; |
| 459 if (delegate) { | 460 if (delegate) |
| 460 delegate->set_chunk_callback(NULL); | |
| 461 delegate->OnClose(status); | 461 delegate->OnClose(status); |
| 462 } | |
| 463 } | 462 } |
| 464 | 463 |
| 465 void SpdyStream::Cancel() { | 464 void SpdyStream::Cancel() { |
| 466 if (cancelled()) | 465 if (cancelled()) |
| 467 return; | 466 return; |
| 468 | 467 |
| 469 cancelled_ = true; | 468 cancelled_ = true; |
| 470 if (session_->IsStreamActive(stream_id_)) | 469 if (session_->IsStreamActive(stream_id_)) |
| 471 session_->ResetStream(stream_id_, CANCEL, ""); | 470 session_->ResetStream(stream_id_, CANCEL, ""); |
| 472 } | 471 } |
| 473 | 472 |
| 474 void SpdyStream::Close() { | 473 void SpdyStream::Close() { |
| 475 session_->CloseStream(stream_id_, net::OK); | 474 session_->CloseStream(stream_id_, net::OK); |
| 476 } | 475 } |
| 477 | 476 |
| 478 int SpdyStream::SendRequest(bool has_upload_data) { | 477 int SpdyStream::SendRequest(bool has_upload_data) { |
| 479 if (delegate_) | |
| 480 delegate_->set_chunk_callback(this); | |
| 481 | |
| 482 // Pushed streams do not send any data, and should always be in STATE_OPEN or | 478 // Pushed streams do not send any data, and should always be in STATE_OPEN or |
| 483 // STATE_DONE. However, we still want to return IO_PENDING to mimic non-push | 479 // STATE_DONE. However, we still want to return IO_PENDING to mimic non-push |
| 484 // behavior. | 480 // behavior. |
| 485 has_upload_data_ = has_upload_data; | 481 has_upload_data_ = has_upload_data; |
| 486 if (pushed_) { | 482 if (pushed_) { |
| 487 send_time_ = base::TimeTicks::Now(); | 483 send_time_ = base::TimeTicks::Now(); |
| 488 DCHECK(!has_upload_data_); | 484 DCHECK(!has_upload_data_); |
| 489 DCHECK(response_received()); | 485 DCHECK(response_received()); |
| 490 return ERR_IO_PENDING; | 486 return ERR_IO_PENDING; |
| 491 } | 487 } |
| (...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 695 return OK; | 691 return OK; |
| 696 } | 692 } |
| 697 | 693 |
| 698 io_state_ = STATE_SEND_BODY; | 694 io_state_ = STATE_SEND_BODY; |
| 699 return OK; | 695 return OK; |
| 700 } | 696 } |
| 701 | 697 |
| 702 // DoSendBody is called to send the optional body for the request. This call | 698 // DoSendBody is called to send the optional body for the request. This call |
| 703 // will also be called as each write of a chunk of the body completes. | 699 // will also be called as each write of a chunk of the body completes. |
| 704 int SpdyStream::DoSendBody() { | 700 int SpdyStream::DoSendBody() { |
| 705 // If we're already in the STATE_SENDING_BODY state, then we've already | 701 // If we're already in the STATE_SEND_BODY state, then we've already |
| 706 // sent a portion of the body. In that case, we need to first consume | 702 // sent a portion of the body. In that case, we need to first consume |
| 707 // the bytes written in the body stream. Note that the bytes written is | 703 // the bytes written in the body stream. Note that the bytes written is |
| 708 // the number of bytes in the frame that were written, only consume the | 704 // the number of bytes in the frame that were written, only consume the |
| 709 // data portion, of course. | 705 // data portion, of course. |
| 710 io_state_ = STATE_SEND_BODY_COMPLETE; | 706 io_state_ = STATE_SEND_BODY_COMPLETE; |
| 711 if (!delegate_) | 707 if (!delegate_) |
| 712 return ERR_UNEXPECTED; | 708 return ERR_UNEXPECTED; |
| 713 return delegate_->OnSendBody(); | 709 return delegate_->OnSendBody(); |
| 714 } | 710 } |
| 715 | 711 |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 748 UMA_HISTOGRAM_TIMES("Net.SpdyStreamDownloadTime", | 744 UMA_HISTOGRAM_TIMES("Net.SpdyStreamDownloadTime", |
| 749 recv_last_byte_time_ - recv_first_byte_time_); | 745 recv_last_byte_time_ - recv_first_byte_time_); |
| 750 UMA_HISTOGRAM_TIMES("Net.SpdyStreamTime", | 746 UMA_HISTOGRAM_TIMES("Net.SpdyStreamTime", |
| 751 recv_last_byte_time_ - send_time_); | 747 recv_last_byte_time_ - send_time_); |
| 752 | 748 |
| 753 UMA_HISTOGRAM_COUNTS("Net.SpdySendBytes", send_bytes_); | 749 UMA_HISTOGRAM_COUNTS("Net.SpdySendBytes", send_bytes_); |
| 754 UMA_HISTOGRAM_COUNTS("Net.SpdyRecvBytes", recv_bytes_); | 750 UMA_HISTOGRAM_COUNTS("Net.SpdyRecvBytes", recv_bytes_); |
| 755 } | 751 } |
| 756 | 752 |
| 757 } // namespace net | 753 } // namespace net |
| OLD | NEW |