Lots of random cleanups, mostly for native_theme_win.cc:
[chromium-blink-merge.git] / net / quic / quic_flow_controller.cc
blob9d0903172cf86ad976b509fc7f7f05c3eb213972
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(QuicConnection* connection,
17 QuicStreamId id,
18 bool is_server,
19 uint64 send_window_offset,
20 uint64 receive_window_offset,
21 uint64 max_receive_window)
22 : connection_(connection),
23 id_(id),
24 is_enabled_(true),
25 is_server_(is_server),
26 bytes_consumed_(0),
27 highest_received_byte_offset_(0),
28 bytes_sent_(0),
29 send_window_offset_(send_window_offset),
30 receive_window_offset_(receive_window_offset),
31 max_receive_window_(max_receive_window),
32 last_blocked_send_window_offset_(0) {
33 DVLOG(1) << ENDPOINT << "Created flow controller for stream " << id_
34 << ", setting initial receive window offset to: "
35 << receive_window_offset_
36 << ", max receive window to: "
37 << max_receive_window_
38 << ", setting send window offset to: " << send_window_offset_;
39 if (connection_->version() <= QUIC_VERSION_16) {
40 DVLOG(1) << ENDPOINT << "Disabling QuicFlowController for stream " << id_
41 << ", QUIC version " << connection_->version();
42 Disable();
46 void QuicFlowController::AddBytesConsumed(uint64 bytes_consumed) {
47 if (!IsEnabled()) {
48 return;
51 bytes_consumed_ += bytes_consumed;
52 DVLOG(1) << ENDPOINT << "Stream " << id_ << " consumed: " << bytes_consumed_;
54 MaybeSendWindowUpdate();
57 bool QuicFlowController::UpdateHighestReceivedOffset(uint64 new_offset) {
58 if (!IsEnabled()) {
59 return false;
62 // Only update if offset has increased.
63 if (new_offset <= highest_received_byte_offset_) {
64 return false;
67 DVLOG(1) << ENDPOINT << "Stream " << id_
68 << " highest byte offset increased from: "
69 << highest_received_byte_offset_ << " to " << new_offset;
70 highest_received_byte_offset_ = new_offset;
71 return true;
74 void QuicFlowController::AddBytesSent(uint64 bytes_sent) {
75 if (!IsEnabled()) {
76 return;
79 if (bytes_sent_ + bytes_sent > send_window_offset_) {
80 LOG(DFATAL) << ENDPOINT << "Stream " << id_ << " Trying to send an extra "
81 << bytes_sent << " bytes, when bytes_sent = " << bytes_sent_
82 << ", and send_window_offset_ = " << send_window_offset_;
83 bytes_sent_ = send_window_offset_;
85 // This is an error on our side, close the connection as soon as possible.
86 connection_->SendConnectionClose(QUIC_FLOW_CONTROL_SENT_TOO_MUCH_DATA);
87 return;
90 bytes_sent_ += bytes_sent;
91 DVLOG(1) << ENDPOINT << "Stream " << id_ << " sent: " << bytes_sent_;
94 bool QuicFlowController::FlowControlViolation() {
95 if (!IsEnabled()) {
96 return false;
99 if (highest_received_byte_offset_ > receive_window_offset_) {
100 LOG(ERROR) << ENDPOINT << "Flow control violation on stream "
101 << id_ << ", receive window offset: "
102 << receive_window_offset_
103 << ", highest received byte offset: "
104 << highest_received_byte_offset_;
105 return true;
107 return false;
110 void QuicFlowController::MaybeSendWindowUpdate() {
111 if (!IsEnabled()) {
112 return;
115 // Send WindowUpdate to increase receive window if
116 // (receive window offset - consumed bytes) < (max window / 2).
117 // This is behaviour copied from SPDY.
118 DCHECK_LT(bytes_consumed_, receive_window_offset_);
119 size_t consumed_window = receive_window_offset_ - bytes_consumed_;
120 size_t threshold = (max_receive_window_ / 2);
122 if (consumed_window < threshold) {
123 // Update our receive window.
124 receive_window_offset_ += (max_receive_window_ - consumed_window);
126 DVLOG(1) << ENDPOINT << "Sending WindowUpdate frame for stream " << id_
127 << ", consumed bytes: " << bytes_consumed_
128 << ", consumed window: " << consumed_window
129 << ", and threshold: " << threshold
130 << ", and max recvw: " << max_receive_window_
131 << ". New receive window offset is: " << receive_window_offset_;
133 // Inform the peer of our new receive window.
134 connection_->SendWindowUpdate(id_, receive_window_offset_);
138 void QuicFlowController::MaybeSendBlocked() {
139 if (!IsEnabled()) {
140 return;
143 if (SendWindowSize() == 0 &&
144 last_blocked_send_window_offset_ < send_window_offset_) {
145 DVLOG(1) << ENDPOINT << "Stream " << id_ << " is flow control blocked. "
146 << "Send window: " << SendWindowSize()
147 << ", bytes sent: " << bytes_sent_
148 << ", send limit: " << send_window_offset_;
149 // The entire send_window has been consumed, we are now flow control
150 // blocked.
151 connection_->SendBlocked(id_);
153 // Keep track of when we last sent a BLOCKED frame so that we only send one
154 // at a given send offset.
155 last_blocked_send_window_offset_ = send_window_offset_;
159 bool QuicFlowController::UpdateSendWindowOffset(uint64 new_send_window_offset) {
160 if (!IsEnabled()) {
161 return false;
164 // Only update if send window has increased.
165 if (new_send_window_offset <= send_window_offset_) {
166 return false;
169 DVLOG(1) << ENDPOINT << "UpdateSendWindowOffset for stream " << id_
170 << " with new offset " << new_send_window_offset
171 << " , current offset: " << send_window_offset_;
173 send_window_offset_ = new_send_window_offset;
174 return true;
177 void QuicFlowController::Disable() {
178 is_enabled_ = false;
181 bool QuicFlowController::IsEnabled() const {
182 bool connection_flow_control_enabled =
183 (id_ == kConnectionLevelId &&
184 FLAGS_enable_quic_connection_flow_control_2);
185 bool stream_flow_control_enabled = (id_ != kConnectionLevelId);
186 return (connection_flow_control_enabled || stream_flow_control_enabled) &&
187 is_enabled_;
190 bool QuicFlowController::IsBlocked() const {
191 return IsEnabled() && SendWindowSize() == 0;
194 uint64 QuicFlowController::SendWindowSize() const {
195 if (bytes_sent_ > send_window_offset_) {
196 return 0;
198 return send_window_offset_ - bytes_sent_;
201 } // namespace net