| Index: net/quic/reliable_quic_stream.cc
|
| diff --git a/net/quic/reliable_quic_stream.cc b/net/quic/reliable_quic_stream.cc
|
| index 36e87844e8dfd886091ee16f3adc64c20dddcab1..31261bbf145129f86fdd21676377a21350840e01 100644
|
| --- a/net/quic/reliable_quic_stream.cc
|
| +++ b/net/quic/reliable_quic_stream.cc
|
| @@ -6,6 +6,7 @@
|
|
|
| #include "base/logging.h"
|
| #include "net/quic/iovector.h"
|
| +#include "net/quic/quic_flow_controller.h"
|
| #include "net/quic/quic_session.h"
|
| #include "net/quic/quic_write_blocked_list.h"
|
|
|
| @@ -50,7 +51,9 @@ class ReliableQuicStream::ProxyAckNotifierDelegate
|
| virtual void OnAckNotification(int num_original_packets,
|
| int num_original_bytes,
|
| int num_retransmitted_packets,
|
| - int num_retransmitted_bytes) OVERRIDE {
|
| + int num_retransmitted_bytes,
|
| + QuicTime::Delta delta_largest_observed)
|
| + OVERRIDE {
|
| DCHECK_LT(0, pending_acks_);
|
| --pending_acks_;
|
| num_original_packets_ += num_original_packets;
|
| @@ -62,7 +65,8 @@ class ReliableQuicStream::ProxyAckNotifierDelegate
|
| delegate_->OnAckNotification(num_original_packets_,
|
| num_original_bytes_,
|
| num_retransmitted_packets_,
|
| - num_retransmitted_bytes_);
|
| + num_retransmitted_bytes_,
|
| + delta_largest_observed);
|
| }
|
| }
|
|
|
| @@ -113,22 +117,21 @@ ReliableQuicStream::ReliableQuicStream(QuicStreamId id, QuicSession* session)
|
| stream_bytes_written_(0),
|
| stream_error_(QUIC_STREAM_NO_ERROR),
|
| connection_error_(QUIC_NO_ERROR),
|
| - flow_control_send_limit_(
|
| - session_->config()->peer_initial_flow_control_window_bytes()),
|
| - max_flow_control_receive_window_bytes_(
|
| - session_->connection()->max_flow_control_receive_window_bytes()),
|
| - flow_control_receive_window_offset_bytes_(
|
| - session_->connection()->max_flow_control_receive_window_bytes()),
|
| read_side_closed_(false),
|
| write_side_closed_(false),
|
| fin_buffered_(false),
|
| fin_sent_(false),
|
| rst_sent_(false),
|
| - is_server_(session_->is_server()) {
|
| - DVLOG(1) << ENDPOINT << "Created stream " << id_
|
| - << ", setting initial receive window to: "
|
| - << flow_control_receive_window_offset_bytes_
|
| - << ", setting send window to: " << flow_control_send_limit_;
|
| + is_server_(session_->is_server()),
|
| + flow_controller_(
|
| + id_,
|
| + is_server_,
|
| + session_->config()->peer_initial_flow_control_window_bytes(),
|
| + session_->connection()->max_flow_control_receive_window_bytes(),
|
| + session_->connection()->max_flow_control_receive_window_bytes()) {
|
| + if (session_->connection()->version() < QUIC_VERSION_17) {
|
| + flow_controller_.Disable();
|
| + }
|
| }
|
|
|
| ReliableQuicStream::~ReliableQuicStream() {
|
| @@ -159,17 +162,8 @@ bool ReliableQuicStream::OnStreamFrame(const QuicStreamFrame& frame) {
|
|
|
| bool accepted = sequencer_.OnStreamFrame(frame);
|
|
|
| - if (IsFlowControlEnabled()) {
|
| - if (flow_control_receive_window_offset_bytes_ < TotalReceivedBytes()) {
|
| - // TODO(rjshade): Lower severity from DFATAL once we have established that
|
| - // flow control is working correctly.
|
| - LOG(DFATAL)
|
| - << ENDPOINT << "Flow control violation on stream: " << id()
|
| - << ", our receive offset is: "
|
| - << flow_control_receive_window_offset_bytes_
|
| - << ", we have consumed: " << sequencer_.num_bytes_consumed()
|
| - << ", we have buffered: " << sequencer_.num_bytes_buffered()
|
| - << ", total: " << TotalReceivedBytes();
|
| + if (version() >= QUIC_VERSION_17) {
|
| + if (flow_controller_.FlowControlViolation()) {
|
| session_->connection()->SendConnectionClose(QUIC_FLOW_CONTROL_ERROR);
|
| return false;
|
| }
|
| @@ -180,33 +174,8 @@ bool ReliableQuicStream::OnStreamFrame(const QuicStreamFrame& frame) {
|
| }
|
|
|
| void ReliableQuicStream::MaybeSendWindowUpdate() {
|
| - if (!IsFlowControlEnabled()) {
|
| - return;
|
| - }
|
| -
|
| - // Send WindowUpdate to increase receive window if
|
| - // (receive window offset - consumed bytes) < (max window / 2).
|
| - // This is behaviour copied from SPDY.
|
| - size_t consumed_window = flow_control_receive_window_offset_bytes_ -
|
| - sequencer_.num_bytes_consumed();
|
| - size_t threshold = (max_flow_control_receive_window_bytes_ / 2);
|
| - if (consumed_window < threshold) {
|
| - // Update our receive window.
|
| - flow_control_receive_window_offset_bytes_ +=
|
| - (max_flow_control_receive_window_bytes_ - consumed_window);
|
| - DVLOG(1) << ENDPOINT << "Stream: " << id()
|
| - << ", sending WindowUpdate frame. "
|
| - << "Consumed bytes: " << sequencer_.num_bytes_consumed()
|
| - << ", Receive window offset: "
|
| - << flow_control_receive_window_offset_bytes_
|
| - << ", Consumed window: " << consumed_window
|
| - << ", and threshold: " << threshold
|
| - << ". New receive window offset is: "
|
| - << flow_control_receive_window_offset_bytes_;
|
| -
|
| - // Inform the peer of our new receive window.
|
| - session()->connection()->SendWindowUpdate(
|
| - id(), flow_control_receive_window_offset_bytes_);
|
| + if (version() >= QUIC_VERSION_17) {
|
| + flow_controller_.MaybeSendWindowUpdate(session()->connection());
|
| }
|
| }
|
|
|
| @@ -351,15 +320,15 @@ QuicConsumedData ReliableQuicStream::WritevData(
|
| size_t write_length = TotalIovecLength(iov, iov_count);
|
|
|
| // How much data we are allowed to write from flow control.
|
| - size_t send_window = SendWindowSize();
|
| + size_t send_window = flow_controller_.SendWindowSize();
|
|
|
| // A FIN with zero data payload should not be flow control blocked.
|
| bool fin_with_zero_data = (fin && write_length == 0);
|
|
|
| - if (IsFlowControlEnabled()) {
|
| + if (version() >= QUIC_VERSION_17 && flow_controller_.IsEnabled()) {
|
| if (send_window == 0 && !fin_with_zero_data) {
|
| // Quick return if we can't send anything.
|
| - session()->connection()->SendBlocked(id());
|
| + flow_controller_.MaybeSendBlocked(session()->connection());
|
| return QuicConsumedData(0, false);
|
| }
|
|
|
| @@ -380,18 +349,15 @@ QuicConsumedData ReliableQuicStream::WritevData(
|
| id(), data, stream_bytes_written_, fin, ack_notifier_delegate);
|
| stream_bytes_written_ += consumed_data.bytes_consumed;
|
|
|
| + if (version() >= QUIC_VERSION_17 && flow_controller_.IsEnabled()) {
|
| + flow_controller_.AddBytesSent(consumed_data.bytes_consumed);
|
| + }
|
| +
|
| if (consumed_data.bytes_consumed == write_length) {
|
| - if (IsFlowControlEnabled() && write_length == send_window &&
|
| - !fin_with_zero_data) {
|
| - DVLOG(1) << ENDPOINT << "Stream " << id()
|
| - << " is flow control blocked. "
|
| - << "Send window: " << send_window
|
| - << ", stream_bytes_written: " << stream_bytes_written_
|
| - << ", flow_control_send_limit: "
|
| - << flow_control_send_limit_;
|
| - // The entire send_window has been consumed, we are now flow control
|
| - // blocked.
|
| - session()->connection()->SendBlocked(id());
|
| + if (!fin_with_zero_data) {
|
| + if (version() >= QUIC_VERSION_17) {
|
| + flow_controller_.MaybeSendBlocked(session()->connection());
|
| + }
|
| }
|
| if (fin && consumed_data.fin_consumed) {
|
| fin_sent_ = true;
|
| @@ -445,57 +411,26 @@ void ReliableQuicStream::OnClose() {
|
| // written on this stream before termination. Done here if needed, using a
|
| // RST frame.
|
| DVLOG(1) << ENDPOINT << "Sending RST in OnClose: " << id();
|
| - session_->SendRstStream(id(), QUIC_STREAM_NO_ERROR, stream_bytes_written_);
|
| + session_->SendRstStream(id(), QUIC_RST_FLOW_CONTROL_ACCOUNTING,
|
| + stream_bytes_written_);
|
| rst_sent_ = true;
|
| }
|
| }
|
|
|
| void ReliableQuicStream::OnWindowUpdateFrame(
|
| const QuicWindowUpdateFrame& frame) {
|
| - if (!IsFlowControlEnabled()) {
|
| + if (!flow_controller_.IsEnabled()) {
|
| DLOG(DFATAL) << "Flow control not enabled! " << version();
|
| return;
|
| }
|
|
|
| - DVLOG(1) << ENDPOINT
|
| - << "OnWindowUpdateFrame for stream " << id()
|
| - << " with byte offset " << frame.byte_offset
|
| - << " , current offset: " << flow_control_send_limit_ << ").";
|
| -
|
| - UpdateFlowControlSendLimit(frame.byte_offset);
|
| -}
|
| -
|
| -void ReliableQuicStream::UpdateFlowControlSendLimit(QuicStreamOffset offset) {
|
| - if (offset <= flow_control_send_limit_) {
|
| - DVLOG(1) << ENDPOINT << "Stream " << id()
|
| - << ", not changing window, current: " << flow_control_send_limit_
|
| - << " new: " << offset;
|
| - // No change to our send window.
|
| - return;
|
| + if (flow_controller_.UpdateSendWindowOffset(frame.byte_offset)) {
|
| + // We can write again!
|
| + // TODO(rjshade): This does not respect priorities (e.g. multiple
|
| + // outstanding POSTs are unblocked on arrival of
|
| + // SHLO with initial window).
|
| + OnCanWrite();
|
| }
|
| -
|
| - DVLOG(1) << ENDPOINT << "Stream " << id()
|
| - << ", changing window, current: " << flow_control_send_limit_
|
| - << " new: " << offset;
|
| - // Send window has increased.
|
| - flow_control_send_limit_ = offset;
|
| -
|
| - // We can write again!
|
| - // TODO(rjshade): This does not respect priorities (e.g. multiple outstanding
|
| - // POSTs are unblocked on arrival of SHLO with initial window).
|
| - OnCanWrite();
|
| -}
|
| -
|
| -bool ReliableQuicStream::IsFlowControlBlocked() const {
|
| - return IsFlowControlEnabled() && SendWindowSize() == 0;
|
| -}
|
| -
|
| -uint64 ReliableQuicStream::SendWindowSize() const {
|
| - return flow_control_send_limit_ - stream_bytes_written();
|
| -}
|
| -
|
| -uint64 ReliableQuicStream::TotalReceivedBytes() const {
|
| - return sequencer_.num_bytes_consumed() + sequencer_.num_bytes_buffered();
|
| }
|
|
|
| } // namespace net
|
|
|