OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "net/quic/quic_flow_controller.h" |
| 6 |
| 7 #include "base/basictypes.h" |
| 8 #include "net/quic/quic_connection.h" |
| 9 #include "net/quic/quic_flags.h" |
| 10 #include "net/quic/quic_protocol.h" |
| 11 |
| 12 namespace net { |
| 13 |
| 14 #define ENDPOINT (is_server_ ? "Server: " : " Client: ") |
| 15 |
| 16 QuicFlowController::QuicFlowController(QuicStreamId id, |
| 17 bool is_server, |
| 18 uint64 send_window_offset, |
| 19 uint64 receive_window_offset, |
| 20 uint64 max_receive_window) |
| 21 : id_(id), |
| 22 is_enabled_(true), |
| 23 is_server_(is_server), |
| 24 bytes_consumed_(0), |
| 25 bytes_buffered_(0), |
| 26 bytes_sent_(0), |
| 27 send_window_offset_(send_window_offset), |
| 28 receive_window_offset_(receive_window_offset), |
| 29 max_receive_window_(max_receive_window) { |
| 30 DVLOG(1) << ENDPOINT << "Created flow controller for stream " << id_ |
| 31 << ", setting initial receive window offset to: " |
| 32 << receive_window_offset_ |
| 33 << ", max receive window to: " |
| 34 << max_receive_window_ |
| 35 << ", setting send window offset to: " << send_window_offset_; |
| 36 } |
| 37 |
| 38 void QuicFlowController::AddBytesConsumed(uint64 bytes_consumed) { |
| 39 if (!IsEnabled()) { |
| 40 return; |
| 41 } |
| 42 |
| 43 bytes_consumed_ += bytes_consumed; |
| 44 DVLOG(1) << ENDPOINT << "Stream " << id_ << " consumed: " << bytes_consumed_; |
| 45 } |
| 46 |
| 47 void QuicFlowController::AddBytesBuffered(uint64 bytes_buffered) { |
| 48 if (!IsEnabled()) { |
| 49 return; |
| 50 } |
| 51 |
| 52 bytes_buffered_ += bytes_buffered; |
| 53 DVLOG(1) << ENDPOINT << "Stream " << id_ << " buffered: " << bytes_buffered_; |
| 54 } |
| 55 |
| 56 void QuicFlowController::RemoveBytesBuffered(uint64 bytes_buffered) { |
| 57 if (!IsEnabled()) { |
| 58 return; |
| 59 } |
| 60 |
| 61 if (bytes_buffered_ < bytes_buffered) { |
| 62 LOG(DFATAL) << "Trying to remove " << bytes_buffered << " bytes, when only " |
| 63 << bytes_buffered_ << " bytes are buffered"; |
| 64 bytes_buffered_ = 0; |
| 65 return; |
| 66 } |
| 67 |
| 68 bytes_buffered_ -= bytes_buffered; |
| 69 DVLOG(1) << ENDPOINT << "Stream " << id_ << " buffered: " << bytes_buffered_; |
| 70 } |
| 71 |
| 72 void QuicFlowController::AddBytesSent(uint64 bytes_sent) { |
| 73 if (!IsEnabled()) { |
| 74 return; |
| 75 } |
| 76 |
| 77 if (bytes_sent_ + bytes_sent > send_window_offset_) { |
| 78 LOG(DFATAL) << "Trying to send an extra " << bytes_sent |
| 79 << " bytes, when bytes_sent = " << bytes_sent_ |
| 80 << ", and send_window = " << send_window_offset_; |
| 81 bytes_sent_ = send_window_offset_; |
| 82 return; |
| 83 } |
| 84 |
| 85 bytes_sent_ += bytes_sent; |
| 86 DVLOG(1) << ENDPOINT << "Stream " << id_ << " sent: " << bytes_sent_; |
| 87 } |
| 88 |
| 89 bool QuicFlowController::FlowControlViolation() { |
| 90 if (receive_window_offset_ < TotalReceivedBytes()) { |
| 91 // TODO(rjshade): Lower severity from DFATAL once we have established that |
| 92 // flow control is working correctly. |
| 93 LOG(DFATAL) |
| 94 << ENDPOINT << "Flow control violation on stream " << id_ |
| 95 << ", receive window: " << receive_window_offset_ |
| 96 << ", bytes received: " << TotalReceivedBytes(); |
| 97 |
| 98 return true; |
| 99 } |
| 100 return false; |
| 101 } |
| 102 |
| 103 void QuicFlowController::MaybeSendWindowUpdate(QuicConnection* connection) { |
| 104 if (!IsEnabled()) { |
| 105 return; |
| 106 } |
| 107 |
| 108 // Send WindowUpdate to increase receive window if |
| 109 // (receive window offset - consumed bytes) < (max window / 2). |
| 110 // This is behaviour copied from SPDY. |
| 111 size_t consumed_window = receive_window_offset_ - bytes_consumed_; |
| 112 size_t threshold = (max_receive_window_ / 2); |
| 113 |
| 114 if (consumed_window < threshold) { |
| 115 // Update our receive window. |
| 116 receive_window_offset_ += (max_receive_window_ - consumed_window); |
| 117 |
| 118 DVLOG(1) << ENDPOINT << "Sending WindowUpdate frame for stream " << id_ |
| 119 << ", consumed bytes: " << bytes_consumed_ |
| 120 << ", consumed window: " << consumed_window |
| 121 << ", and threshold: " << threshold |
| 122 << ", and max recvw: " << max_receive_window_ |
| 123 << ". New receive window offset is: " << receive_window_offset_; |
| 124 |
| 125 // Inform the peer of our new receive window. |
| 126 connection->SendWindowUpdate(id_, receive_window_offset_); |
| 127 } |
| 128 } |
| 129 |
| 130 void QuicFlowController::MaybeSendBlocked(QuicConnection* connection) { |
| 131 if (!IsEnabled()) { |
| 132 return; |
| 133 } |
| 134 |
| 135 if (SendWindowSize() == 0) { |
| 136 DVLOG(1) << ENDPOINT << "Stream " << id_ << " is flow control blocked. " |
| 137 << "Send window: " << SendWindowSize() |
| 138 << ", bytes sent: " << bytes_sent_ |
| 139 << ", send limit: " << send_window_offset_; |
| 140 // The entire send_window has been consumed, we are now flow control |
| 141 // blocked. |
| 142 connection->SendBlocked(id_); |
| 143 } |
| 144 } |
| 145 |
| 146 bool QuicFlowController::UpdateSendWindowOffset(uint64 new_send_window_offset) { |
| 147 // Only update if send window has increased. |
| 148 if (new_send_window_offset <= send_window_offset_) { |
| 149 return false; |
| 150 } |
| 151 |
| 152 DVLOG(1) << ENDPOINT << "UpdateSendWindowOffset for stream " << id_ |
| 153 << " with new offset " << new_send_window_offset |
| 154 << " , current offset: " << send_window_offset_; |
| 155 |
| 156 send_window_offset_ = new_send_window_offset; |
| 157 return true; |
| 158 } |
| 159 |
| 160 void QuicFlowController::Disable() { |
| 161 is_enabled_ = false; |
| 162 } |
| 163 |
| 164 bool QuicFlowController::IsEnabled() const { |
| 165 return FLAGS_enable_quic_stream_flow_control && is_enabled_; |
| 166 } |
| 167 |
| 168 bool QuicFlowController::IsBlocked() const { |
| 169 return IsEnabled() && SendWindowSize() == 0; |
| 170 } |
| 171 |
| 172 uint64 QuicFlowController::SendWindowSize() const { |
| 173 if (bytes_sent_ > send_window_offset_) { |
| 174 return 0; |
| 175 } |
| 176 return send_window_offset_ - bytes_sent_; |
| 177 } |
| 178 |
| 179 uint64 QuicFlowController::TotalReceivedBytes() const { |
| 180 return bytes_consumed_ + bytes_buffered_; |
| 181 } |
| 182 |
| 183 } // namespace net |
OLD | NEW |