Moves //gfe/gfe2/http2:window_manager to //third_party/http2/adapter. PiperOrigin-RevId: 364328994 Change-Id: I0899a629122cfe88f2f952ad5dae00e1331c57bc
diff --git a/http2/adapter/window_manager.cc b/http2/adapter/window_manager.cc new file mode 100644 index 0000000..148931f --- /dev/null +++ b/http2/adapter/window_manager.cc
@@ -0,0 +1,100 @@ +#include "http2/adapter/window_manager.h" + +#include <utility> + +#include "common/platform/api/quiche_logging.h" +#include "spdy/platform/api/spdy_bug_tracker.h" + +namespace http2 { +namespace adapter { + +WindowManager::WindowManager(size_t window_size_limit, + WindowUpdateListener listener) + : limit_(window_size_limit), window_(window_size_limit), buffered_(0), + listener_(std::move(listener)) {} + +void WindowManager::OnWindowSizeLimitChange(const size_t new_limit) { + QUICHE_VLOG(2) << "WindowManager@" << this + << " OnWindowSizeLimitChange from old limit of " << limit_ + << " to new limit of " << new_limit; + if (new_limit > limit_) { + window_ += (new_limit - limit_); + } else { + SPDY_BUG_V2(H2 window decrease) + << "Window size limit decrease not currently supported."; + } + limit_ = new_limit; +} + +void WindowManager::SetWindowSizeLimit(size_t new_limit) { + QUICHE_VLOG(2) << "WindowManager@" << this + << " SetWindowSizeLimit from old limit of " << limit_ + << " to new limit of " << new_limit; + limit_ = new_limit; + MaybeNotifyListener(); +} + +bool WindowManager::MarkDataBuffered(size_t bytes) { + QUICHE_VLOG(2) << "WindowManager@" << this << " window: " << window_ + << " bytes: " << bytes; + if (window_ < bytes) { + QUICHE_VLOG(2) << "WindowManager@" << this << " window underflow " + << "window: " << window_ << " bytes: " << bytes; + window_ = 0; + } else { + window_ -= bytes; + } + buffered_ += bytes; + if (window_ == 0) { + // If data hasn't been flushed in a while there may be space available. + MaybeNotifyListener(); + } + return window_ > 0; +} + +void WindowManager::MarkDataFlushed(size_t bytes) { + QUICHE_VLOG(2) << "WindowManager@" << this << " buffered: " << buffered_ + << " bytes: " << bytes; + if (buffered_ < bytes) { + SPDY_BUG_V2(bug_2816_1) + << "WindowManager@" << this << " buffered underflow " + << "buffered_: " << buffered_ << " bytes: " << bytes; + buffered_ = 0; + } else { + buffered_ -= bytes; + } + MaybeNotifyListener(); +} + +void WindowManager::MaybeNotifyListener() { + if (buffered_ + window_ > limit_) { + QUICHE_LOG(ERROR) << "Flow control violation; limit: " << limit_ + << " buffered: " << buffered_ << " window: " << window_; + return; + } + // For the sake of efficiency, we want to send window updates if less than + // half of the max quota is available to the peer at any point in time. + // http://google3/gfe/gfe2/stubby/autobahn_fd_wrapper.cc?l=1180-1183&rcl=307416556 + const size_t kDesiredMinWindow = limit_ / 2; + const size_t kDesiredMinDelta = limit_ / 3; + const size_t delta = limit_ - (buffered_ + window_); + bool send_update = false; + if (delta >= kDesiredMinDelta) { + // This particular window update was sent because the available delta + // exceeded the desired minimum. + send_update = true; + } else if (window_ < kDesiredMinWindow) { + // This particular window update was sent because the quota available to the + // peer at this moment is less than the desired minimum. + send_update = true; + } + if (send_update && delta > 0) { + QUICHE_VLOG(2) << "WindowManager@" << this + << " Informing listener of delta: " << delta; + listener_(delta); + window_ += delta; + } +} + +} // namespace adapter +} // namespace http2