Example #1
0
        private void SendAck(ushort sequence)
        {
            // Check the last ack time
            if (!_lastAckTimes.TryGet(sequence, out NetTime value) || ((NetTime.Now - value).TotalMilliseconds > connection.SmoothRoundtrip * config.ReliabilityResendRoundtripMultiplier && (NetTime.Now - value).TotalMilliseconds > config.ReliabilityMinAckResendDelay))
            {
                // Set the last ack time
                _lastAckTimes.Set(sequence, NetTime.Now);

                // Alloc ack memory
                HeapMemory ackMemory = memoryManager.AllocHeapMemory(4 + (uint)(config.EnableMergedAcks ? config.MergedAckBytes : 0));

                // Write header
                ackMemory.Buffer[0] = HeaderPacker.Pack(MessageType.Ack);
                ackMemory.Buffer[1] = (byte)channelId;

                // Write sequence
                ackMemory.Buffer[2] = (byte)sequence;
                ackMemory.Buffer[3] = (byte)(sequence >> 8);

                if (config.EnableMergedAcks)
                {
                    // Reset the memory
                    for (int i = 0; i < config.MergedAckBytes; i++)
                    {
                        ackMemory.Buffer[4 + i] = 0;
                    }

                    // Set the bit fields
                    for (int i = 0; i < config.MergedAckBytes * 8; i++)
                    {
                        ushort bitSequence = (ushort)(sequence - (i + 1));
                        bool   bitAcked    = SequencingUtils.Distance(bitSequence, _incomingLowestAckedSequence, sizeof(ushort)) <= 0 || _incomingAckedSequences.Contains(bitSequence);

                        if (bitAcked)
                        {
                            // Set the ack time for this packet
                            _lastAckTimes.Set(bitSequence, NetTime.Now);
                        }

                        // Write single ack bit
                        ackMemory.Buffer[4 + (i / 8)] |= (byte)((bitAcked ? 1 : 0) << (7 - (i % 8)));
                    }
                }

                // Send ack
                connection.SendInternal(new ArraySegment <byte>(ackMemory.Buffer, 0, 4 + (config.EnableMergedAcks ? config.MergedAckBytes : 0)), false);

                // Return memory
                memoryManager.DeAlloc(ackMemory);
            }
        }
        private void SendAck(ushort sequence)
        {
            // Check the last ack time
            if (!_lastAckTimes.TryGet(sequence, out NetTime value) || ((NetTime.Now - value).TotalMilliseconds > connection.SmoothRoundtrip * config.ReliabilityResendRoundtripMultiplier && (NetTime.Now - value).TotalMilliseconds > config.ReliabilityMinAckResendDelay))
            {
                // Set the last ack time
                _lastAckTimes.Set(sequence, NetTime.Now);

                // Alloc ack memory
                HeapMemory ackMemory = memoryManager.AllocHeapMemory(4);

                // Write header
                ackMemory.Buffer[0] = HeaderPacker.Pack(MessageType.Ack);
                ackMemory.Buffer[1] = (byte)channelId;

                // Write sequence
                ackMemory.Buffer[2] = (byte)sequence;
                ackMemory.Buffer[3] = (byte)(sequence >> 8);

                // Send ack
                connection.SendInternal(new ArraySegment <byte>(ackMemory.Buffer, 0, 4), false);

                // Return memory
                memoryManager.DeAlloc(ackMemory);
            }
        }
        public HeapPointers HandleIncomingMessagePoll(ArraySegment <byte> payload)
        {
            // Read the sequence number
            ushort sequence = (ushort)(payload.Array[payload.Offset] | (ushort)(payload.Array[payload.Offset + 1] << 8));

            lock (_receiveLock)
            {
                if (_incomingAckedPackets.Contains(sequence))
                {
                    // We have already received this message. Ignore it.
                    return(null);
                }

                // Add to sequencer
                _incomingAckedPackets.Set(sequence, true);

                // Alloc pointers
                HeapPointers pointers = memoryManager.AllocHeapPointers(1);

                // Alloc wrapper
                pointers.Pointers[0] = memoryManager.AllocMemoryWrapper(new ArraySegment <byte>(payload.Array, payload.Offset + 2, payload.Count - 2));

                return(pointers);
            }
        }
Example #4
0
        public HeapPointers HandleIncomingMessagePoll(ArraySegment <byte> payload)
        {
            // -> Sorting happens in the ConcurrentCircularQueue when messages are Enqueued

            //

            // Read the sequence number
            ushort sequence = (ushort)(payload.Array[payload.Offset] | (ushort)(payload.Array[payload.Offset + 1] << 8));

            lock (_receiveLock)
            {
                if (_incomingAckedPackets.Contains(sequence))
                {
                    // We have already received this message. Ignore it.
                    return(null);
                }

                /* if (SequencingUtils.Distance(sequence, _incomingLowestAckedSequence, sizeof(ushort)) <= 0)
                 * {
                 *      if (SequencingUtils.Distance(sequence, _lastPollSequence, sizeof(ushort)) > 0)
                 *      {
                 *              Logging.LogInfo("Skipping dropping packet since it's newer than _lastPollSequence (" + _lastPollSequence + ") | _incomingLowestAckedSequence: " + _incomingLowestAckedSequence + " | currentSequence: " + sequence);
                 *      }
                 * } */

                if (SequencingUtils.Distance(sequence, _lastPollSequence, sizeof(ushort)) > 0)
                // ! We're using _lastPollSequence instead of _incomingLowestAckedSequence to not drop old packets if we're still waiting for them to be polled by the game/MLAPI, which can still be sorted properly
                {
                    // Set the new sequence
                    _incomingLowestAckedSequence = sequence;
                    _incomingAckedPackets.Set(sequence, true);

                    // Alloc pointers
                    HeapPointers pointers = memoryManager.AllocHeapPointers(1);

                    // Alloc wrapper
                    pointers.Pointers[0] = memoryManager.AllocMemoryWrapper(new ArraySegment <byte>(payload.Array, payload.Offset + 2, payload.Count - 2));

                    return(pointers);
                }

                return(null);
            }
        }