Beispiel #1
0
        public static unsafe void ReadAckPacket(NetworkPipelineContext context, PacketHeader header)
        {
            SharedContext *reliable = (SharedContext *)context.internalSharedProcessBuffer.GetUnsafePtr();

            // Store receive timestamp for our acked sequence ID with remote processing time
            StoreReceiveTimestamp(context.internalSharedProcessBuffer, header.AckedSequenceId, context.timestamp, header.ProcessingTime);

            // Check the distance of the acked seqId in the header, if it's too far away from last acked packet we
            // can't process it and add it to the ack mask
            if (!SequenceHelpers.GreaterThan16(header.AckedSequenceId, (ushort)reliable->SentPackets.Acked))
            {
                // No new acks;
                return;
            }

            reliable->SentPackets.Acked   = header.AckedSequenceId;
            reliable->SentPackets.AckMask = header.AckMask;
        }
Beispiel #2
0
        /// <summary>
        /// Read header data and update reliability tracking information in the shared context.
        /// - If the packets sequence ID is lower than the last received ID+1, then it's stale
        /// - If the packets sequence ID is higher, then we'll process it and update tracking info in the shared context
        /// </summary>
        /// <param name="context">Pipeline context, the reliability shared state is used here.</param>
        /// <param name="header">Packet header of a new received packet.</param>
        /// <returns>Sequence ID of the received packet.</returns>
        public static unsafe int Read(NetworkPipelineContext context, PacketHeader header)
        {
            SharedContext *reliable = (SharedContext *)context.internalSharedProcessBuffer.GetUnsafePtr();

            reliable->stats.PacketsReceived++;
            if (SequenceHelpers.StalePacket(
                    header.SequenceId,
                    (ushort)(reliable->ReceivedPackets.Sequence + 1),
                    (ushort)reliable->WindowSize))
            {
                reliable->stats.PacketsStale++;
                return((int)ErrorCodes.Stale_Packet);
            }

            var window = reliable->WindowSize - 1;

            if (SequenceHelpers.GreaterThan16((ushort)(header.SequenceId + 1), (ushort)reliable->ReceivedPackets.Sequence))
            {
                int distance = SequenceHelpers.AbsDistance(header.SequenceId, (ushort)reliable->ReceivedPackets.Sequence);

                for (var i = 0; i < Math.Min(distance, window); ++i)
                {
                    if ((reliable->ReceivedPackets.AckMask & 1 << (window - i)) == 0)
                    {
                        reliable->stats.PacketsDropped++;
                    }
                }

                if (distance > window)
                {
                    reliable->stats.PacketsDropped   += distance - window;
                    reliable->ReceivedPackets.AckMask = 1;
                }
                else
                {
                    reliable->ReceivedPackets.AckMask <<= distance;
                    reliable->ReceivedPackets.AckMask  |= 1;
                }

                reliable->ReceivedPackets.Sequence = header.SequenceId;
            }
            else if (SequenceHelpers.LessThan16(header.SequenceId, (ushort)reliable->ReceivedPackets.Sequence))
            {
                int distance = SequenceHelpers.AbsDistance(header.SequenceId, (ushort)reliable->ReceivedPackets.Sequence);
                // If this is a resent packet the distance will seem very big and needs to be calculated again with adjustment for wrapping
                if (distance >= ushort.MaxValue - reliable->WindowSize)
                {
                    distance = reliable->ReceivedPackets.Sequence - header.SequenceId;
                }

                var ackBit = 1 << distance;
                if ((ackBit & reliable->ReceivedPackets.AckMask) != 0)
                {
                    reliable->stats.PacketsDuplicated++;
                    return((int)ErrorCodes.Duplicated_Packet);
                }

                reliable->stats.PacketsOutOfOrder++;
                reliable->ReceivedPackets.AckMask |= (uint)ackBit;
            }

            // Store receive timestamp for remote sequence ID we just received
            StoreRemoteReceiveTimestamp(context.internalSharedProcessBuffer, header.SequenceId, context.timestamp);

            ReadAckPacket(context, header);

            return(header.SequenceId);
        }