| 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_session.h" | 5 #include "net/spdy/spdy_session.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <map> | 8 #include <map> |
| 9 | 9 |
| 10 #include "base/basictypes.h" | 10 #include "base/basictypes.h" |
| (...skipping 735 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 746 // Find our stream. | 746 // Find our stream. |
| 747 CHECK(IsStreamActive(stream_id)); | 747 CHECK(IsStreamActive(stream_id)); |
| 748 scoped_refptr<SpdyStream> stream = active_streams_[stream_id]; | 748 scoped_refptr<SpdyStream> stream = active_streams_[stream_id]; |
| 749 CHECK_EQ(stream->stream_id(), stream_id); | 749 CHECK_EQ(stream->stream_id(), stream_id); |
| 750 | 750 |
| 751 if (len < 0) { | 751 if (len < 0) { |
| 752 NOTREACHED(); | 752 NOTREACHED(); |
| 753 return scoped_ptr<SpdyBuffer>(); | 753 return scoped_ptr<SpdyBuffer>(); |
| 754 } | 754 } |
| 755 | 755 |
| 756 if (len > kMaxSpdyFrameChunkSize) { | 756 int effective_len = std::min(len, kMaxSpdyFrameChunkSize); |
| 757 len = kMaxSpdyFrameChunkSize; | 757 |
| 758 flags = static_cast<SpdyDataFlags>(flags & ~DATA_FLAG_FIN); | 758 bool send_stalled_by_stream = false; |
| 759 if (flow_control_state_ >= FLOW_CONTROL_STREAM) { |
| 760 send_stalled_by_stream = (stream->send_window_size() <= 0); |
| 761 UMA_HISTOGRAM_BOOLEAN("Net.SpdyDataFrameSendStalledByStream", |
| 762 send_stalled_by_stream); |
| 759 } | 763 } |
| 760 | 764 |
| 761 // Obey send window size of the stream (and session, if applicable) | 765 if (flow_control_state_ == FLOW_CONTROL_STREAM_AND_SESSION) { |
| 762 // if flow control is enabled. | 766 UMA_HISTOGRAM_BOOLEAN("Net.SpdyDataFrameSendStalledBySession", |
| 767 IsSendStalled()); |
| 768 } |
| 769 |
| 770 // Obey send window size of the stream if stream flow control is |
| 771 // enabled. |
| 763 if (flow_control_state_ >= FLOW_CONTROL_STREAM) { | 772 if (flow_control_state_ >= FLOW_CONTROL_STREAM) { |
| 764 int32 effective_window_size = stream->send_window_size(); | 773 if (send_stalled_by_stream) { |
| 765 if (effective_window_size <= 0) { | |
| 766 // Because we queue frames onto the session, it is possible that | |
| 767 // a stream was not flow controlled at the time it attempted the | |
| 768 // write, but when we go to fulfill the write, it is now flow | |
| 769 // controlled. This is why we need the session to mark the stream | |
| 770 // as stalled - because only the session knows for sure when the | |
| 771 // stall occurs. | |
| 772 stream->set_send_stalled_by_flow_control(true); | 774 stream->set_send_stalled_by_flow_control(true); |
| 773 net_log().AddEvent( | 775 net_log().AddEvent( |
| 774 NetLog::TYPE_SPDY_SESSION_STREAM_STALLED_ON_STREAM_SEND_WINDOW, | 776 NetLog::TYPE_SPDY_SESSION_STREAM_STALLED_BY_STREAM_SEND_WINDOW, |
| 775 NetLog::IntegerCallback("stream_id", stream_id)); | 777 NetLog::IntegerCallback("stream_id", stream_id)); |
| 776 return scoped_ptr<SpdyBuffer>(); | 778 return scoped_ptr<SpdyBuffer>(); |
| 777 } | 779 } |
| 778 if (flow_control_state_ == FLOW_CONTROL_STREAM_AND_SESSION) { | 780 |
| 779 effective_window_size = | 781 effective_len = std::min(effective_len, stream->send_window_size()); |
| 780 std::min(effective_window_size, session_send_window_size_); | 782 } |
| 781 if (effective_window_size <= 0) { | 783 |
| 782 DCHECK(IsSendStalled()); | 784 // Obey send window size of the session if session flow control is |
| 783 stream->set_send_stalled_by_flow_control(true); | 785 // enabled. |
| 784 QueueSendStalledStream(stream); | 786 if (flow_control_state_ == FLOW_CONTROL_STREAM_AND_SESSION) { |
| 785 net_log().AddEvent( | 787 if (IsSendStalled()) { |
| 786 NetLog::TYPE_SPDY_SESSION_STREAM_STALLED_ON_SESSION_SEND_WINDOW, | 788 stream->set_send_stalled_by_flow_control(true); |
| 787 NetLog::IntegerCallback("stream_id", stream_id)); | 789 QueueSendStalledStream(stream); |
| 788 return scoped_ptr<SpdyBuffer>(); | 790 net_log().AddEvent( |
| 789 } | 791 NetLog::TYPE_SPDY_SESSION_STREAM_STALLED_BY_SESSION_SEND_WINDOW, |
| 792 NetLog::IntegerCallback("stream_id", stream_id)); |
| 793 return scoped_ptr<SpdyBuffer>(); |
| 790 } | 794 } |
| 791 | 795 |
| 792 int new_len = std::min(len, effective_window_size); | 796 effective_len = std::min(effective_len, session_send_window_size_); |
| 793 if (new_len < len) { | |
| 794 len = new_len; | |
| 795 flags = static_cast<SpdyDataFlags>(flags & ~DATA_FLAG_FIN); | |
| 796 } | |
| 797 } | 797 } |
| 798 | 798 |
| 799 DCHECK_GE(effective_len, 0); |
| 800 |
| 801 // Clear FIN flag if only some of the data will be in the data |
| 802 // frame. |
| 803 if (effective_len < len) |
| 804 flags = static_cast<SpdyDataFlags>(flags & ~DATA_FLAG_FIN); |
| 805 |
| 799 if (net_log().IsLoggingAllEvents()) { | 806 if (net_log().IsLoggingAllEvents()) { |
| 800 net_log().AddEvent( | 807 net_log().AddEvent( |
| 801 NetLog::TYPE_SPDY_SESSION_SEND_DATA, | 808 NetLog::TYPE_SPDY_SESSION_SEND_DATA, |
| 802 base::Bind(&NetLogSpdyDataCallback, stream_id, len, | 809 base::Bind(&NetLogSpdyDataCallback, stream_id, effective_len, |
| 803 (flags & DATA_FLAG_FIN) != 0)); | 810 (flags & DATA_FLAG_FIN) != 0)); |
| 804 } | 811 } |
| 805 | 812 |
| 806 // Send PrefacePing for DATA_FRAMEs with nonzero payload size. | 813 // Send PrefacePing for DATA_FRAMEs with nonzero payload size. |
| 807 if (len > 0) | 814 if (effective_len > 0) |
| 808 SendPrefacePingIfNoneInFlight(); | 815 SendPrefacePingIfNoneInFlight(); |
| 809 | 816 |
| 810 // TODO(mbelshe): reduce memory copies here. | 817 // TODO(mbelshe): reduce memory copies here. |
| 811 DCHECK(buffered_spdy_framer_.get()); | 818 DCHECK(buffered_spdy_framer_.get()); |
| 812 scoped_ptr<SpdyFrame> frame( | 819 scoped_ptr<SpdyFrame> frame( |
| 813 buffered_spdy_framer_->CreateDataFrame( | 820 buffered_spdy_framer_->CreateDataFrame( |
| 814 stream_id, data->data(), static_cast<uint32>(len), flags)); | 821 stream_id, data->data(), |
| 822 static_cast<uint32>(effective_len), flags)); |
| 815 | 823 |
| 816 scoped_ptr<SpdyBuffer> data_buffer(new SpdyBuffer(frame.Pass())); | 824 scoped_ptr<SpdyBuffer> data_buffer(new SpdyBuffer(frame.Pass())); |
| 817 | 825 |
| 818 if (flow_control_state_ == FLOW_CONTROL_STREAM_AND_SESSION) { | 826 if (flow_control_state_ == FLOW_CONTROL_STREAM_AND_SESSION) { |
| 819 DecreaseSendWindowSize(static_cast<int32>(len)); | 827 DecreaseSendWindowSize(static_cast<int32>(effective_len)); |
| 820 data_buffer->AddConsumeCallback( | 828 data_buffer->AddConsumeCallback( |
| 821 base::Bind(&SpdySession::OnWriteBufferConsumed, | 829 base::Bind(&SpdySession::OnWriteBufferConsumed, |
| 822 weak_factory_.GetWeakPtr(), | 830 weak_factory_.GetWeakPtr(), |
| 823 static_cast<size_t>(len))); | 831 static_cast<size_t>(effective_len))); |
| 824 } | 832 } |
| 825 | 833 |
| 826 return data_buffer.Pass(); | 834 return data_buffer.Pass(); |
| 827 } | 835 } |
| 828 | 836 |
| 829 void SpdySession::CloseStream(SpdyStreamId stream_id, int status) { | 837 void SpdySession::CloseStream(SpdyStreamId stream_id, int status) { |
| 830 DCHECK_NE(0u, stream_id); | 838 DCHECK_NE(0u, stream_id); |
| 831 // TODO(mbelshe): We should send a RST_STREAM control frame here | 839 // TODO(mbelshe): We should send a RST_STREAM control frame here |
| 832 // so that the server can cancel a large send. | 840 // so that the server can cancel a large send. |
| 833 | 841 |
| (...skipping 1533 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2367 if (!queue->empty()) { | 2375 if (!queue->empty()) { |
| 2368 SpdyStreamId stream_id = queue->front(); | 2376 SpdyStreamId stream_id = queue->front(); |
| 2369 queue->pop_front(); | 2377 queue->pop_front(); |
| 2370 return stream_id; | 2378 return stream_id; |
| 2371 } | 2379 } |
| 2372 } | 2380 } |
| 2373 return 0; | 2381 return 0; |
| 2374 } | 2382 } |
| 2375 | 2383 |
| 2376 } // namespace net | 2384 } // namespace net |
| OLD | NEW |