handleAckFrame method
Processes an incoming AckFrame, marking packets as acknowledged. Returns a list of sequence numbers that were successfully acknowledged by this frame.
Implementation
List<int> handleAckFrame(AckFrame frame) {
final newlyAckedSequences = <int>[];
// Process the first range (ending at largestAcked)
// largestAcked is inclusive. firstAckRangeLength is the count of packets in this range.
// So, the smallest sequence in this range is largestAcked - firstAckRangeLength + 1.
if (frame.firstAckRangeLength > 0) {
for (int i = 0; i < frame.firstAckRangeLength; i++) {
final seq = frame.largestAcked - i;
if (_sentPackets.containsKey(seq)) {
final packet = _sentPackets.remove(seq);
packet?.isAcked = true;
_retransmitTimers[seq]?.cancel();
_retransmitTimers.remove(seq);
newlyAckedSequences.add(seq);
}
}
}
// Process additional ACK ranges
// Ranges are ordered from highest sequence numbers to lowest.
// `gap` is relative to the *start* of the previously processed (higher sequence) range.
int currentSeq = frame.largestAcked - frame.firstAckRangeLength; // Sequence just below the first range
for (final rangeBlock in frame.ackRanges) {
// The current range's highest packet (rangeEnd) is `rangeBlock.gap` packets below `currentSeq`.
// `currentSeq` represents the packet number immediately preceding the lowest packet of the previously acked block.
final rangeEnd = currentSeq - rangeBlock.gap; // CORRECTED
for (int i = 0; i < rangeBlock.ackRangeLength; i++) {
final seq = rangeEnd - i;
if (_sentPackets.containsKey(seq)) {
final packet = _sentPackets.remove(seq);
packet?.isAcked = true;
_retransmitTimers[seq]?.cancel();
_retransmitTimers.remove(seq);
newlyAckedSequences.add(seq);
}
}
// Update currentSeq for the next iteration: it should be the packet number
// immediately preceding the lowest packet of the range just processed.
// Lowest packet in current range = rangeEnd - rangeBlock.ackRangeLength + 1.
currentSeq = (rangeEnd - rangeBlock.ackRangeLength + 1) - 1; // CORRECTED
}
return newlyAckedSequences;
}