Exemplo n.º 1
0
        public bool Read(ByteArrayReaderWriter stream, int length, byte[] key, ulong protocolID)
        {
            Payload = BufferPool.GetBuffer(2048);
            Length  = 0;
            try
            {
                Length = PacketIO.ReadPacketData(Header, stream, length, protocolID, key, Payload);
            }
            catch
            {
                BufferPool.ReturnBuffer(Payload);
                return(false);
            }

            if (Length < 1 || Length > Defines.MAX_PAYLOAD_SIZE)
            {
                BufferPool.ReturnBuffer(Payload);
                return(false);
            }

            return(true);
        }
        public void StoreFragmentData(byte channelID, ushort sequence, ushort ack, uint ackBits, int fragmentID, int fragmentSize, byte[] fragmentData, int fragmentBytes, bool compressed)
        {
            int copyOffset = 0;

            if (fragmentID == 0)
            {
                byte[] packetHeader = BufferPool.GetBuffer(Defines.MAX_PACKET_HEADER_BYTES);
                int    headerBytes  = PacketIO.WritePacketHeader(packetHeader, channelID, sequence, ack, ackBits, compressed);
                this.HeaderOffset = Defines.MAX_PACKET_HEADER_BYTES - headerBytes;

                if (this.PacketDataBuffer.Length < (Defines.MAX_PACKET_HEADER_BYTES + fragmentSize))
                {
                    this.PacketDataBuffer.SetSize(Defines.MAX_PACKET_HEADER_BYTES + fragmentSize);
                }

                this.PacketDataBuffer.BufferCopy(packetHeader, 0, this.HeaderOffset, headerBytes);
                copyOffset = headerBytes;

                fragmentBytes -= headerBytes;

                BufferPool.ReturnBuffer(packetHeader);
            }

            int writePos = Defines.MAX_PACKET_HEADER_BYTES + fragmentID * fragmentSize;
            int end      = writePos + fragmentBytes;

            if (this.PacketDataBuffer.Length < end)
            {
                this.PacketDataBuffer.SetSize(end);
            }

            if (fragmentID == NumFragmentsTotal - 1)
            {
                this.PacketBytes = (this.NumFragmentsTotal - 1) * fragmentSize + fragmentBytes;
            }

            this.PacketDataBuffer.BufferCopy(fragmentData, copyOffset, Defines.MAX_PACKET_HEADER_BYTES + fragmentID * fragmentSize, fragmentBytes);
        }
        protected void processSendBuffer()
        {
            int    num  = 0;
            ushort num2 = oldestUnacked;

            while (PacketIO.SequenceLessThan(num2, sequence))
            {
                num++;
                num2 = (ushort)(num2 + 1);
            }
            ushort num3 = oldestUnacked;

            while (PacketIO.SequenceLessThan(num3, sequence) && num3 < oldestUnacked + 256)
            {
                BufferedPacket bufferedPacket = sendBuffer.Find(num3);
                if (bufferedPacket != null && !bufferedPacket.writeLock && !(time - bufferedPacket.time < 0.1))
                {
                    bool flag = false;
                    if (!((bufferedPacket.buffer.Length >= config.FragmentThreshold) ? (messagePacker.Length + bufferedPacket.buffer.Length <= config.MaxPacketSize - 6 - 10) : (messagePacker.Length + bufferedPacket.buffer.Length <= config.FragmentThreshold - 10)))
                    {
                        flushMessagePacker();
                    }
                    bufferedPacket.time = time;
                    int length = messagePacker.Length;
                    messagePacker.SetSize(messagePacker.Length + bufferedPacket.buffer.Length);
                    messagePacker.BufferCopy(bufferedPacket.buffer, 0, length, bufferedPacket.buffer.Length);
                    tempList.Add(num3);
                    lastMessageSend = time;
                }
                num3 = (ushort)(num3 + 1);
            }
            if (time - lastMessageSend >= 0.1)
            {
                sendAckPacket();
                lastMessageSend = time;
            }
            flushMessagePacker();
        }
Exemplo n.º 4
0
        public bool Read(byte[] token, ulong sequenceNum, byte[] key)
        {
            byte[] tokenBuffer = BufferPool.GetBuffer(300);
            int    tokenLen    = 0;

            try
            {
                tokenLen = PacketIO.DecryptChallengeToken(sequenceNum, token, key, tokenBuffer);
            }
            catch
            {
                BufferPool.ReturnBuffer(tokenBuffer);
                return(false);
            }

            using (var reader = ByteArrayReaderWriter.Get(tokenBuffer))
            {
                ClientID = reader.ReadUInt64();
                UserData = reader.ReadBytes(256);
            }

            return(true);
        }
