void SequenceNumberStats::sequenceNumberReceived(quint16 incoming, QUuid senderUUID, const bool wantExtraDebugging) { // if the sender node has changed, reset all stats if (senderUUID != _lastSenderUUID) { qDebug() << "sequence number stats was reset due to new sender node"; qDebug() << "previous:" << _lastSenderUUID << "current:" << senderUUID; reset(); _lastSenderUUID = senderUUID; } // determine our expected sequence number... handle rollover appropriately quint16 expected = _stats._numReceived > 0 ? _lastReceived + (quint16)1 : incoming; _stats._numReceived++; if (incoming == expected) { // on time _lastReceived = incoming; } else { // out of order if (wantExtraDebugging) { qDebug() << "out of order... got:" << incoming << "expected:" << expected; } int incomingInt = (int)incoming; int expectedInt = (int)expected; // check if the gap between incoming and expected is reasonable, taking possible rollover into consideration int absGap = std::abs(incomingInt - expectedInt); if (absGap >= UINT16_RANGE - MAX_REASONABLE_SEQUENCE_GAP) { // rollover likely occurred between incoming and expected. // correct the larger of the two so that it's within [-UINT16_RANGE, -1] while the other remains within [0, UINT16_RANGE-1] if (incomingInt > expectedInt) { incomingInt -= UINT16_RANGE; } else { expectedInt -= UINT16_RANGE; } } else if (absGap > MAX_REASONABLE_SEQUENCE_GAP) { // ignore packet if gap is unreasonable qDebug() << "ignoring unreasonable sequence number:" << incoming << "previous:" << _lastReceived; _stats._numUnreasonable++; return; } // now that rollover has been corrected for (if it occurred), incoming and expected can be // compared to each other directly, though one of them might be negative if (incomingInt > expectedInt) { // early if (wantExtraDebugging) { qDebug() << "this packet is earlier than expected..."; qDebug() << ">>>>>>>> missing gap=" << (incomingInt - expectedInt); } _stats._numEarly++; _stats._numLost += (incomingInt - expectedInt); _lastReceived = incoming; // add all sequence numbers that were skipped to the missing sequence numbers list for (int missingInt = expectedInt; missingInt < incomingInt; missingInt++) { _missingSet.insert((quint16)(missingInt < 0 ? missingInt + UINT16_RANGE : missingInt)); } // prune missing sequence list if it gets too big; sequence numbers that are older than MAX_REASONABLE_SEQUENCE_GAP // will be removed. if (_missingSet.size() > MAX_REASONABLE_SEQUENCE_GAP) { pruneMissingSet(wantExtraDebugging); } } else { // late if (wantExtraDebugging) { qDebug() << "this packet is later than expected..."; } _stats._numLate++; // do not update _lastReceived; it shouldn't become smaller // remove this from missing sequence number if it's in there if (_missingSet.remove(incoming)) { if (wantExtraDebugging) { qDebug() << "found it in _missingSet"; } _stats._numLost--; _stats._numRecovered++; } else { if (wantExtraDebugging) { qDebug() << "sequence:" << incoming << "was NOT found in _missingSet and is probably a duplicate"; } _stats._numDuplicate++; } } } }
SequenceNumberStats::ArrivalInfo SequenceNumberStats::sequenceNumberReceived(quint16 incoming, NetworkLocalID senderID, const bool wantExtraDebugging) { SequenceNumberStats::ArrivalInfo arrivalInfo; // if the sender node has changed, reset all stats if (senderID != _lastSenderID) { if (_stats._received > 0) { qCDebug(networking) << "sequence number stats was reset due to new sender node"; qCDebug(networking) << "previous:" << _lastSenderID << "current:" << senderID; reset(); } _lastSenderID = senderID; } // determine our expected sequence number... handle rollover appropriately quint16 expected = _stats._received > 0 ? _lastReceivedSequence + (quint16)1 : incoming; _stats._received++; if (incoming == expected) { // on time arrivalInfo._status = OnTime; _lastReceivedSequence = incoming; _stats._expectedReceived++; } else { // out of order if (wantExtraDebugging) { qCDebug(networking) << "out of order... got:" << incoming << "expected:" << expected; } int incomingInt = (int)incoming; int expectedInt = (int)expected; // check if the gap between incoming and expected is reasonable, taking possible rollover into consideration int absGap = abs(incomingInt - expectedInt); if (absGap >= UINT16_RANGE - MAX_REASONABLE_SEQUENCE_GAP) { // rollover likely occurred between incoming and expected. // correct the larger of the two so that it's within [-UINT16_RANGE, -1] while the other remains within [0, UINT16_RANGE-1] if (incomingInt > expectedInt) { incomingInt -= UINT16_RANGE; } else { expectedInt -= UINT16_RANGE; } } else if (absGap > MAX_REASONABLE_SEQUENCE_GAP) { arrivalInfo._status = Unreasonable; HIFI_FCDEBUG(networking(), "unreasonable sequence number:" << incoming << "previous:" << _lastReceivedSequence); _stats._unreasonable++; receivedUnreasonable(incoming); return arrivalInfo; } // now that rollover has been corrected for (if it occurred), incomingInt and expectedInt can be // compared to each other directly, though one of them might be negative arrivalInfo._seqDiffFromExpected = incomingInt - expectedInt; if (incomingInt > expectedInt) { // early arrivalInfo._status = Early; if (wantExtraDebugging) { qCDebug(networking) << "this packet is earlier than expected..."; qCDebug(networking) << ">>>>>>>> missing gap=" << (incomingInt - expectedInt); } int skipped = incomingInt - expectedInt; _stats._early++; _stats._lost += skipped; _stats._expectedReceived += (skipped + 1); _lastReceivedSequence = incoming; // add all sequence numbers that were skipped to the missing sequence numbers list for (int missingInt = expectedInt; missingInt < incomingInt; missingInt++) { _missingSet.insert((quint16)(missingInt < 0 ? missingInt + UINT16_RANGE : missingInt)); } // prune missing sequence list if it gets too big; sequence numbers that are older than MAX_REASONABLE_SEQUENCE_GAP // will be removed. if (_missingSet.size() > MAX_REASONABLE_SEQUENCE_GAP) { pruneMissingSet(wantExtraDebugging); } } else { // late if (wantExtraDebugging) { qCDebug(networking) << "this packet is later than expected..."; } _stats._late++; // do not update _lastReceived; it shouldn't become smaller // remove this from missing sequence number if it's in there if (_missingSet.remove(incoming)) { arrivalInfo._status = Recovered; if (wantExtraDebugging) { qCDebug(networking) << "found it in _missingSet"; } if (_stats._lost > 0) { _stats._lost--; _stats._recovered++; } } else { // this late seq num is not in our missing set. it is possibly a duplicate, or possibly a late // packet that should have arrived before our first received packet. we'll count these // as unreasonable. arrivalInfo._status = Unreasonable; HIFI_FCDEBUG(networking(), "unreasonable sequence number:" << incoming << "(possible duplicate)"); _stats._unreasonable++; receivedUnreasonable(incoming); return arrivalInfo; } } } // if we've made it here, we received a reasonable seq number. _consecutiveUnreasonableOnTime = 0; return arrivalInfo; }