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 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
144 request_ = headers; | 144 request_ = headers; |
145 } | 145 } |
146 | 146 |
147 void SpdyStream::set_initial_recv_window_size(int32 window_size) { | 147 void SpdyStream::set_initial_recv_window_size(int32 window_size) { |
148 session_->set_initial_recv_window_size(window_size); | 148 session_->set_initial_recv_window_size(window_size); |
149 } | 149 } |
150 | 150 |
151 void SpdyStream::PossiblyResumeIfStalled() { | 151 void SpdyStream::PossiblyResumeIfStalled() { |
152 if (send_window_size_ > 0 && stalled_by_flow_control_) { | 152 if (send_window_size_ > 0 && stalled_by_flow_control_) { |
153 stalled_by_flow_control_ = false; | 153 stalled_by_flow_control_ = false; |
154 io_state_ = STATE_SEND_BODY; | 154 if (delegate_->IsRequestBodyChunked()) |
155 io_state_ = STATE_SEND_CHUNKED_BODY; | |
156 else | |
157 io_state_ = STATE_SEND_BODY; | |
155 DoLoop(OK); | 158 DoLoop(OK); |
156 } | 159 } |
157 } | 160 } |
158 | 161 |
159 void SpdyStream::AdjustSendWindowSize(int32 delta_window_size) { | 162 void SpdyStream::AdjustSendWindowSize(int32 delta_window_size) { |
160 send_window_size_ += delta_window_size; | 163 send_window_size_ += delta_window_size; |
161 PossiblyResumeIfStalled(); | 164 PossiblyResumeIfStalled(); |
162 } | 165 } |
163 | 166 |
164 void SpdyStream::IncreaseSendWindowSize(int32 delta_window_size) { | 167 void SpdyStream::IncreaseSendWindowSize(int32 delta_window_size) { |
165 DCHECK(session_->is_flow_control_enabled()); | 168 DCHECK(session_->is_flow_control_enabled()); |
166 DCHECK_GE(delta_window_size, 1); | 169 DCHECK_GE(delta_window_size, 1); |
167 | 170 |
168 int32 new_window_size = send_window_size_ + delta_window_size; | 171 int32 new_window_size = send_window_size_ + delta_window_size; |
169 | 172 |
170 // We should ignore WINDOW_UPDATEs received before or after this state, | 173 // 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 | 174 // 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. | 175 // early) and after means we've written a DATA frame with FIN bit. |
173 if (io_state_ != STATE_SEND_BODY_COMPLETE) | 176 if (io_state_ != STATE_SEND_BODY_COMPLETE && |
177 io_state_ != STATE_SEND_CHUNKED_BODY && | |
178 io_state_ != STATE_SEND_CHUNKED_BODY_COMPLETE) { | |
174 return; | 179 return; |
Ryan Hamilton
2012/07/02 22:34:32
This still feels totally wrong to me. I do not th
ramant (doing other things)
2012/07/04 21:04:33
Done.
| |
180 } | |
175 | 181 |
176 // it's valid for send_window_size_ to become negative (via an incoming | 182 // it's valid for send_window_size_ to become negative (via an incoming |
177 // SETTINGS), in which case incoming WINDOW_UPDATEs will eventually make | 183 // SETTINGS), in which case incoming WINDOW_UPDATEs will eventually make |
178 // it positive; however, if send_window_size_ is positive and incoming | 184 // it positive; however, if send_window_size_ is positive and incoming |
179 // WINDOW_UPDATE makes it negative, we have an overflow. | 185 // WINDOW_UPDATE makes it negative, we have an overflow. |
180 if (send_window_size_ > 0 && new_window_size < 0) { | 186 if (send_window_size_ > 0 && new_window_size < 0) { |
181 std::string desc = base::StringPrintf( | 187 std::string desc = base::StringPrintf( |
182 "Received WINDOW_UPDATE [delta: %d] for stream %d overflows " | 188 "Received WINDOW_UPDATE [delta: %d] for stream %d overflows " |
183 "send_window_size_ [current: %d]", delta_window_size, stream_id_, | 189 "send_window_size_ [current: %d]", delta_window_size, stream_id_, |
184 send_window_size_); | 190 send_window_size_); |
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
428 // This function is only called when an entire frame is written. | 434 // This function is only called when an entire frame is written. |
429 void SpdyStream::OnWriteComplete(int bytes) { | 435 void SpdyStream::OnWriteComplete(int bytes) { |
430 DCHECK_LE(0, bytes); | 436 DCHECK_LE(0, bytes); |
431 send_bytes_ += bytes; | 437 send_bytes_ += bytes; |
432 if (cancelled() || closed()) | 438 if (cancelled() || closed()) |
433 return; | 439 return; |
434 DoLoop(bytes); | 440 DoLoop(bytes); |
435 } | 441 } |
436 | 442 |
437 void SpdyStream::OnChunkAvailable() { | 443 void SpdyStream::OnChunkAvailable() { |
438 DCHECK(io_state_ == STATE_SEND_HEADERS || io_state_ == STATE_SEND_BODY || | 444 DCHECK(io_state_ == STATE_SEND_HEADERS || |
439 io_state_ == STATE_SEND_BODY_COMPLETE); | 445 io_state_ == STATE_SEND_CHUNKED_BODY || |
440 if (io_state_ == STATE_SEND_BODY) | 446 io_state_ == STATE_SEND_CHUNKED_BODY_COMPLETE); |
447 if (io_state_ == STATE_SEND_CHUNKED_BODY) | |
441 OnWriteComplete(0); | 448 OnWriteComplete(0); |
442 } | 449 } |
443 | 450 |
444 int SpdyStream::GetProtocolVersion() const { | 451 int SpdyStream::GetProtocolVersion() const { |
445 return session_->GetProtocolVersion(); | 452 return session_->GetProtocolVersion(); |
446 } | 453 } |
447 | 454 |
448 void SpdyStream::LogStreamError(int status, const std::string& description) { | 455 void SpdyStream::LogStreamError(int status, const std::string& description) { |
449 net_log_.AddEvent(NetLog::TYPE_SPDY_STREAM_ERROR, | 456 net_log_.AddEvent(NetLog::TYPE_SPDY_STREAM_ERROR, |
450 base::Bind(&NetLogSpdyStreamErrorCallback, | 457 base::Bind(&NetLogSpdyStreamErrorCallback, |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
555 CHECK_EQ(OK, result); | 562 CHECK_EQ(OK, result); |
556 result = DoSendHeaders(); | 563 result = DoSendHeaders(); |
557 break; | 564 break; |
558 case STATE_SEND_HEADERS_COMPLETE: | 565 case STATE_SEND_HEADERS_COMPLETE: |
559 result = DoSendHeadersComplete(result); | 566 result = DoSendHeadersComplete(result); |
560 break; | 567 break; |
561 case STATE_SEND_BODY: | 568 case STATE_SEND_BODY: |
562 CHECK_EQ(OK, result); | 569 CHECK_EQ(OK, result); |
563 result = DoSendBody(); | 570 result = DoSendBody(); |
564 break; | 571 break; |
572 case STATE_SEND_CHUNKED_BODY: | |
573 result = DoSendChunkedBody(); | |
574 break; | |
575 case STATE_SEND_CHUNKED_BODY_COMPLETE: | |
576 result = DoSendChunkedBodyComplete(result); | |
577 break; | |
565 case STATE_SEND_BODY_COMPLETE: | 578 case STATE_SEND_BODY_COMPLETE: |
566 result = DoSendBodyComplete(result); | 579 result = DoSendBodyComplete(result); |
567 break; | 580 break; |
568 // This is an intermediary waiting state. This state is reached when all | 581 // This is an intermediary waiting state. This state is reached when all |
569 // data has been sent, but no data has been received. | 582 // data has been sent, but no data has been received. |
570 case STATE_WAITING_FOR_RESPONSE: | 583 case STATE_WAITING_FOR_RESPONSE: |
571 io_state_ = STATE_WAITING_FOR_RESPONSE; | 584 io_state_ = STATE_WAITING_FOR_RESPONSE; |
572 result = ERR_IO_PENDING; | 585 result = ERR_IO_PENDING; |
573 break; | 586 break; |
574 // State machine 2: connection is established. | 587 // State machine 2: connection is established. |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
688 | 701 |
689 if (!delegate_) | 702 if (!delegate_) |
690 return ERR_UNEXPECTED; | 703 return ERR_UNEXPECTED; |
691 | 704 |
692 // There is no body, skip that state. | 705 // There is no body, skip that state. |
693 if (delegate_->OnSendHeadersComplete(result)) { | 706 if (delegate_->OnSendHeadersComplete(result)) { |
694 io_state_ = STATE_WAITING_FOR_RESPONSE; | 707 io_state_ = STATE_WAITING_FOR_RESPONSE; |
695 return OK; | 708 return OK; |
696 } | 709 } |
697 | 710 |
698 io_state_ = STATE_SEND_BODY; | 711 if (delegate_->IsRequestBodyChunked()) |
712 io_state_ = STATE_SEND_CHUNKED_BODY; | |
713 else | |
714 io_state_ = STATE_SEND_BODY; | |
699 return OK; | 715 return OK; |
700 } | 716 } |
701 | 717 |
702 // DoSendBody is called to send the optional body for the request. This call | 718 // 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. | 719 // will also be called as each write of a chunk of the body completes. |
704 int SpdyStream::DoSendBody() { | 720 int SpdyStream::DoSendBody() { |
705 // If we're already in the STATE_SENDING_BODY state, then we've already | 721 // If we're already in the STATE_SENDING_BODY state, then we've already |
706 // sent a portion of the body. In that case, we need to first consume | 722 // 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 | 723 // 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 | 724 // the number of bytes in the frame that were written, only consume the |
(...skipping 14 matching lines...) Expand all Loading... | |
723 bool eof = false; | 739 bool eof = false; |
724 result = delegate_->OnSendBodyComplete(result, &eof); | 740 result = delegate_->OnSendBodyComplete(result, &eof); |
725 if (!eof) | 741 if (!eof) |
726 io_state_ = STATE_SEND_BODY; | 742 io_state_ = STATE_SEND_BODY; |
727 else | 743 else |
728 io_state_ = STATE_WAITING_FOR_RESPONSE; | 744 io_state_ = STATE_WAITING_FOR_RESPONSE; |
729 | 745 |
730 return result; | 746 return result; |
731 } | 747 } |
732 | 748 |
749 int SpdyStream::DoSendChunkedBody() { | |
750 io_state_ = STATE_SEND_CHUNKED_BODY_COMPLETE; | |
751 if (!delegate_) | |
752 return ERR_UNEXPECTED; | |
753 return delegate_->OnSendChunkedBody(); | |
754 } | |
755 | |
756 int SpdyStream::DoSendChunkedBodyComplete(int result) { | |
757 if (result < 0) | |
758 return result; | |
759 | |
760 if (!delegate_) | |
761 return ERR_UNEXPECTED; | |
762 | |
763 bool eof = false; | |
764 result = delegate_->OnSendChunkedBodyComplete(result, &eof); | |
765 if (!eof) | |
766 io_state_ = STATE_SEND_CHUNKED_BODY; | |
767 else | |
768 io_state_ = STATE_WAITING_FOR_RESPONSE; | |
769 | |
770 return result; | |
771 } | |
772 | |
733 int SpdyStream::DoOpen(int result) { | 773 int SpdyStream::DoOpen(int result) { |
734 if (delegate_) | 774 if (delegate_) |
735 delegate_->OnDataSent(result); | 775 delegate_->OnDataSent(result); |
736 io_state_ = STATE_OPEN; | 776 io_state_ = STATE_OPEN; |
737 return result; | 777 return result; |
738 } | 778 } |
739 | 779 |
740 void SpdyStream::UpdateHistograms() { | 780 void SpdyStream::UpdateHistograms() { |
741 // We need all timers to be filled in, otherwise metrics can be bogus. | 781 // We need all timers to be filled in, otherwise metrics can be bogus. |
742 if (send_time_.is_null() || recv_first_byte_time_.is_null() || | 782 if (send_time_.is_null() || recv_first_byte_time_.is_null() || |
743 recv_last_byte_time_.is_null()) | 783 recv_last_byte_time_.is_null()) |
744 return; | 784 return; |
745 | 785 |
746 UMA_HISTOGRAM_TIMES("Net.SpdyStreamTimeToFirstByte", | 786 UMA_HISTOGRAM_TIMES("Net.SpdyStreamTimeToFirstByte", |
747 recv_first_byte_time_ - send_time_); | 787 recv_first_byte_time_ - send_time_); |
748 UMA_HISTOGRAM_TIMES("Net.SpdyStreamDownloadTime", | 788 UMA_HISTOGRAM_TIMES("Net.SpdyStreamDownloadTime", |
749 recv_last_byte_time_ - recv_first_byte_time_); | 789 recv_last_byte_time_ - recv_first_byte_time_); |
750 UMA_HISTOGRAM_TIMES("Net.SpdyStreamTime", | 790 UMA_HISTOGRAM_TIMES("Net.SpdyStreamTime", |
751 recv_last_byte_time_ - send_time_); | 791 recv_last_byte_time_ - send_time_); |
752 | 792 |
753 UMA_HISTOGRAM_COUNTS("Net.SpdySendBytes", send_bytes_); | 793 UMA_HISTOGRAM_COUNTS("Net.SpdySendBytes", send_bytes_); |
754 UMA_HISTOGRAM_COUNTS("Net.SpdyRecvBytes", recv_bytes_); | 794 UMA_HISTOGRAM_COUNTS("Net.SpdyRecvBytes", recv_bytes_); |
755 } | 795 } |
756 | 796 |
757 } // namespace net | 797 } // namespace net |
OLD | NEW |