code: func (c *cubicState) getCwnd(packetsAcked, sndCwnd int, srtt time.Duration) int {
  	elapsed := time.Since(c.t).Seconds()
  
  	// Compute the window as per Cubic after 'elapsed' time
  	// since last congestion event.
  	c.wC = c.cubicCwnd(elapsed - c.k)
  
  	// Compute the TCP friendly estimate of the congestion window.
  	c.wEst = c.wMax*c.beta + (3.0*((1.0-c.beta)/(1.0+c.beta)))*(elapsed/srtt.Seconds())
  
  	// Make sure in the TCP friendly region CUBIC performs at least
  	// as well as Reno.
  	if c.wC < c.wEst && float64(sndCwnd) < c.wEst {
  		// TCP Friendly region of cubic.
  		return int(c.wEst)
  	}
  
  	// In Concave/Convex region of CUBIC, calculate what CUBIC window
  	// will be after 1 RTT and use that to grow congestion window
  	// for every ack.
  	tEst := (time.Since(c.t) + srtt).Seconds()
  	wtRtt := c.cubicCwnd(tEst - c.k)
  	// As per 4.3 for each received ACK cwnd must be incremented
  	// by (w_cubic(t+RTT) - cwnd/cwnd.
  	cwnd := float64(sndCwnd)
  	for i := 0; i < packetsAcked; i++ {
  		// Concave/Convex regions of cubic have the same formulas.
  		// See: https://tools.ietf.org/html/rfc8312#section-4.3
  		cwnd += (wtRtt - cwnd) / cwnd
  	}
  	return int(cwnd)
  }
docs: // getCwnd returns the current congestion window as computed by CUBIC.
  // Refer: https://tools.ietf.org/html/rfc8312#section-4