Exemplo n.º 1
0
        public override bool QueueChunkEx(ChunkFlags flags, int dataSize, byte[] data, int sequence)
        {
            if (ResendQueueConstruct.DataSize +
                dataSize + NetworkCore.PACKET_HEADER_SIZE > NetworkCore.MAX_PAYLOAD)
            {
                Flush();
            }

            var header = new NetworkChunkHeader
            {
                Flags    = flags,
                Size     = dataSize,
                Sequence = sequence
            };

            var chunkDataOffset = ResendQueueConstruct.DataSize;

            chunkDataOffset = header.Pack(ResendQueueConstruct.Data, chunkDataOffset);

            Buffer.BlockCopy(data, 0, ResendQueueConstruct.Data, chunkDataOffset, dataSize);
            chunkDataOffset += dataSize;

            ResendQueueConstruct.NumChunks++;
            ResendQueueConstruct.DataSize = chunkDataOffset;

            if (flags.HasFlag(ChunkFlags.VITAL) && !flags.HasFlag(ChunkFlags.RESEND))
            {
                BufferSize += SIZEOF_NETWORK_CHUNK_RESEND + dataSize;
                if (BufferSize >= BUFFERSIZE)
                {
                    Disconnect("too weak connection (out of buffer)");
                    return(false);
                }

                var resend = new NetworkChunkResend
                {
                    Sequence      = sequence,
                    Flags         = flags,
                    DataSize      = dataSize,
                    Data          = new byte[dataSize],
                    FirstSendTime = Time.Get(),
                    LastSendTime  = Time.Get()
                };

                Buffer.BlockCopy(data, 0, resend.Data, 0, dataSize);
                ResendQueue.Enqueue(resend);
            }

            return(true);
        }
Exemplo n.º 2
0
        private void AddChunk(NetworkChunkConstruct packet, int sequence,
                              byte[] data, int dataSize)
        {
            Debug.Assert(packet.DataSize + NetworkCore.MAX_CHUNK_HEADER_SIZE +
                         dataSize <= packet.Data.Length, "too much data");

            var header = new NetworkChunkHeader
            {
                Flags    = sequence >= 0 ? ChunkFlags.VITAL : ChunkFlags.NONE,
                Size     = dataSize,
                Sequence = sequence >= 0 ? sequence : 0
            };

            var packetDataOffset = packet.DataSize;
            var chunkStartOffset = packetDataOffset;

            packetDataOffset = header.Pack(packet.Data, packetDataOffset);
            packet.DataSize += packetDataOffset - chunkStartOffset;

            Buffer.BlockCopy(data, 0, packet.Data, packetDataOffset, dataSize);
            packet.DataSize += dataSize;
            packet.NumChunks++;
        }
Exemplo n.º 3
0
        public override bool FetchChunk(out NetworkChunk packet)
        {
            var header = new NetworkChunkHeader();
            var end    = ChunkConstruct.DataSize;

            while (true)
            {
                if (!Valid || CurrentChunk >= ChunkConstruct.NumChunks)
                {
                    Clear();
                    packet = null;
                    return(false);
                }

                var dataOffset = 0;
                for (var i = 0; i < CurrentChunk; i++)
                {
                    dataOffset  = header.Unpack(ChunkConstruct.Data, dataOffset);
                    dataOffset += header.Size;
                }

                dataOffset = header.Unpack(ChunkConstruct.Data, dataOffset);
                CurrentChunk++;

                if (dataOffset + header.Size > end)
                {
                    Clear();
                    packet = null;
                    return(false);
                }

                if (Connection != null && header.Flags.HasFlag(ChunkFlags.VITAL))
                {
                    if (Connection.UnknownAck ||
                        header.Sequence == (Connection.Ack + 1) % NetworkCore.MAX_SEQUENCE)
                    {
                        Connection.UnknownAck = false;
                        Connection.Ack        = (Connection.Ack + 1) % NetworkCore.MAX_SEQUENCE;
                    }
                    else
                    {
                        if (NetworkCore.IsSeqInBackroom(header.Sequence, Connection.Ack))
                        {
                            continue;
                        }

                        Debug.Log("connection",
                                  $"asking for resend {header.Sequence} {(Connection.Ack + 1) % NetworkCore.MAX_SEQUENCE}");
                        Connection.SignalResend();
                        continue;
                    }
                }

                packet = new NetworkChunk
                {
                    ClientId = ClientId,
                    EndPoint = EndPoint,
                    Flags    = (SendFlags)header.Flags,
                    DataSize = header.Size,
                    Data     = new byte[header.Size]
                };

                Buffer.BlockCopy(ChunkConstruct.Data, dataOffset, packet.Data, 0, header.Size);
                return(true);
            }
        }