It seems that stream and connection share exactly the same flow control algorithm. Are the pictures at the end of this post correct ?
If the connection level flow controller is just an aggregation of all the stream's flow controllers (bytes_consumed = sum of all stream's bytes_consumed, etc...), then why not simply removed the WINDOW_UPDATE communication with stream ID = 0, and just make sure that the MaybeSendWindowUpdate() function doesn't use more than what is currently available at the connection level (=looking at aggregate connection counters how much buffer size is mark as "consumed", so = GetMaxFreeBufferSize() ) ?
void QuicFlowController::MaybeSendWindowUpdate() {
// Send WindowUpdate to increase receive window if
// (receive window offset - consumed bytes) < (max window / 2).
// This is behaviour copied from SPDY.
DCHECK_LT(bytes_consumed_, receive_window_offset_);
QuicStreamOffset consumed_window = receive_window_offset_ - bytes_consumed_;
QuicByteCount threshold = (max_receive_window_ / 2);
if (consumed_window < threshold) {
// Update our receive window.
// CURRENT CODE
// receive_window_offset_ += (max_receive_window_ - consumed_window);
// NEW CODE
// receive_window_offset_ += MIN( connection_.GetMaxFreeBufferSize(), (max_receive_window_ - consumed_window) );
DVLOG(1) << ENDPOINT << "Sending WindowUpdate frame for stream " << id_
<< ", consumed bytes: " << bytes_consumed_
<< ", consumed window: " << consumed_window
<< ", and threshold: " << threshold
<< ", and max recvw: " << max_receive_window_
<< ". New receive window offset is: " << receive_window_offset_;
// Inform the peer of our new receive window.
connection_->SendWindowUpdate(id_, receive_window_offset_);
}