protected void onAcknowledge(Acknowledgement acknowledgement) { try { waitForAckLatch.Get().CountDown(); waitForSeqAckLatch.Get().CountDown(); CongestionControl cc = session.getCongestionControl(); long rtt = acknowledgement.getRoundTripTime(); if (rtt > 0) { long rttVar = acknowledgement.getRoundTripTimeVar(); cc.setRTT(rtt, rttVar); statistics.setRTT(rtt, rttVar); } long rate = acknowledgement.getPacketReceiveRate(); if (rate > 0) { long linkCapacity = acknowledgement.getEstimatedLinkCapacity(); cc.updatePacketArrivalRate(rate, linkCapacity); statistics.setPacketArrivalRate(cc.getPacketArrivalRate(), cc.getEstimatedLinkCapacity()); } long ackNumber = acknowledgement.getAckNumber(); cc.onACK(ackNumber); statistics.setCongestionWindowSize((long)cc.getCongestionWindowSize()); //need to remove all sequence numbers up the ack number from the sendBuffer bool removed = false; for (long s = lastAckSequenceNumber; s < ackNumber; s++) { lock (sendLock) { removed = sendBuffer.Remove(s); } if (removed) { unacknowledged.DecrementAndGet(); } } lastAckSequenceNumber = (int)Math.Max(lastAckSequenceNumber, ackNumber); //send ACK2 packet to the receiver sendAck2(ackNumber); statistics.incNumberOfACKReceived(); if (storeStatistics) { statistics.storeParameters(); } } catch (Exception ex) { Log.Write(this.ToString(), ex); } }
/** * spec p. 13: <br/> * 1) Locate the related ACK in the ACK History Window according to the * ACK sequence number in this ACK2. <br/> * 2) Update the largest ACK number ever been acknowledged. <br/> * 3) Calculate new rtt according to the ACK2 arrival time and the ACK * departure time, and update the RTT value as: RTT = (RTT * 7 + * rtt) / 8. <br/> * 4) Update RTTVar by: RTTVar = (RTTVar * 3 + abs(RTT - rtt)) / 4. <br/> * 5) Update both ACK and NAK period to 4 * RTT + RTTVar + SYN. <br/> */ protected void onAck2PacketReceived(Acknowledgment2 ack2) { AckHistoryEntry entry = ackHistoryWindow.getEntry(ack2.getAckSequenceNumber()); if (entry != null) { long ackNumber = entry.getAckNumber(); largestAcknowledgedAckNumber = (int)Math.Max(ackNumber, largestAcknowledgedAckNumber); long rtt = entry.getAge(); if (roundTripTime > 0) { roundTripTime = (roundTripTime * 7 + rtt) / 8; } else { roundTripTime = rtt; } roundTripTimeVar = (roundTripTimeVar * 3 + Math.Abs(roundTripTimeVar - rtt)) / 4; ackTimerInterval = 4 * roundTripTime + roundTripTimeVar + Util.getSYNTime(); nakTimerInterval = ackTimerInterval; statistics.setRTT(roundTripTime, roundTripTimeVar); } }