Exemplo n.º 5
0
        static void StartServer(Config cfg)
        {
            TcpListener listener = new TcpListener(System.Net.IPAddress.Any, cfg.port);

            listener.Start();
            int clients = 0;

            for (; ;)
            {
                Console.WriteLine("Waiting for new connection...");
                TcpClient client = listener.AcceptTcpClient(); // wait until a client appears

                Client connection = new Client();
                clientlist.Add(connection);

                connection.Start(client, clients++, BroadcastMsg);
                // Send MOTD
                foreach (string str in cfg.MOTD.Split('\n'))
                {
                    PacketIO.Send(connection.socket, new Message(Commands.System, str, "MOTD", 0));
                }
            }
        }
        public override void SendMessage(byte[] buffer, int bufferLength)
        {
            int    num  = 0;
            ushort num2 = oldestUnacked;

            while (PacketIO.SequenceLessThan(num2, sequence))
            {
                if (sendBuffer.Exists(num2))
                {
                    num++;
                }
                num2 = (ushort)(num2 + 1);
            }
            if (num == sendBuffer.Size)
            {
                ByteBuffer byteBuffer = ObjPool <ByteBuffer> .Get();

                byteBuffer.SetSize(bufferLength);
                byteBuffer.BufferCopy(buffer, 0, 0, bufferLength);
                messageQueue.Enqueue(byteBuffer);
            }
            else
            {
                ushort         val            = sequence++;
                BufferedPacket bufferedPacket = sendBuffer.Insert(val);
                bufferedPacket.time = -1.0;
                int variableLengthBytes = getVariableLengthBytes((ushort)bufferLength);
                bufferedPacket.buffer.SetSize(bufferLength + 2 + variableLengthBytes);
                using (ByteArrayReaderWriter byteArrayReaderWriter = ByteArrayReaderWriter.Get(bufferedPacket.buffer.InternalBuffer))
                {
                    byteArrayReaderWriter.Write(val);
                    writeVariableLengthUShort((ushort)bufferLength, byteArrayReaderWriter);
                    byteArrayReaderWriter.WriteBuffer(buffer, bufferLength);
                }
                bufferedPacket.writeLock = false;
            }
        }
        public void ReceivePacket(byte[] packetData, int bufferLength)
        {
            if (bufferLength > config.MaxPacketSize)
            {
                throw new ArgumentOutOfRangeException("Packet is larger than max packet size");
            }

            if (packetData == null)
            {
                throw new InvalidOperationException("Tried to receive null packet!");
            }

            if (bufferLength > packetData.Length)
            {
                throw new InvalidOperationException("Buffer length exceeds actual packet length!");
            }

            byte prefixByte = packetData[0];

            if ((prefixByte & 1) == 0)
            {
                // regular packet

                ushort sequence;
                ushort ack;
                uint   ackBits;

                byte channelID;
                bool compressed;

                int packetHeaderBytes = PacketIO.ReadPacketHeader(packetData, 0, bufferLength, out channelID, out sequence, out ack, out ackBits, out compressed);

                bool isStale;
                lock (receivedPackets)
                    isStale = !receivedPackets.TestInsert(sequence);

                if (!isStale && (prefixByte & 0x80) == 0)
                {
                    if (packetHeaderBytes >= bufferLength)
                    {
                        throw new FormatException($"Buffer too small for packet data! {packetHeaderBytes} packetHeaderBytes > {bufferLength} bufferLength");
                    }

                    ByteBuffer tempBuffer = ObjPool <ByteBuffer> .Get();

                    if (compressed)
                    {
                        var decompressedBytes = LZ4Codec.Unwrap(packetData, packetHeaderBytes);
                        tempBuffer.SetSize(decompressedBytes.Length);
                        tempBuffer.BufferCopy(decompressedBytes, 0, 0, decompressedBytes.Length);
                        bufferLength = decompressedBytes.Length + packetHeaderBytes;
                    }
                    else
                    {
                        tempBuffer.SetSize(bufferLength - packetHeaderBytes);
                        tempBuffer.BufferCopy(packetData, packetHeaderBytes, 0, tempBuffer.Length);
                    }

                    // process packet
                    config.ProcessPacketCallback(sequence, tempBuffer.InternalBuffer, tempBuffer.Length);

                    // add to received buffer
                    lock (receivedPackets) {
                        ReceivedPacketData receivedPacketData = receivedPackets.Insert(sequence);

                        if (receivedPacketData == null)
                        {
                            throw new InvalidOperationException("Failed to insert received packet!");
                        }

                        receivedPacketData.time        = this.time;
                        receivedPacketData.packetBytes = (uint)(bufferLength);
                    }

                    ObjPool <ByteBuffer> .Return(tempBuffer);
                }

                if (!isStale || (prefixByte & 0x80) != 0)
                {
                    for (int i = 0; i < 32; i++)
                    {
                        if ((ackBits & 1) != 0)
                        {
                            ushort         ack_sequence   = (ushort)(ack - i);
                            SentPacketData sentPacketData = sentPackets.Find(ack_sequence);

                            if (sentPacketData != null && !sentPacketData.acked)
                            {
                                sentPacketData.acked = true;

                                if (config.AckPacketCallback != null)
                                {
                                    config.AckPacketCallback(ack_sequence);
                                }

                                float rtt = (float)(this.time - sentPacketData.time) * 1000.0f;
                                if ((this.rtt == 0f && rtt > 0f) || Math.Abs(this.rtt - rtt) < 0.00001f)
                                {
                                    this.rtt = rtt;
                                }
                                else
                                {
                                    this.rtt += (rtt - this.rtt) * config.RTTSmoothFactor;
                                }
                            }
                        }

                        ackBits >>= 1;
                    }
                }
            }
            else
            {
                // fragment packet

                int fragmentID;
                int numFragments;
                int fragmentBytes;

                ushort sequence;
                ushort ack;
                uint   ackBits;

                byte fragmentChannelID;

                bool compressed;
                int  fragmentHeaderBytes = PacketIO.ReadFragmentHeader(packetData, 0, bufferLength, config.MaxFragments, config.FragmentSize,
                                                                       out fragmentID, out numFragments, out fragmentBytes, out sequence, out ack, out ackBits, out fragmentChannelID, out compressed);

                FragmentReassemblyData reassemblyData = fragmentReassembly.Find(sequence);
                if (reassemblyData == null)
                {
                    reassemblyData = fragmentReassembly.Insert(sequence);

                    // failed to insert into buffer (stale)
                    if (reassemblyData == null)
                    {
                        return;
                    }

                    reassemblyData.Sequence             = sequence;
                    reassemblyData.Ack                  = 0;
                    reassemblyData.AckBits              = 0;
                    reassemblyData.NumFragmentsReceived = 0;
                    reassemblyData.NumFragmentsTotal    = numFragments;
                    reassemblyData.PacketBytes          = 0;
                    reassemblyData.PacketDataBuffer.SetSize(0);
                    Array.Clear(reassemblyData.FragmentReceived, 0, reassemblyData.FragmentReceived.Length);
                }

                if (numFragments != reassemblyData.NumFragmentsTotal)
                {
                    return;
                }

                if (reassemblyData.FragmentReceived[fragmentID])
                {
                    return;
                }

                reassemblyData.NumFragmentsReceived++;
                reassemblyData.FragmentReceived[fragmentID] = true;

                byte[] tempFragmentData = BufferPool.GetBuffer(2048);
                Buffer.BlockCopy(packetData, fragmentHeaderBytes, tempFragmentData, 0, bufferLength - fragmentHeaderBytes);

                reassemblyData.StoreFragmentData(fragmentChannelID, sequence, ack, ackBits, fragmentID, config.FragmentSize, tempFragmentData, bufferLength - fragmentHeaderBytes, compressed);
                BufferPool.ReturnBuffer(tempFragmentData);

                if (reassemblyData.NumFragmentsReceived == reassemblyData.NumFragmentsTotal)
                {
                    // grab internal buffer and pass it to ReceivePacket. Internal buffer will be packet marked as normal packet, so it will go through normal packet path

                    // copy into new buffer to remove preceding offset (used to simplify variable length header handling)
                    ByteBuffer temp = ObjPool <ByteBuffer> .Get();

                    temp.SetSize(reassemblyData.PacketDataBuffer.Length - reassemblyData.HeaderOffset);
                    Buffer.BlockCopy(reassemblyData.PacketDataBuffer.InternalBuffer, reassemblyData.HeaderOffset, temp.InternalBuffer, 0, temp.Length);

                    // receive packet
                    this.ReceivePacket(temp.InternalBuffer, temp.Length);

                    // return temp buffer
                    ObjPool <ByteBuffer> .Return(temp);

                    // clear reassembly
                    reassemblyData.PacketDataBuffer.SetSize(0);
                    fragmentReassembly.Remove(sequence);
                }
            }
        }
        public ushort SendPacket(byte[] packetData, int position, int length, byte channelID)
        {
            if (length > config.MaxPacketSize)
            {
                throw new ArgumentOutOfRangeException("Packet is too large to send, max packet size is " + config.MaxPacketSize + " bytes");
            }

            if (length < 1)
            {
                throw new ArgumentOutOfRangeException("Packet is too small; minimum packet size is 1 byte.");
            }

            var  compressedBuffer = LZ4Codec.Wrap(packetData, position, length);
            bool compressed       = false;
            int  bytesSaved       = length - compressedBuffer.Length;

            if (bytesSaved > 0)
            {
                packetData = compressedBuffer;
                position   = 0;
                length     = compressedBuffer.Length;
                compressed = true;
            }

            ushort sequence = this.sequence++;
            ushort ack;
            uint   ackBits;

            lock (receivedPackets)
                receivedPackets.GenerateAckBits(out ack, out ackBits);

            SentPacketData sentPacketData = sentPackets.Insert(sequence);

            sentPacketData.time        = this.time;
            sentPacketData.packetBytes = (uint)(config.PacketHeaderSize + length);
            sentPacketData.acked       = false;

            if (length <= config.FragmentThreshold)
            {
                // regular packet

                byte[] transmitData         = BufferPool.GetBuffer(2048);
                int    headerBytes          = PacketIO.WritePacketHeader(transmitData, channelID, sequence, ack, ackBits, compressed);
                int    transmitBufferLength = length + headerBytes;

                Buffer.BlockCopy(packetData, position, transmitData, headerBytes, length);

                config.TransmitPacketCallback(transmitData, transmitBufferLength);

                BufferPool.ReturnBuffer(transmitData);
            }
            else
            {
                // fragmented packet

                byte[] packetHeader = BufferPool.GetBuffer(Defines.MAX_PACKET_HEADER_BYTES);

                int packetHeaderBytes = 0;

                try {
                    packetHeaderBytes = PacketIO.WritePacketHeader(packetHeader, channelID, sequence, ack, ackBits, compressed);
                }
                catch {
                    throw;
                }

                int numFragments = (length / config.FragmentSize) + ((length % config.FragmentSize) != 0 ? 1 : 0);
                //int fragmentBufferSize = Defines.FRAGMENT_HEADER_BYTES + Defines.MAX_PACKET_HEADER_BYTES + config.FragmentSize;

                byte[] fragmentPacketData = BufferPool.GetBuffer(2048);
                int    qpos = 0;

                byte prefixByte = 1;
                prefixByte |= (byte)((channelID & 0x03) << 6);

                for (int fragmentID = 0; fragmentID < numFragments; fragmentID++)
                {
                    using (var writer = ByteArrayReaderWriter.Get(fragmentPacketData)) {
                        writer.Write(prefixByte);
                        writer.Write(channelID);
                        writer.Write(sequence);
                        writer.Write((byte)fragmentID);
                        writer.Write((byte)(numFragments - 1));
                        writer.Write(compressed ? (byte)1 : (byte)0);

                        if (fragmentID == 0)
                        {
                            writer.WriteBuffer(packetHeader, 0, packetHeaderBytes);
                        }

                        int bytesToCopy = config.FragmentSize;
                        if (qpos + bytesToCopy > length)
                        {
                            bytesToCopy = length - qpos;
                        }

                        for (int i = 0; i < bytesToCopy; i++)
                        {
                            writer.Write(packetData[position + qpos++]);
                        }

                        int fragmentPacketBytes = (int)writer.WritePosition;
                        config.TransmitPacketCallback(fragmentPacketData, fragmentPacketBytes);
                    }
                }

                BufferPool.ReturnBuffer(packetHeader);
                BufferPool.ReturnBuffer(fragmentPacketData);
            }

            return(sequence);
        }
