/*
 * Copyright (c) 2014 mucaho (https://github.com/mucaho).
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

package com.github.mucaho.jnetrobust.control;

/**
 * SRTT = (1 - alpha) * SRTT + alpha * R'
 * SRTT += ( R' - SRTT ) * alpha;
 * <p/>
 * RTTVAR = (1 - beta) * RTTVAR + beta * |SRTT - R'|
 * RTTVAR += (| SRTT - R' | - RTTVAR) * beta
 * <p/>
 * alpha = 1/8 = 0.125
 * beta = 1/4 = 0.25
 * K = 4
 * G <= 100ms
 * <p/>
 * RTO = SRTT + max (G, K*RTTVAR)
 * <p/>
 * if timer expires, RTO *= 2, until the RTT of the newly retransmitted message arrives
 */
public class RTTControl {
    private final static float alpha = 1f / 8f;
    private final static float beta = 1f / 4f;

    private final int K;
    private final int G; //ms


    public RTTControl(int k, int g) {
        super();
        K = k;
        G = g;
    }

    private long rto = 3000;
    private Long lastBackoffTime = null;
    private long srtt = 0;
    private long rttvar = 0;


    public long getSmoothedRTT() {
        return this.srtt;
    }

    public long getRTTVariation() {
        return this.rttvar;
    }

    public long getRTO() { // retransmissionTimeOut
        if (lastBackoffTime != null) {
            return this.rto * 2;
        } else {
            return this.rto;
        }
    }

    public void backoff() {
        lastBackoffTime = System.currentTimeMillis();
    }

    public void updateRTT(long packetTimestamp) {
        long rttDelta = System.currentTimeMillis() - packetTimestamp - srtt;

        if (srtt == 0 || rttvar == 0) { // first RTT received
            srtt = rttDelta;
            rttvar = rttDelta / 2;
        } else {
            srtt += rttDelta * alpha;
            rttvar += (Math.abs(rttDelta) - rttvar) * beta;
        }

        rto = srtt + Math.max(G, K * rttvar);

        if (lastBackoffTime != null && packetTimestamp >= lastBackoffTime) {
            lastBackoffTime = null;
        }
    }

}

@@ -622,17 +622,17 @@
 %3Cp/%3E%0A * 
-i
+I
 f timer 
@@ -648,13 +648,93 @@
 RTO 
-*= 2,
++= RTO as linear backoff (or more conservatively RTO *= 2 as exponential backoff),%0A *
  unt
@@ -1088,14 +1088,45 @@
 to =
+ 1000; // or more conservatively
  3000
-;
 %0A   
@@ -1159,24 +1159,59 @@
 ime = null;%0A
+    private int backoffFactor = 1;%0A
     private 
@@ -1451,51 +1451,8 @@
 Out%0A
-        if (lastBackoffTime != null) %7B%0A    
     
@@ -1466,78 +1466,29 @@
 urn 
-this.
 rto * 
-2;%0A        %7D else %7B%0A            return this.r
+backoffFac
 to
+r
 ;%0A
-        %7D%0A
     
@@ -1568,24 +1568,49 @@
 meMillis();%0A
+        backoffFactor++;%0A
     %7D%0A%0A    p
@@ -2104,24 +2104,24 @@
 koffTime) %7B%0A
-
             
@@ -2140,24 +2140,55 @@
 ime = null;%0A
+            backoffFactor = 1;%0A
         %7D%0A  

Add linear backoff to retransmission timeout