* * Copyright 2017 gRPC authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http:www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *

package transport

import (
	
	
)

bdpLimit is the maximum value the flow control windows will be increased to. TCP typically limits this to 4MB, but some systems go up to 16MB. Since this is only a limit, it is safe to make it optimistic.
alpha is a constant factor used to keep a moving average of RTTs.
If the current bdp sample is greater than or equal to our beta * our estimated bdp and the current bandwidth sample is the maximum bandwidth observed so far, we increase our bbp estimate by a factor of gamma.
To put our bdp to be smaller than or equal to twice the real BDP, we should multiply our current sample with 4/3, however to round things out we use 2 as the multiplication factor.
	gamma = 2
)
Adding arbitrary data to ping so that its ack can be identified. Easter-egg: what does the ping message say?
var bdpPing = &ping{data: [8]byte{2, 4, 16, 16, 9, 14, 7, 7}}

sentAt is the time when the ping was sent.
bdp is the current bdp estimate.
sample is the number of bytes received in one measurement cycle.
bwMax is the maximum bandwidth noted so far (bytes/sec).
bool to keep track of the beginning of a new measurement cycle.
Callback to update the window sizes.
sampleCount is the number of samples taken so far.
round trip time (seconds)
timesnap registers the time bdp ping was sent out so that network rtt can be calculated when its ack is received. It is called (by controller) when the bdpPing is being written on the wire.
func ( *bdpEstimator) ( [8]byte) {
	if bdpPing.data !=  {
		return
	}
	.sentAt = time.Now()
}
add adds bytes to the current sample for calculating bdp. It returns true only if a ping must be sent. This can be used by the caller (handleData) to make decision about batching a window update with it.
func ( *bdpEstimator) ( uint32) bool {
	.mu.Lock()
	defer .mu.Unlock()
	if .bdp == bdpLimit {
		return false
	}
	if !.isSent {
		.isSent = true
		.sample = 
		.sentAt = time.Time{}
		.sampleCount++
		return true
	}
	.sample += 
	return false
}
calculate is called when an ack for a bdp ping is received. Here we calculate the current bdp and bandwidth sample and decide if the flow control windows should go up.
Check if the ping acked for was the bdp ping.
	if bdpPing.data !=  {
		return
	}
	.mu.Lock()
	 := time.Since(.sentAt).Seconds()
Bootstrap rtt with an average of first 10 rtt samples.
		.rtt += ( - .rtt) / float64(.sampleCount)
Heed to the recent past more.
		.rtt += ( - .rtt) * float64(alpha)
	}
The number of bytes accumulated so far in the sample is smaller than or equal to 1.5 times the real BDP on a saturated connection.
	 := float64(.sample) / (.rtt * float64(1.5))
	if  > .bwMax {
		.bwMax = 
If the current sample (which is smaller than or equal to the 1.5 times the real BDP) is greater than or equal to 2/3rd our perceived bdp AND this is the maximum bandwidth seen so far, we should update our perception of the network BDP.
	if float64(.sample) >= beta*float64(.bdp) &&  == .bwMax && .bdp != bdpLimit {
		 := float64(.sample)
		.bdp = uint32(gamma * )
		if .bdp > bdpLimit {
			.bdp = bdpLimit
		}
		 := .bdp
		.mu.Unlock()
		.updateFlowControl()
		return
	}
	.mu.Unlock()