示例#1
0
        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 (SequencingUtils.Distance(sequence, _incomingLowestAckedSequence, sizeof(ushort)) <= 0 || _incomingAckedSequences.Contains(sequence))
                {
                    // We have already acked this message. Ack again
                    SendAck(sequence);

                    return(null);
                }
                else if (sequence == _incomingLowestAckedSequence + 1)
                {
                    // This is the "next" packet

                    do
                    {
                        // Remove previous
                        _incomingAckedSequences.Remove(_incomingLowestAckedSequence);

                        _incomingLowestAckedSequence++;
                    }while (_incomingAckedSequences.Contains((ushort)(_incomingLowestAckedSequence + 1)));

                    // Ack the new message
                    SendAck(sequence);

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

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

                    return(pointers);
                }
                else if (SequencingUtils.Distance(sequence, _incomingLowestAckedSequence, sizeof(ushort)) > 0 && !_incomingAckedSequences.Contains(sequence))
                {
                    // This is a future packet

                    // Add to sequencer
                    _incomingAckedSequences.Add(sequence);

                    // Ack the new message
                    SendAck(sequence);

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

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

                    return(pointers);
                }

                return(null);
            }
        }
        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 (SequencingUtils.Distance(sequence, _incomingLowestAckedSequence, sizeof(ushort)) <= 0)
                {
                    // We have already acked this message. Ack again

                    SendAck(sequence);

                    return(null);
                }
                else
                {
                    // This is a future packet

                    // Add to sequencer
                    _incomingLowestAckedSequence = sequence;

                    // Send ack
                    SendAck(sequence);

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

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

                    return(pointers);
                }
            }
        }
示例#3
0
        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);
            }
        }
示例#4
0
        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 (SequencingUtils.Distance(sequence, _incomingLowestAckedSequence, sizeof(ushort)) > 0)
                {
                    // Set the new sequence
                    _incomingLowestAckedSequence = sequence;

                    // 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);
                }

                /* else
                 *      Logging.LogInfo("Dropped packet in UnreliableOrdered channel..."); */

                return(null);
            }
        }
        public HeapPointers HandleIncomingMessagePoll(ArraySegment <byte> payload)
        {
            // Alloc pointers
            HeapPointers pointers = memoryManager.AllocHeapPointers(1);

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

            return(pointers);
        }
示例#6
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);
            }
        }
