public override void ProcessDataPacket(ITcpDataPacket packet) { if (BasicTcpPacket.CompareSequences((ushort)(_sequenceIn + 1), packet.Sequence) == 0) { // This is exactly what we were expecting _sequenceIn++; if (packet.ResendCount > 0) { PacketCountReceiveDataResend++; } else { PacketCountReceiveDataFirst++; } SendAck(packet, true); Socket.BufferClientData(packet.Data); } else if (BasicTcpPacket.CompareSequences((ushort)(_sequenceIn + 1), packet.Sequence) > 0) { // This is an old packet, don't process (already did that), just send ack #if (DEBUG) Logger.Debug("Got old Data packet, sending ACK, data already processed."); #endif SendAck(packet, false); } else { #if (DEBUG) Logger.Debug("Got unexpected sequence (expected " + _sequenceIn + ") from packet " + packet); #endif } }
// Received this data packet public override void ProcessDataPacket(ITcpDataPacket packet) { if (!Closed) { lock (_processDataLock) { Stats.DataPacketsReceived++; int compareSequences = BasicTcpPacket.CompareSequences(_nextDataSeqIn, packet.Sequence); if (compareSequences == 0) { Stats.ExpectedDataPacketsReceived++; if (BasicTcpPacket.CompareSequences(packet.Sequence, _highestDataSeqIn) > 0) { _highestDataSeqIn = packet.Sequence; } // This is exactly what we were expecting // pop it in our list ITcpDataPacket currentPacket = _recvWindow[_recvWindowsNextFree] = packet; // Now flush our window until we get to a gap while (_recvWindow[_recvWindowsNextFree] != null) { currentPacket = _recvWindow[_recvWindowsNextFree]; // Send Data Upstream (only it not closed) if (!Socket.Closed && !Socket.Closing) { Socket.BufferClientData(currentPacket.Data); } #if DEBUG else { Logger.Debug("Got a data packet, but not writing to socket, because its closed or closing"); } #endif // clear this space in our window _recvWindow[_recvWindowsNextFree] = null; // increment our pointer to next space _recvWindowsNextFree = (byte)((_recvWindowsNextFree + 1) % WindowSize); // increment our next next expected sequence number _nextDataSeqIn++; #if DEBUG Logger.Debug("Processed sq=" + currentPacket.Sequence + " upstream, nextDataSeqIn=" + _nextDataSeqIn + ", recvWindowNextFree=" + _recvWindowsNextFree + ", highestDataSeqIn=" + _highestDataSeqIn); #endif } // Send Ack (only when done with sending all the packets we can) SendAck(currentPacket, currentPacket, true); _lastAckedPacket = currentPacket; } else if (compareSequences > 0) { Stats.OldDataPacketsReceived++; if (packet.ResendCount > 0) { Stats.OldDataResendPacketsReceived++; } // This is an old packet, don't process (already did that), just send ack #if DEBUG Logger.Debug("Got old Data packet (resend=" + packet.ResendCount + "), sending ACK, data already processed."); #endif SendAck(packet, _lastAckedPacket, false); } else { Stats.FutureDataPacketsReceived++; // This is an out of sequence packet from the future, // if it fits in our window, we need to save it for future use int differenceInSequences = DifferenceInSequences(_nextDataSeqIn, packet.Sequence); if (differenceInSequences < WindowSize) { // ok we can put it in _recvWindow[(_recvWindowsNextFree + differenceInSequences) % WindowSize] = packet; if (BasicTcpPacket.CompareSequences(packet.Sequence, _highestDataSeqIn) > 0) { _highestDataSeqIn = packet.Sequence; } #if DEBUG Logger.Debug("Queued sq=" + packet.Sequence + " in window, nextDataSeqIn=" + _nextDataSeqIn + ", recvWindowNextFree=" + _recvWindowsNextFree + ", highestDataSeqIn=" + _highestDataSeqIn); #endif // Now we send an ack for the last in sequence packet we received if (_lastAckedPacket != null) { SendAck(packet, _lastAckedPacket, false); Stats.HoldingAcksSent++; } } else { #if DEBUG Logger.Debug("Got too far in the future sequence (expected " + _nextDataSeqIn + ") from packet " + packet + ", dropping"); #endif // Now we send an ack for the last in sequence packet we received if (_lastAckedPacket != null) { SendAck(_lastAckedPacket, _lastAckedPacket, false); Stats.HoldingAcksSent++; } } } #if DEBUG if (Stats.DataPacketsReceived % 1000 == 0) { Logger.Debug("Received Stats:\n" + Stats.GetReceiverStats()); } #endif Monitor.PulseAll(_processDataLock); } } else { Logger.Error("Failed to process data packet, the connection closed."); } }