Exemplo n.º 9
0
        public void ReceivePacket(byte[] packetData, int bufferLength)
        {
            if (bufferLength > config.MaxPacketSize)
            {
                throw new ArgumentOutOfRangeException("Packet is larger than max packet size");
            }
            if (packetData == null)
            {
                throw new InvalidOperationException("Tried to receive null packet!");
            }
            if (bufferLength > packetData.Length)
            {
                throw new InvalidOperationException("Buffer length exceeds actual packet length!");
            }
            byte b = packetData[0];

            if ((b & 1) == 0)
            {
                byte   channelID;
                ushort arg;
                ushort ack;
                uint   ackBits;
                int    num = PacketIO.ReadPacketHeader(packetData, 0, bufferLength, out channelID, out arg, out ack, out ackBits);
                bool   flag;
                lock (receivedPackets)
                {
                    flag = !receivedPackets.TestInsert(arg);
                }
                if (!flag && (b & 0x80) == 0)
                {
                    if (num >= bufferLength)
                    {
                        throw new FormatException("Buffer too small for packet data!");
                    }
                    ByteBuffer byteBuffer = ObjPool <ByteBuffer> .Get();

                    byteBuffer.SetSize(bufferLength - num);
                    byteBuffer.BufferCopy(packetData, num, 0, byteBuffer.Length);
                    config.ProcessPacketCallback(arg, byteBuffer.InternalBuffer, byteBuffer.Length);
                    lock (receivedPackets)
                    {
                        ReceivedPacketData receivedPacketData = receivedPackets.Insert(arg);
                        if (receivedPacketData == null)
                        {
                            throw new InvalidOperationException("Failed to insert received packet!");
                        }
                        receivedPacketData.time        = time;
                        receivedPacketData.packetBytes = (uint)(config.PacketHeaderSize + bufferLength);
                    }
                    ObjPool <ByteBuffer> .Return(byteBuffer);
                }
                if (flag && (b & 0x80) == 0)
                {
                    return;
                }
                for (int i = 0; i < 32; i++)
                {
                    if ((ackBits & 1) != 0)
                    {
                        ushort         obj            = (ushort)(ack - i);
                        SentPacketData sentPacketData = sentPackets.Find(obj);
                        if (sentPacketData != null && !sentPacketData.acked)
                        {
                            sentPacketData.acked = true;
                            if (config.AckPacketCallback != null)
                            {
                                config.AckPacketCallback(obj);
                            }
                            float num2 = (float)(time - sentPacketData.time) * 1000f;
                            if ((rtt == 0f && num2 > 0f) || Math.Abs(rtt - num2) < 1E-05f)
                            {
                                rtt = num2;
                            }
                            else
                            {
                                rtt += (num2 - rtt) * config.RTTSmoothFactor;
                            }
                        }
                    }
                    ackBits >>= 1;
                }
                return;
            }
            int    fragmentID;
            int    numFragments;
            int    fragmentBytes;
            ushort num3;
            ushort ack2;
            uint   ackBits2;
            byte   channelID2;
            int    num4 = PacketIO.ReadFragmentHeader(packetData, 0, bufferLength, config.MaxFragments, config.FragmentSize, out fragmentID, out numFragments, out fragmentBytes, out num3, out ack2, out ackBits2, out channelID2);
            FragmentReassemblyData fragmentReassemblyData = fragmentReassembly.Find(num3);

            if (fragmentReassemblyData == null)
            {
                fragmentReassemblyData = fragmentReassembly.Insert(num3);
                if (fragmentReassemblyData == null)
                {
                    return;
                }
                fragmentReassemblyData.Sequence             = num3;
                fragmentReassemblyData.Ack                  = 0;
                fragmentReassemblyData.AckBits              = 0u;
                fragmentReassemblyData.NumFragmentsReceived = 0;
                fragmentReassemblyData.NumFragmentsTotal    = numFragments;
                fragmentReassemblyData.PacketBytes          = 0;
                Array.Clear(fragmentReassemblyData.FragmentReceived, 0, fragmentReassemblyData.FragmentReceived.Length);
            }
            if (numFragments == fragmentReassemblyData.NumFragmentsTotal && !fragmentReassemblyData.FragmentReceived[fragmentID])
            {
                fragmentReassemblyData.NumFragmentsReceived++;
                fragmentReassemblyData.FragmentReceived[fragmentID] = true;
                byte[] buffer = BufferPool.GetBuffer(2048);
                Buffer.BlockCopy(packetData, num4, buffer, 0, bufferLength - num4);
                fragmentReassemblyData.StoreFragmentData(channelID2, num3, ack2, ackBits2, fragmentID, config.FragmentSize, buffer, bufferLength - num4);
                BufferPool.ReturnBuffer(buffer);
                if (fragmentReassemblyData.NumFragmentsReceived == fragmentReassemblyData.NumFragmentsTotal)
                {
                    ByteBuffer byteBuffer2 = ObjPool <ByteBuffer> .Get();

                    byteBuffer2.SetSize(fragmentReassemblyData.PacketDataBuffer.Length - fragmentReassemblyData.HeaderOffset);
                    Buffer.BlockCopy(fragmentReassemblyData.PacketDataBuffer.InternalBuffer, fragmentReassemblyData.HeaderOffset, byteBuffer2.InternalBuffer, 0, byteBuffer2.Length);
                    ReceivePacket(byteBuffer2.InternalBuffer, byteBuffer2.Length);
                    ObjPool <ByteBuffer> .Return(byteBuffer2);

                    fragmentReassemblyData.PacketDataBuffer.SetSize(0);
                    fragmentReassembly.Remove(num3);
                }
            }
        }