示例#7
0
        public HeapPointers HandleIncomingMessagePoll(ArraySegment <byte> payload)
        {
            // Read the sequence number
            ushort sequence = (ushort)(payload.Array[payload.Offset] | (ushort)(payload.Array[payload.Offset + 1] << 8));
            // Read the raw fragment data
            ushort encodedFragment = (ushort)(payload.Array[payload.Offset + 2] | (ushort)(payload.Array[payload.Offset + 3] << 8));
            // The fragmentId is the last 15 least significant bits
            ushort fragment = (ushort)(encodedFragment & 32767);
            // IsFinal is the most significant bit
            bool isFinal = (ushort)((encodedFragment & 32768) >> 15) == 1;

            if (fragment >= config.MaxFragments)
            {
                if (Logging.CurrentLogLevel <= LogLevel.Error)
                {
                    Logging.LogError("FragmentId was too large. [FragmentId=" + fragment + "] [Config.MaxFragments=" + config.MaxFragments + "]. The fragment was silently dropped, expect a timeout.");
                }
                return(null);
            }

            lock (_receiveLock)
            {
                // If the sequence is older than the last one we sent to user OR the packet is already acked OR the sequence is alive and its complete OR (the sequence is alive AND the fragments is alloced AND the alloced fragment count is larger than the fragment (I.E, the fragment is actually alloced) AND the fragment is not null AND the fragment is not dead))
                if (SequencingUtils.Distance(sequence, _incomingLowestAckedSequence, sizeof(ushort)) <= 0 ||
                    (_incomingAckedSequences.Contains(sequence)) ||
                    (_receiveSequencer.TryGet(sequence, out PendingIncomingPacketFragmented value) && (value.IsComplete || (value.Fragments.VirtualCount > fragment && value.Fragments.Pointers[value.Fragments.VirtualOffset + fragment] != null))))
                {
                    // We have already acked this message. Ack again

                    SendAckEncoded(sequence, encodedFragment);

                    return(null);
                }
                else
                {
                    // This is a packet after the last. One that is not yet completed

                    if (!_receiveSequencer.CanUpdateOrSet(sequence))
                    {
                        // If we cant update or set, that means the window is full and we are not in the window.

                        if (Logging.CurrentLogLevel <= LogLevel.Warning)
                        {
                            Logging.LogWarning("Incoming packet window is exhausted. Expect delays");
                        }
                        return(null);
                    }

                    if (!_receiveSequencer.TryGet(sequence, out value))
                    {
                        // If this is the first fragment we ever get, index the data.

                        HeapPointers fragmentPointers = memoryManager.AllocHeapPointers((uint)fragment + 1);

                        value = new PendingIncomingPacketFragmented()
                        {
                            Fragments = fragmentPointers,
                            Size      = isFinal ? (ushort?)(fragment + 1) : null
                        };

                        _receiveSequencer.Set(sequence, value);
                    }
                    else
                    {
                        // If the first fragment we got was fragment 1 / 500. The fragments array will only be of size 128. We need to potentially resize it
                        if (value.Fragments.Pointers.Length - value.Fragments.VirtualOffset <= fragment)
                        {
                            // We need to expand the fragments array.

                            // Alloc new array
                            HeapPointers newPointers = memoryManager.AllocHeapPointers((uint)fragment + 1);

                            // Copy old values
                            Array.Copy(value.Fragments.Pointers, newPointers.Pointers, value.Fragments.Pointers.Length);

                            // Return the memory for the old
                            memoryManager.DeAlloc(value.Fragments);

                            // Update the index
                            value = new PendingIncomingPacketFragmented()
                            {
                                Fragments = newPointers,
                                Size      = isFinal ? (ushort?)(fragment + 1) : value.Size
                            };

                            _receiveSequencer.Update(sequence, value);
                        }

                        // We might also have to expand the virtual count
                        if (value.Fragments.VirtualCount <= fragment)
                        {
                            // Update the new virtual count
                            value.Fragments.VirtualCount = (uint)fragment + 1;

                            // Update the struct to set the size if it has changed (TODO: Check if needed)
                            value = new PendingIncomingPacketFragmented()
                            {
                                Fragments = value.Fragments,
                                Size      = isFinal ? (ushort?)(fragment + 1) : value.Size
                            };

                            _receiveSequencer.Update(sequence, value);
                        }
                    }

                    // If the fragment is null OR the fragment is DEAD
                    if (value.Fragments.Pointers[value.Fragments.VirtualOffset + fragment] == null)
                    {
                        // Alloc some memory for the fragment
                        HeapMemory memory = memoryManager.AllocHeapMemory((uint)payload.Count - 4);

                        // Copy the payload
                        Buffer.BlockCopy(payload.Array, payload.Offset + 4, memory.Buffer, 0, payload.Count - 4);

                        // Add fragment to index
                        value.Fragments.Pointers[value.Fragments.VirtualOffset + fragment] = memory;
                    }

                    // Send ack
                    SendAckEncoded(sequence, encodedFragment);

                    // If this sequence just completed. Return the memory
                    if (value.IsComplete)
                    {
                        if (sequence == (ushort)(_incomingLowestAckedSequence + 1))
                        {
                            // This is the next packet.

                            do
                            {
                                // Remove previous
                                _incomingAckedSequences.Remove(_incomingLowestAckedSequence);

                                _incomingLowestAckedSequence++;
                            }while (_incomingAckedSequences.Contains((ushort)(_incomingLowestAckedSequence + 1)));
                        }
                        else
                        {
                            // This is a future one
                            _incomingAckedSequences.Add(sequence);
                        }

                        // Get the total size of all fragments
                        uint totalSize = value.TotalByteSize;

                        // Alloc memory for that large segment
                        HeapMemory memory = memoryManager.AllocHeapMemory(totalSize);

                        // Keep track of where we are, fragments COULD have different sizes.
                        int bufferPosition = 0;

                        if (value.Fragments != null)
                        {
                            // Copy all the parts
                            for (int i = 0; i < value.Fragments.VirtualCount; i++)
                            {
                                // Copy fragment to final buffer
                                Buffer.BlockCopy(((HeapMemory)value.Fragments.Pointers[value.Fragments.VirtualOffset + i]).Buffer, (int)((HeapMemory)value.Fragments.Pointers[value.Fragments.VirtualOffset + i]).VirtualOffset, memory.Buffer, bufferPosition, (int)((HeapMemory)value.Fragments.Pointers[value.Fragments.VirtualOffset + i]).VirtualCount);

                                bufferPosition += (int)((HeapMemory)value.Fragments.Pointers[value.Fragments.VirtualOffset + i]).VirtualCount;
                            }
                        }

                        // Free the memory of all the individual fragments
                        value.DeAlloc(memoryManager);

                        // Kill
                        _receiveSequencer.Remove(sequence);

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

                        // Alloc a memory wrapper
                        pointers.Pointers[0] = memoryManager.AllocMemoryWrapper(memory);

                        return(pointers);
                    }

                    return(null);
                }
            }
        }
        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 (SequencingUtils.Distance(sequence, _incomingLowestAckedSequence, sizeof(ushort)) <= 0 || _receiveSequencer.Contains(sequence))
                {
                    // We have already acked this message. Ack again

                    SendAck(sequence);

                    return(null);
                }
                else if (sequence == (ushort)(_incomingLowestAckedSequence + 1))
                {
                    // This is the packet right after

                    _incomingLowestAckedSequence++;

                    // Send ack
                    SendAck(sequence);

                    uint additionalPackets = 0;

                    // Count all the additional sequential packets that are ready
                    for (int i = 1; (_receiveSequencer.TryGet((ushort)(_incomingLowestAckedSequence + i), out PendingIncomingPacket value)); i++)
                    {
                        additionalPackets++;
                    }

                    // Allocate pointers (alloc size 1, we might need more)
                    HeapPointers pointers = memoryManager.AllocHeapPointers(1 + additionalPackets);

                    // Point the first pointer to the memory that is known.
                    pointers.Pointers[0] = memoryManager.AllocMemoryWrapper(new ArraySegment <byte>(payload.Array, payload.Offset + 2, payload.Count - 2));

                    for (int i = 0; _receiveSequencer.TryGet((ushort)(_incomingLowestAckedSequence + 1), out PendingIncomingPacket value); i++)
                    {
                        // Update lowest incoming
                        ++_incomingLowestAckedSequence;

                        // Set the memory
                        pointers.Pointers[1 + i] = memoryManager.AllocMemoryWrapper(value.Memory);

                        // Kill
                        _receiveSequencer.Remove(_incomingLowestAckedSequence);
                    }

                    return(pointers);
                }
                else if (SequencingUtils.Distance(sequence, _incomingLowestAckedSequence, sizeof(ushort)) > 0)
                {
                    // Future packet

                    if (!_receiveSequencer.CanUpdateOrSet(sequence))
                    {
                        // If we cant update or set, that means the window is full and we are not in the window.

                        if (Logging.CurrentLogLevel <= LogLevel.Warning)
                        {
                            Logging.LogWarning("Incoming packet window is exhausted. Expect delays");
                        }
                        return(null);
                    }

                    if (!_receiveSequencer.Contains(sequence))
                    {
                        // Alloc payload plus header memory
                        HeapMemory memory = memoryManager.AllocHeapMemory((uint)payload.Count - 2);

                        // Copy the payload
                        Buffer.BlockCopy(payload.Array, payload.Offset + 2, memory.Buffer, 0, payload.Count - 2);

                        // Add to sequencer
                        _receiveSequencer.Set(sequence, new PendingIncomingPacket()
                        {
                            Memory = memory
                        });

                        // Send ack
                        SendAck(sequence);
                    }
                }

                return(null);
            }
        }