/// <summary> /// process ACK event (see spec. p 12) /// </summary> /// <param name="isTriggeredByTimer"></param> protected void processACKEvent(bool isTriggeredByTimer) { try { //(1).Find the sequence number *prior to which* all the packets have been received long ackNumber; ReceiverLossListEntry entry = receiverLossList.getFirstEntry(); if (entry == null) { ackNumber = largestReceivedSeqNumber + 1; } else { ackNumber = entry.getSequenceNumber(); } //(2).a) if ackNumber equals to the largest sequence number ever acknowledged by ACK2 if (ackNumber == largestAcknowledgedAckNumber) { //do not send this ACK return; } else if (ackNumber == lastAckNumber) { //or it is equals to the ackNumber in the last ACK //and the time interval between these two ACK packets //is less than 2 RTTs,do not send(stop) long timeOfLastSentAck = ackHistoryWindow.getTime(lastAckNumber); if (Util.getCurrentTime() - timeOfLastSentAck < 2 * roundTripTime) { return; } } long ackSeqNumber; //if this ACK is not triggered by ACK timers,send out a light Ack and stop. if (!isTriggeredByTimer) { ackSeqNumber = sendLightAcknowledgment(ackNumber); return; } else { //pack the packet speed and link capacity into the ACK packet and send it out. //(7).records the ACK number,ackseqNumber and the departure time of //this Ack in the ACK History Window ackSeqNumber = sendAcknowledgment(ackNumber); } AckHistoryEntry sentAckNumber = new AckHistoryEntry(ackSeqNumber, ackNumber, Util.getCurrentTime()); ackHistoryWindow.add(sentAckNumber); //store ack number for next iteration lastAckNumber = ackNumber; } catch (Exception exc) { Log.Write(this.ToString(), exc); } }
/** * write a NAK triggered by a received sequence number that is larger than * the largestReceivedSeqNumber + 1 * @param currentSequenceNumber - the currently received sequence number * @throws IOException */ protected void SendNAK(long currentSequenceNumber) { NegativeAcknowledgement nAckPacket = new NegativeAcknowledgement(); nAckPacket.AddLossInfo(largestReceivedSeqNumber + 1, currentSequenceNumber); nAckPacket.SetSession(session); nAckPacket.DestinationID = session.Destination.SocketID; //put all the sequence numbers between (but excluding) these two values into the //receiver loss list for (long i = largestReceivedSeqNumber + 1; i < currentSequenceNumber; i++) { ReceiverLossListEntry detectedLossSeqNumber = new ReceiverLossListEntry(i); receiverLossList.Insert(detectedLossSeqNumber); } endpoint.DoSend(nAckPacket); //logger.info("NAK for "+currentSequenceNumber); statistics.incNumberOfNAKSent(); }
/** * write a NAK triggered by a received sequence number that is larger than * the largestReceivedSeqNumber + 1 * @param currentSequenceNumber - the currently received sequence number * @throws IOException */ protected void sendNAK(long currentSequenceNumber) { try { NegativeAcknowledgement nAckPacket = new NegativeAcknowledgement(); nAckPacket.addLossInfo(largestReceivedSeqNumber + 1, currentSequenceNumber); nAckPacket.setSession(session); nAckPacket.setDestinationID(session.getDestination().getSocketID()); //put all the sequence numbers between (but excluding) these two values into the //receiver loss list for (long i = largestReceivedSeqNumber + 1; i < currentSequenceNumber; i++) { ReceiverLossListEntry detectedLossSeqNumber = new ReceiverLossListEntry(i); receiverLossList.insert(detectedLossSeqNumber); } endpoint.doSend(nAckPacket); //logger.info("NAK for "+currentSequenceNumber); statistics.incNumberOfNAKSent(); } catch (Exception exc) { Log.Write(this.ToString(), exc); } }