Exemplo n.º 10
0
        public ushort SendPacket(byte[] packetData, int length, byte channelID)
        {
            if (length > config.MaxPacketSize)
            {
                throw new ArgumentOutOfRangeException("Packet is too large to send, max packet size is " + config.MaxPacketSize + " bytes");
            }
            ushort num = sequence++;
            ushort ack;
            uint   ackBits;

            lock (receivedPackets)
            {
                receivedPackets.GenerateAckBits(out ack, out ackBits);
            }
            SentPacketData sentPacketData = sentPackets.Insert(num);

            sentPacketData.time        = time;
            sentPacketData.packetBytes = (uint)(config.PacketHeaderSize + length);
            sentPacketData.acked       = false;
            if (length <= config.FragmentThreshold)
            {
                byte[] buffer = BufferPool.GetBuffer(2048);
                int    num2   = PacketIO.WritePacketHeader(buffer, channelID, num, ack, ackBits);
                int    arg    = length + num2;
                Buffer.BlockCopy(packetData, 0, buffer, num2, length);
                config.TransmitPacketCallback(buffer, arg);
                BufferPool.ReturnBuffer(buffer);
            }
            else
            {
                byte[] buffer2 = BufferPool.GetBuffer(10);
                int    num3    = 0;
                try
                {
                    num3 = PacketIO.WritePacketHeader(buffer2, channelID, num, ack, ackBits);
                }
                catch
                {
                    throw;
                }
                int    num4    = length / config.FragmentSize + ((length % config.FragmentSize != 0) ? 1 : 0);
                byte[] buffer3 = BufferPool.GetBuffer(2048);
                int    num5    = 0;
                byte   b       = 1;
                b = (byte)(b | (byte)((channelID & 3) << 6));
                for (int i = 0; i < num4; i++)
                {
                    using (ByteArrayReaderWriter byteArrayReaderWriter = ByteArrayReaderWriter.Get(buffer3))
                    {
                        byteArrayReaderWriter.Write(b);
                        byteArrayReaderWriter.Write(channelID);
                        byteArrayReaderWriter.Write(num);
                        byteArrayReaderWriter.Write((byte)i);
                        byteArrayReaderWriter.Write((byte)(num4 - 1));
                        if (i == 0)
                        {
                            byteArrayReaderWriter.WriteBuffer(buffer2, num3);
                        }
                        int num6 = config.FragmentSize;
                        if (num5 + num6 > length)
                        {
                            num6 = length - num5;
                        }
                        for (int j = 0; j < num6; j++)
                        {
                            byteArrayReaderWriter.Write(packetData[num5++]);
                        }
                        int arg2 = (int)byteArrayReaderWriter.WritePosition;
                        config.TransmitPacketCallback(buffer3, arg2);
                    }
                }
                BufferPool.ReturnBuffer(buffer2);
                BufferPool.ReturnBuffer(buffer3);
            }
            return(num);
        }
        public void ReceivePacket(byte[] packetData, int bufferLength)
        {
            if (bufferLength > config.MaxPacketSize)
            {
                throw new ArgumentOutOfRangeException("Packet is larger than max packet size");
            }

            byte prefixByte = packetData[0];

            if ((prefixByte & 1) == 0)
            {
                // regular packet

                ushort sequence;
                ushort ack;
                uint   ackBits;

                byte channelID;

                int  packetHeaderBytes = PacketIO.ReadPacketHeader(packetData, 0, bufferLength, out channelID, out sequence, out ack, out ackBits);
                bool isStale           = !receivedPackets.TestInsert(sequence);

                if (!isStale && (prefixByte & 0x80) == 0)
                {
                    ByteBuffer tempBuffer = ObjPool <ByteBuffer> .Get();

                    tempBuffer.SetSize(bufferLength - packetHeaderBytes);
                    tempBuffer.BufferCopy(packetData, packetHeaderBytes, 0, tempBuffer.Length);

                    // process packet
                    config.ProcessPacketCallback(sequence, tempBuffer.InternalBuffer, tempBuffer.Length);

                    // add to received buffer
                    ReceivedPacketData receivedPacketData = receivedPackets.Insert(sequence);
                    receivedPacketData.time        = this.time;
                    receivedPacketData.packetBytes = (uint)(config.PacketHeaderSize + bufferLength);

                    ObjPool <ByteBuffer> .Return(tempBuffer);
                }

                if (!isStale || (prefixByte & 0x80) != 0)
                {
                    for (int i = 0; i < 32; i++)
                    {
                        if ((ackBits & 1) != 0)
                        {
                            ushort         ack_sequence   = (ushort)(ack - i);
                            SentPacketData sentPacketData = sentPackets.Find(ack_sequence);

                            if (sentPacketData != null && !sentPacketData.acked)
                            {
                                sentPacketData.acked = true;

                                if (config.AckPacketCallback != null)
                                {
                                    config.AckPacketCallback(ack_sequence);
                                }

                                float rtt = (float)(this.time - sentPacketData.time) * 1000.0f;
                                if ((this.rtt == 0f && rtt > 0f) || Math.Abs(this.rtt - rtt) < 0.00001f)
                                {
                                    this.rtt = rtt;
                                }
                                else
                                {
                                    this.rtt += (rtt - this.rtt) * config.RTTSmoothFactor;
                                }
                            }
                        }

                        ackBits >>= 1;
                    }
                }
            }
            else
            {
                // fragment packet

                int fragmentID;
                int numFragments;
                int fragmentBytes;

                ushort sequence;
                ushort ack;
                uint   ackBits;

                byte fragmentChannelID;

                int fragmentHeaderBytes = PacketIO.ReadFragmentHeader(packetData, 0, bufferLength, config.MaxFragments, config.FragmentSize,
                                                                      out fragmentID, out numFragments, out fragmentBytes, out sequence, out ack, out ackBits, out fragmentChannelID);

                FragmentReassemblyData reassemblyData = fragmentReassembly.Find(sequence);
                if (reassemblyData == null)
                {
                    reassemblyData = fragmentReassembly.Insert(sequence);

                    // failed to insert into buffer (stale)
                    if (reassemblyData == null)
                    {
                        return;
                    }

                    reassemblyData.Sequence             = sequence;
                    reassemblyData.Ack                  = 0;
                    reassemblyData.AckBits              = 0;
                    reassemblyData.NumFragmentsReceived = 0;
                    reassemblyData.NumFragmentsTotal    = numFragments;
                    reassemblyData.PacketBytes          = 0;
                    Array.Clear(reassemblyData.FragmentReceived, 0, reassemblyData.FragmentReceived.Length);
                }

                if (numFragments != reassemblyData.NumFragmentsTotal)
                {
                    return;
                }

                if (reassemblyData.FragmentReceived[fragmentID])
                {
                    return;
                }

                reassemblyData.NumFragmentsReceived++;
                reassemblyData.FragmentReceived[fragmentID] = true;

                byte[] tempFragmentData = BufferPool.GetBuffer(2048);
                Buffer.BlockCopy(packetData, fragmentHeaderBytes, tempFragmentData, 0, bufferLength - fragmentHeaderBytes);
                reassemblyData.StoreFragmentData(fragmentChannelID, sequence, ack, ackBits, fragmentID, config.FragmentSize, tempFragmentData, bufferLength - fragmentHeaderBytes);
                BufferPool.ReturnBuffer(tempFragmentData);

                if (reassemblyData.NumFragmentsReceived == reassemblyData.NumFragmentsTotal)
                {
                    // grab internal buffer and pass it to ReceivePacket. Internal buffer will be packet marked as normal packet, so it will go through normal packet path
                    this.ReceivePacket(reassemblyData.PacketDataBuffer.InternalBuffer, reassemblyData.PacketDataBuffer.Length);
                    reassemblyData.PacketDataBuffer.SetSize(0);
                    fragmentReassembly.Remove(sequence);
                }
            }
        }
 public bool TestInsert(ushort sequence)
 {
     return(!PacketIO.SequenceLessThan(sequence, (ushort)(this.sequence - numEntries)));
 }
