Add details (where missing) for histograms and remove a few that are not worth provid...
[chromium-blink-merge.git] / net / quic / quic_flow_controller.cc
blob412f250b8e56aa7ba8135e777e004163e42f259f
1 // Copyright 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.
5 #include "net/quic/quic_flow_controller.h"
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"
12 namespace net {
14 #define ENDPOINT (is_server_ ? "Server: " : " Client: ")
16 QuicFlowController::QuicFlowController(QuicVersion version,
17 QuicStreamId id,
18 bool is_server,
19 uint64 send_window_offset,
20 uint64 receive_window_offset,
21 uint64 max_receive_window)
22 : id_(id),
23 is_enabled_(true),
24 is_server_(is_server),
25 bytes_consumed_(0),
26 bytes_buffered_(0),
27 bytes_sent_(0),
28 send_window_offset_(send_window_offset),
29 receive_window_offset_(receive_window_offset),
30 max_receive_window_(max_receive_window),
31 last_blocked_send_window_offset_(0) {
32 DVLOG(1) << ENDPOINT << "Created flow controller for stream " << id_
33 << ", setting initial receive window offset to: "
34 << receive_window_offset_
35 << ", max receive window to: "
36 << max_receive_window_
37 << ", setting send window offset to: " << send_window_offset_;
38 if (version < QUIC_VERSION_17) {
39 DVLOG(1) << ENDPOINT << "Disabling QuicFlowController for stream " << id_
40 << ", QUIC version " << version;
41 Disable();
45 void QuicFlowController::AddBytesConsumed(uint64 bytes_consumed) {
46 if (!IsEnabled()) {
47 return;
50 bytes_consumed_ += bytes_consumed;
51 DVLOG(1) << ENDPOINT << "Stream " << id_ << " consumed: " << bytes_consumed_;
54 void QuicFlowController::AddBytesBuffered(uint64 bytes_buffered) {
55 if (!IsEnabled()) {
56 return;
59 bytes_buffered_ += bytes_buffered;
60 DVLOG(1) << ENDPOINT << "Stream " << id_ << " buffered: " << bytes_buffered_;
63 void QuicFlowController::RemoveBytesBuffered(uint64 bytes_buffered) {
64 if (!IsEnabled()) {
65 return;
68 if (bytes_buffered_ < bytes_buffered) {
69 LOG(DFATAL) << "Trying to remove " << bytes_buffered << " bytes, when only "
70 << bytes_buffered_ << " bytes are buffered";
71 bytes_buffered_ = 0;
72 return;
75 bytes_buffered_ -= bytes_buffered;
76 DVLOG(1) << ENDPOINT << "Stream " << id_ << " buffered: " << bytes_buffered_;
79 void QuicFlowController::AddBytesSent(uint64 bytes_sent) {
80 if (!IsEnabled()) {
81 return;
84 if (bytes_sent_ + bytes_sent > send_window_offset_) {
85 LOG(DFATAL) << ENDPOINT << "Stream " << id_ << " Trying to send an extra "
86 << bytes_sent << " bytes, when bytes_sent = " << bytes_sent_
87 << ", and send_window_offset_ = " << send_window_offset_;
88 bytes_sent_ = send_window_offset_;
89 return;
92 bytes_sent_ += bytes_sent;
93 DVLOG(1) << ENDPOINT << "Stream " << id_ << " sent: " << bytes_sent_;
96 bool QuicFlowController::FlowControlViolation() {
97 if (!IsEnabled()) {
98 return false;
101 if (receive_window_offset_ < TotalReceivedBytes()) {
102 LOG(ERROR)
103 << ENDPOINT << "Flow control violation on stream " << id_
104 << ", receive window: " << receive_window_offset_
105 << ", bytes received: " << TotalReceivedBytes();
107 return true;
109 return false;
112 void QuicFlowController::MaybeSendWindowUpdate(QuicConnection* connection) {
113 if (!IsEnabled()) {
114 return;
117 // Send WindowUpdate to increase receive window if
118 // (receive window offset - consumed bytes) < (max window / 2).
119 // This is behaviour copied from SPDY.
120 size_t consumed_window = receive_window_offset_ - bytes_consumed_;
121 size_t threshold = (max_receive_window_ / 2);
123 if (consumed_window < threshold) {
124 // Update our receive window.
125 receive_window_offset_ += (max_receive_window_ - consumed_window);
127 DVLOG(1) << ENDPOINT << "Sending WindowUpdate frame for stream " << id_
128 << ", consumed bytes: " << bytes_consumed_
129 << ", consumed window: " << consumed_window
130 << ", and threshold: " << threshold
131 << ", and max recvw: " << max_receive_window_
132 << ". New receive window offset is: " << receive_window_offset_;
134 // Inform the peer of our new receive window.
135 connection->SendWindowUpdate(id_, receive_window_offset_);
139 void QuicFlowController::MaybeSendBlocked(QuicConnection* connection) {
140 if (!IsEnabled()) {
141 return;
144 if (SendWindowSize() == 0 &&
145 last_blocked_send_window_offset_ < send_window_offset_) {
146 DVLOG(1) << ENDPOINT << "Stream " << id_ << " is flow control blocked. "
147 << "Send window: " << SendWindowSize()
148 << ", bytes sent: " << bytes_sent_
149 << ", send limit: " << send_window_offset_;
150 // The entire send_window has been consumed, we are now flow control
151 // blocked.
152 connection->SendBlocked(id_);
154 // Keep track of when we last sent a BLOCKED frame so that we only send one
155 // at a given send offset.
156 last_blocked_send_window_offset_ = send_window_offset_;
160 bool QuicFlowController::UpdateSendWindowOffset(uint64 new_send_window_offset) {
161 if (!IsEnabled()) {
162 return false;
165 // Only update if send window has increased.
166 if (new_send_window_offset <= send_window_offset_) {
167 return false;
170 DVLOG(1) << ENDPOINT << "UpdateSendWindowOffset for stream " << id_
171 << " with new offset " << new_send_window_offset
172 << " , current offset: " << send_window_offset_;
174 send_window_offset_ = new_send_window_offset;
175 return true;
178 void QuicFlowController::Disable() {
179 is_enabled_ = false;
182 bool QuicFlowController::IsEnabled() const {
183 bool connection_flow_control_enabled =
184 (id_ == kConnectionLevelId &&
185 FLAGS_enable_quic_connection_flow_control);
186 bool stream_flow_control_enabled =
187 (id_ != kConnectionLevelId &&
188 FLAGS_enable_quic_stream_flow_control_2);
189 return (connection_flow_control_enabled || stream_flow_control_enabled) &&
190 is_enabled_;
193 bool QuicFlowController::IsBlocked() const {
194 return IsEnabled() && SendWindowSize() == 0;
197 uint64 QuicFlowController::SendWindowSize() const {
198 if (bytes_sent_ > send_window_offset_) {
199 return 0;
201 return send_window_offset_ - bytes_sent_;
204 uint64 QuicFlowController::TotalReceivedBytes() const {
205 return bytes_consumed_ + bytes_buffered_;
208 } // namespace net