public void SendNextPackets() { //Monitor.Enter(_pendingPackets); //get packets from queue Monitor.Enter(_outgoingPackets); int relate = _headPendingPacket == null ? -1 : _headPendingPacket.idx - 1; if (relate < 0) { relate += _windowSize; } PendingPacket tailPendingPacket = _headPendingPacket; while (tailPendingPacket != null && tailPendingPacket.Next != null) { tailPendingPacket = tailPendingPacket.Next; } int packetUsed = 0; int nextPacket = tailPendingPacket == null ? 0 : tailPendingPacket.idx + 1; foreach (NetPacket packet in _outgoingPackets) { if (tailPendingPacket == null || tailPendingPacket.idx == relate) { PendingPacket pendingPacket = _pendingPackets[nextPacket++ % _windowSize]; pendingPacket.Packet = packet; packetUsed++; pendingPacket.Packet.Sequence = (ushort)_localSequence; if (_headPendingPacket == null) { _headPendingPacket = pendingPacket; } if (tailPendingPacket != null) { tailPendingPacket.Next = pendingPacket; } tailPendingPacket = pendingPacket; _localSequence = NetUtils.IncrementSequenceNumber(_localSequence, 1); } else //Queue filled { break; } } _outgoingPackets.RemoveRange(0, packetUsed); Monitor.Exit(_outgoingPackets); ResendPackets(); }
//ProcessAck in packet public void ProcessAck(NetPacket packet) { ushort ackWindowStart = packet.Sequence; if (ackWindowStart >= NetConstants.MaxSequence) { NetUtils.DebugWrite("[PA]Bad window start"); return; } byte[] acksData = packet.RawData; NetUtils.DebugWrite("[PA]AcksStart: {0}", ackWindowStart); //Monitor.Enter(_pendingPackets); for (int idx = 0; idx < packet.GetDataSize(); ++idx) { int currentByte = idx / BitsInByte; int currentBit = idx % BitsInByte; if ((acksData[currentByte] & (1 << currentBit)) == 0) { // Packet not ack, will be resent automaticaly as needed continue; } // packet acknowledged = true int seqAck = NetUtils.IncrementSequenceNumber(ackWindowStart, idx); PendingPacket pendingPacket = _headPendingPacket; PendingPacket prevPacket = null; while (pendingPacket != null) { // Looking for the packet to acknowledge if (pendingPacket.Packet.Sequence != seqAck) { prevPacket = pendingPacket; pendingPacket = pendingPacket.Next; continue; } // Packet found, remove it from the list if (pendingPacket == _headPendingPacket) { _headPendingPacket = pendingPacket.Next; } var packetToClear = pendingPacket; //move forward pendingPacket = pendingPacket.Next; if (prevPacket != null) { prevPacket.Next = pendingPacket; } //clear acked packet packetToClear.Packet.Recycle(); packetToClear.Clear(); NetUtils.DebugWrite("[PA]Removing reliableInOrder ack: {0} - true", seqAck); break; } } //Monitor.Exit(_pendingPackets); }
//Process incoming packet public bool ProcessPacket(NetPacket packet) { if (_mustSendAcksStartTimer <= 0) { _mustSendAcksStartTimer = NetTime.NowMs; } if (packet.Sequence >= NetConstants.MaxSequence) { NetUtils.DebugWrite("[RR]Bad sequence"); return(false); } _packetsToAcknowledge.Add(packet.Sequence); // Check if its a duplicated packet if (_ordered && RelativeSequenceDiff(packet.Sequence, _remoteSequence) < 0) { // Its a duplicated packet return(false); } //detailed check if (packet.Sequence == _remoteSequence) { NetUtils.DebugWrite("[RR]ReliableInOrder packet succes"); _peer.AddIncomingPacket(packet); _remoteSequence = NetUtils.IncrementSequenceNumber(_remoteSequence, 1); if (_ordered) { NetPacket p; while ((p = _receivedPackets[_remoteSequence % _windowSize]) != null) { //process holded packet _receivedPackets[_remoteSequence % _windowSize] = null; _peer.AddIncomingPacket(p); _remoteSequence = NetUtils.IncrementSequenceNumber(_remoteSequence, 1); } } else { while (_earlyReceived[_remoteSequence % _windowSize]) { //process early packet _earlyReceived[_remoteSequence % _windowSize] = false; _remoteSequence = NetUtils.IncrementSequenceNumber(_remoteSequence, 1); } } return(true); } //holded packet if (_ordered) { // Doesnt matter if it overwrites multiple time the same packet _receivedPackets[packet.Sequence % _windowSize] = packet; } else { if (_earlyReceived[packet.Sequence % _windowSize] == false) { _earlyReceived[packet.Sequence % _windowSize] = true; _peer.AddIncomingPacket(packet); } } return(true); }