Exemplo n.º 13
0
        //Queue<string> _sendQueue = new Queue<string>();

        public Connection(TcpClient client)
        {
            _packetIO = new PacketIO(client.GetStream());
            _client   = client;
        }
Exemplo n.º 14
0
        /// <summary>
        /// Osc Constructor.  Starts the Reader thread and initializes some internal state.
        /// </summary>
        /// <param name="oscPacketIO">The PacketIO instance used for packet IO.</param>
        public Osc(PacketIO oscPacketIO)
        {
            // Save the PacketExchage pointer
              OscPacketIO = oscPacketIO;

              // Create the hashtable for the address lookup mechanism
              AddressTable = new Hashtable();

              ReadThread = new Thread(Read);
              ReaderRunning = true;
              ReadThread.IsBackground = true;
              ReadThread.Start();
        }
        protected void processSendBuffer()
        {
            int numUnacked = 0;

            for (ushort seq = oldestUnacked; PacketIO.SequenceLessThan(seq, this.sequence); seq++)
            {
                numUnacked++;
            }

            for (ushort seq = oldestUnacked; PacketIO.SequenceLessThan(seq, this.sequence); seq++)
            {
                // never send message ID >= ( oldestUnacked + bufferSize )
                if (seq >= (oldestUnacked + 256))
                {
                    break;
                }

                // for any message that hasn't been sent in the last 0.1 seconds and fits in the available space of our message packer, add it
                var packet = sendBuffer.Find(seq);
                if (packet != null && !packet.writeLock)
                {
                    if (time - packet.time < 0.1)
                    {
                        continue;
                    }

                    bool packetFits = false;

                    if (packet.buffer.Length < config.FragmentThreshold)
                    {
                        packetFits = (messagePacker.Length + packet.buffer.Length) <= (config.FragmentThreshold - Defines.MAX_PACKET_HEADER_BYTES);
                    }
                    else
                    {
                        packetFits = (messagePacker.Length + packet.buffer.Length) <= (config.MaxPacketSize - Defines.FRAGMENT_HEADER_BYTES - Defines.MAX_PACKET_HEADER_BYTES);
                    }

                    // if the packet won't fit, flush the message packer
                    if (!packetFits)
                    {
                        flushMessagePacker();
                    }

                    packet.time = time;

                    int ptr = messagePacker.Length;
                    messagePacker.SetSize(messagePacker.Length + packet.buffer.Length);
                    messagePacker.BufferCopy(packet.buffer, 0, ptr, packet.buffer.Length);

                    tempList.Add(seq);

                    lastMessageSend = time;
                }
            }

            // if it has been 0.1 seconds since the last time we sent a message, send an empty message
            if (time - lastMessageSend >= 0.1)
            {
                sendAckPacket();
                lastMessageSend = time;
            }

            // flush any remaining messages in message packer
            flushMessagePacker();
        }
