//ProcessAck in packet public void ProcessAck(NetPacket packet) { ushort ackWindowStart = packet.Sequence; if (ackWindowStart > NetConstants.MaxSequence) { _peer.DebugWrite("[PA]Bad window start"); return; } //check relevance if (NetUtils.RelativeSequenceNumber(ackWindowStart, _localWindowStart) <= -_windowSize) { _peer.DebugWrite("[PA]Old acks"); return; } byte[] acksData = packet.RawData; _peer.DebugWrite("[PA]AcksStart: {0}", ackWindowStart); int startByte = NetConstants.SequencedHeaderSize; Monitor.Enter(_pendingPacketsAccess); for (int i = 0; i < _windowSize; i++) { int ackSequence = (ackWindowStart + i) % NetConstants.MaxSequence; if (NetUtils.RelativeSequenceNumber(ackSequence, _localWindowStart) < 0) { //Skip old ack continue; } int currentByte = startByte + i / BitsInByte; int currentBit = i % BitsInByte; if ((acksData[currentByte] & (1 << currentBit)) == 0) { //Skip false ack continue; } if (ackSequence == _localWindowStart) { //Move window _localWindowStart = (_localWindowStart + 1) % NetConstants.MaxSequence; } int storeIdx = ackSequence % _windowSize; if (_pendingPackets[storeIdx].NotEmpty) { NetPacket removed = _pendingPackets[storeIdx].GetAndClear(); _peer.Recycle(removed); _peer.DebugWrite("[PA]Removing reliableInOrder ack: {0} - true", ackSequence); } else { _peer.DebugWrite("[PA]Removing reliableInOrder ack: {0} - false", ackSequence); } } Monitor.Exit(_pendingPacketsAccess); }