Exemplo n.º 16
0
        internal byte[] GenerateConnectToken(IPEndPoint[] addressList, double time, int expirySeconds, int serverTimeout, ulong sequence, ulong clientID, byte[] userData)
        {
            if (userData.Length > 256)
            {
                throw new ArgumentOutOfRangeException("User data cannot be larger than 256 bytes");
            }

            if (addressList == null)
            {
                throw new NullReferenceException("Address list cannot be null");
            }
            else if (addressList.Length == 0)
            {
                throw new ArgumentOutOfRangeException("Address list cannot be empty");
            }
            else if (addressList.Length > Defines.MAX_SERVER_ADDRESSES)
            {
                throw new ArgumentOutOfRangeException("Address list cannot contain more than " + Defines.MAX_SERVER_ADDRESSES + " entries");
            }

            NetcodePrivateConnectToken privateConnectToken = new NetcodePrivateConnectToken();

            privateConnectToken.ClientID       = clientID;
            privateConnectToken.TimeoutSeconds = serverTimeout;

            // generate random crypto keys
            byte[] clientToServerKey = new byte[32];
            byte[] serverToClientKey = new byte[32];
            KeyUtils.GenerateKey(clientToServerKey);
            KeyUtils.GenerateKey(serverToClientKey);

            privateConnectToken.ClientToServerKey = clientToServerKey;
            privateConnectToken.ServerToClientKey = serverToClientKey;
            privateConnectToken.UserData          = new byte[256];

            Buffer.BlockCopy(userData, 0, privateConnectToken.UserData, 0, userData.Length);

            privateConnectToken.ConnectServers = new ConnectTokenServerEntry[addressList.Length];
            for (int i = 0; i < privateConnectToken.ConnectServers.Length; i++)
            {
                privateConnectToken.ConnectServers[i] = new ConnectTokenServerEntry()
                {
                    AddressType = addressList[i].AddressFamily == AddressFamily.InterNetwork ? NetcodeAddressType.IPv4 : NetcodeAddressType.IPv6,
                    Endpoint    = addressList[i]
                };
            }

            byte[] privateConnectTokenBytes = new byte[1024];
            using (var writer = ByteArrayReaderWriter.Get(privateConnectTokenBytes))
            {
                privateConnectToken.Write(writer);
            }

            ulong createTimestamp = (ulong)Math.Truncate(time);
            ulong expireTimestamp = expirySeconds >= 0 ? (createTimestamp + (ulong)expirySeconds) : 0xFFFFFFFFFFFFFFFFUL;

            byte[] encryptedPrivateToken = new byte[1024];
            PacketIO.EncryptPrivateConnectToken(privateConnectTokenBytes, protocolID, expireTimestamp, sequence, privateKey, encryptedPrivateToken);

            NetcodePublicConnectToken publicToken = new NetcodePublicConnectToken();

            publicToken.ProtocolID               = protocolID;
            publicToken.CreateTimestamp          = createTimestamp;
            publicToken.ExpireTimestamp          = expireTimestamp;
            publicToken.ConnectTokenSequence     = sequence;
            publicToken.PrivateConnectTokenBytes = encryptedPrivateToken;
            publicToken.ConnectServers           = privateConnectToken.ConnectServers;
            publicToken.ClientToServerKey        = clientToServerKey;
            publicToken.ServerToClientKey        = serverToClientKey;
            publicToken.TimeoutSeconds           = serverTimeout;

            byte[] publicTokenBytes = new byte[2048];
            using (var writer = ByteArrayReaderWriter.Get(publicTokenBytes))
            {
                publicToken.Write(writer);
            }

            return(publicTokenBytes);
        }
        public override void Update(double newTime)
        {
            double dt = newTime - time;

            time = newTime;
            this.packetController.Update(time);

            // see if we can pop messages off of the message queue and put them on the send queue
            if (messageQueue.Count > 0)
            {
                int sendBufferSize = 0;
                for (ushort seq = oldestUnacked; PacketIO.SequenceLessThan(seq, this.sequence); seq++)
                {
                    if (sendBuffer.Exists(seq))
                    {
                        sendBufferSize++;
                    }
                }

                if (sendBufferSize < sendBuffer.Size)
                {
                    var message = messageQueue.Dequeue();
                    SendMessage(message.InternalBuffer, 0, message.Length);
                    ObjPool <ByteBuffer> .Return(message);
                }
            }

            // update congestion mode
            {
                // conditions are bad if round-trip-time exceeds 250ms
                bool conditionsBad = (this.packetController.RTT >= 250f);

                // if conditions are bad, immediately enable congestion control and reset the congestion timer
                if (conditionsBad)
                {
                    if (this.congestionControl == false)
                    {
                        // if we're within 10 seconds of the last time we switched, double the threshold interval
                        if (time - lastCongestionSwitchTime < 10.0)
                        {
                            congestionDisableInterval = Math.Min(congestionDisableInterval * 2, 60.0);
                        }

                        lastCongestionSwitchTime = time;
                    }

                    this.congestionControl      = true;
                    this.congestionDisableTimer = 0.0;
                }

                // if we're in bad mode, and conditions are good, update the timer and see if we can disable congestion control
                if (this.congestionControl && !conditionsBad)
                {
                    this.congestionDisableTimer += dt;
                    if (this.congestionDisableTimer >= this.congestionDisableInterval)
                    {
                        this.congestionControl   = false;
                        lastCongestionSwitchTime = time;
                        congestionDisableTimer   = 0.0;
                    }
                }

                // as long as conditions are good, halve the threshold interval every 10 seconds
                if (this.congestionControl == false)
                {
                    congestionDisableTimer += dt;
                    if (congestionDisableTimer >= 10.0)
                    {
                        congestionDisableInterval = Math.Max(congestionDisableInterval * 0.5, 5.0);
                    }
                }
            }

            // if we're in congestion control mode, only send packets 10 times per second.
            // otherwise, send 30 times per second
            double flushInterval = congestionControl ? 0.1 : 0.033;

            if (time - lastBufferFlush >= flushInterval)
            {
                lastBufferFlush = time;
                processSendBuffer();
            }
        }
        public override void Update(double newTime)
        {
            double num = newTime - time;

            time = newTime;
            packetController.Update(time);
            if (messageQueue.Count > 0)
            {
                int    num2 = 0;
                ushort num3 = oldestUnacked;
                while (PacketIO.SequenceLessThan(num3, sequence))
                {
                    if (sendBuffer.Exists(num3))
                    {
                        num2++;
                    }
                    num3 = (ushort)(num3 + 1);
                }
                if (num2 < sendBuffer.Size)
                {
                    ByteBuffer byteBuffer = messageQueue.Dequeue();
                    SendMessage(byteBuffer.InternalBuffer, byteBuffer.Length);
                    ObjPool <ByteBuffer> .Return(byteBuffer);
                }
            }
            bool flag = packetController.RTT >= 250f;

            if (flag)
            {
                if (!congestionControl)
                {
                    if (time - lastCongestionSwitchTime < 10.0)
                    {
                        congestionDisableInterval = Math.Min(congestionDisableInterval * 2.0, 60.0);
                    }
                    lastCongestionSwitchTime = time;
                }
                congestionControl      = true;
                congestionDisableTimer = 0.0;
            }
            if (congestionControl && !flag)
            {
                congestionDisableTimer += num;
                if (congestionDisableTimer >= congestionDisableInterval)
                {
                    congestionControl        = false;
                    lastCongestionSwitchTime = time;
                    congestionDisableTimer   = 0.0;
                }
            }
            if (!congestionControl)
            {
                congestionDisableTimer += num;
                if (congestionDisableTimer >= 10.0)
                {
                    congestionDisableInterval = Math.Max(congestionDisableInterval * 0.5, 5.0);
                }
            }
            double num4 = (!congestionControl) ? 0.033 : 0.1;

            if (time - lastBufferFlush >= num4)
            {
                lastBufferFlush = time;
                processSendBuffer();
            }
        }