elitepvpers

elitepvpers (https://www.elitepvpers.com/forum/)
-   CO2 Programming (https://www.elitepvpers.com/forum/co2-programming/)
-   -   Packetbuilder (https://www.elitepvpers.com/forum/co2-programming/1496302-packetbuilder.html)

Arco. 10/18/2011 21:21

Packetbuilder
 
I have a simple packetbuilder right now, but is there any way that this can be optimized for efficiency?
Spoiler:
Code:

class PacketBuilder
    {
        private byte[] buffer;

        public PacketBuilder(byte[] Buffer)
        {
            buffer = Buffer;
        }
        public void ZeroFill(byte[] Buffer, ushort Offset, ushort Count)
        {
            for (ushort i = 0; i < Count; i++)
                Buffer[i + Offset] = 0x00;
        }
        public void WriteStringWithLength(string Arg, ushort Offset)
        {
            buffer[Offset] = (byte)Arg.Length;
            Offset++;
            ushort i = 0;
            while (i < Arg.Length)
            {
                buffer[(ushort)(i + Offset)] = (byte)Arg[i];
                i = (ushort)(i + 1);
            }
        }
        public void WriteString(string Arg, ushort Offset)
        {
            ushort i = 0;
            while (i < Arg.Length)
            {
                buffer[(ushort)(i + Offset)] = (byte)Arg[i];
                i = (ushort)(i + 1);
            }
        }
        public void WriteUshort(ushort Arg, ushort Offset)
        {
            buffer[Offset] = (byte)(Arg);
            buffer[Offset + 1] = (byte)(Arg >> 8);
        }
        public void WriteUInt(uint Arg, ushort Offset)
        {
            buffer[Offset] = (byte)(Arg);
            buffer[Offset + 1] = (byte)(Arg >> 8);
            buffer[Offset + 2] = (byte)(Arg >> 16);
            buffer[Offset + 3] = (byte)(Arg >> 24);
        }
        public void WriteUlong(ulong Arg, ushort Offset)
        {
            buffer[Offset] = (byte)(Arg);
            buffer[Offset + 1] = (byte)(Arg >> 8);
            buffer[Offset + 2] = (byte)(Arg >> 16);
            buffer[Offset + 3] = (byte)(Arg >> 24);
            buffer[Offset + 4] = (byte)(Arg >> 32);
            buffer[Offset + 5] = (byte)(Arg >> 40);
            buffer[Offset + 6] = (byte)(Arg >> 48);
            buffer[Offset + 7] = (byte)(Arg >> 56);
        }
    }


BaussHacker 10/18/2011 21:43

Why you making Offset ushort? Just make it an int instead from ushort -> int, because index of an array is int.

buffer[int], even it doesn't say anything, it still uses time converting from ushort to int. I could be wrong, but it's how I look at it.

And this:
Code:

        public void WriteStringWithLength(string Arg, ushort Offset)
        {
            buffer[Offset] = (byte)Arg.Length;
            Offset++;
            ushort i = 0;
            while (i < Arg.Length)
            {
                buffer[(ushort)(i + Offset)] = (byte)Arg[i];
                i = (ushort)(i + 1);
            }
        }

Just use a for loop.
Code:

        public void WriteStringWithLength(string Arg, ushort Offset)
        {
            buffer[Offset] = (byte)Arg.Length;
            for (int i = 1; i < Arg.Length; i++)
                buffer[(ushort)(i + Offset)] = (byte)Arg[i];
        }

Same goes for:
Code:

public void WriteString(string Arg, ushort Offset)
        {
            ushort i = 0;
            while (i < Arg.Length)
            {
                buffer[(ushort)(i + Offset)] = (byte)Arg[i];
                i = (ushort)(i + 1);
            }
        }

Code:


        public void WriteString(string Arg, ushort Offset)
        {
            for (int i = 0; i < Arg.Length; i++)
                buffer[(ushort)(i + Offset)] = (byte)Arg[i];
        }

Can't really see much more, not even sure if it will do lot difference.

Arco. 10/18/2011 22:46

Thanks beautiful.

pro4never 10/18/2011 23:30

Few things..

Pointers. I don't see much reason not to use them here
Structs. Maybe its just me who's fond if it but I'd rather just use a memory structure that's organized the same as my packet then marshal it to send.

IAmHawtness 10/18/2011 23:35

Quote:

Originally Posted by pro4never (Post 13423344)
Few things..

Pointers. I don't see much reason not to use them here
Structs. Maybe its just me who's fond if it but I'd rather just use a memory structure that's organized the same as my packet then marshal it to send.

I agree with the pointers part, unsafe code would optimize this code a lot. All these bitwise shifts are pretty CPU intensive (as in they require a lot more cycles) compared to using pointers.

I've never been a fan of using structs though, mainly because I'm often too lazy to completely structure a packet

Korvacs 10/19/2011 00:13

Pointers, a way to write a byte to the buffer would come in handy aswell, i assume you forgot about that..

Arco. 10/19/2011 01:55

So how do all of you write/structure packets?

Korvacs 10/19/2011 02:03

Packet class with buffer and pointer, then a series of methods to write to the buffer using the pointer etc.

Arco. 10/19/2011 02:21

Sorta long the lines of this?
Code:

        public static void WriteUInt32(uint arg, int offset, byte[] buffer)
        {
            unsafe
            {
                fixed (byte* Buffer = buffer)
                {
                    *((uint*)(Buffer + offset)) = arg;
                }
            }
        }

Alright in case that's what you mean by it, this is what I recoded my packetbuilder to.

Spoiler:
Code:

public class Writer
{
    byte[] buffer;

    public Writer(byte[] BUFFER)
    {
        buffer = BUFFER;
    }
    public void WriteStringWithLength(string arg, int offset)
    {
        buffer[offset] = (byte)arg.Length;
        offset++;
        ushort i = 0;
        while (i < arg.Length)
        {
            buffer[(ushort)(i + offset)] = (byte)arg[i];
            i = (ushort)(i + 1);
        }
    }
    public void WriteString(string arg, int offset )
    {
        if (buffer.Length >= offset + arg.Length)
        {
            unsafe
            {
                fixed (byte* Buffer = buffer)
                {
                    ushort i = 0;
                    while (i < arg.Length)
                    {
                        *((byte*)(Buffer + offset + i)) = (byte)arg[i];
                        i++;
                    }
                }
            }
        }
    }
    public void WriteByte(byte arg, int offset )
    {
        buffer[offset] = (byte)(arg);
    }
    public void WriteUInt16(ushort arg, int offset )
    {
        if (buffer.Length >= offset + sizeof(ushort))
        {
            unsafe
            {
                fixed (byte* Buffer = buffer)
                    *((ushort*)(Buffer + offset)) = arg;
            }
        }
    }
    public void WriteUInt32(uint arg, int offset )
    {
        if (buffer.Length >= offset + sizeof(uint))
        {
            unsafe
            {
                fixed (byte* Buffer = buffer)
                    *((uint*)(Buffer + offset)) = arg;

            }
        }
    }
    public void WriteUInt64(ulong arg, int offset )
    {
        if (buffer.Length >= offset + sizeof(ulong))
        {
            unsafe
            {
                fixed (byte* Buffer = buffer)
                    *((ulong*)(Buffer + offset)) = arg;

            }
        }
    }
    public void WriteStringList(List<string> arg, int offset )
    {

        buffer[offset] = (byte)arg.Count;
        offset++;
        foreach (string str in arg)
        {
            buffer[offset] = (byte)str.Length;
            WriteString(str, offset + 1);
            offset += str.Length + 1;
        }
    }
}


pro4never 10/19/2011 03:38

I'd strongly recommend looking into tq's net string packer...

It's sexy as hell imo. You can reverse it from the eudemons binary leaked source. It's what we use in my source instead of a method like your WriteStringList method there.

Korvacs 10/19/2011 09:53

Mine doesn't require the unsafe or fixed declarations in every method, but yeah something like that.

BaussHacker 10/19/2011 11:17

Quote:

Originally Posted by Arco. (Post 13424242)
Sorta long the lines of this?
Code:

        public static void WriteUInt32(uint arg, int offset, byte[] buffer)
        {
            unsafe
            {
                fixed (byte* Buffer = buffer)
                {
                    *((uint*)(Buffer + offset)) = arg;
                }
            }
        }

Alright in case that's what you mean by it, this is what I recoded my packetbuilder to.

Spoiler:
Code:

public class Writer
{
    byte[] buffer;

    public Writer(byte[] BUFFER)
    {
        buffer = BUFFER;
    }
    public void WriteStringWithLength(string arg, int offset)
    {
        buffer[offset] = (byte)arg.Length;
        offset++;
        ushort i = 0;
        while (i < arg.Length)
        {
            buffer[(ushort)(i + offset)] = (byte)arg[i];
            i = (ushort)(i + 1);
        }
    }
    public void WriteString(string arg, int offset )
    {
        if (buffer.Length >= offset + arg.Length)
        {
            unsafe
            {
                fixed (byte* Buffer = buffer)
                {
                    ushort i = 0;
                    while (i < arg.Length)
                    {
                        *((byte*)(Buffer + offset + i)) = (byte)arg[i];
                        i++;
                    }
                }
            }
        }
    }
    public void WriteByte(byte arg, int offset )
    {
        buffer[offset] = (byte)(arg);
    }
    public void WriteUInt16(ushort arg, int offset )
    {
        if (buffer.Length >= offset + sizeof(ushort))
        {
            unsafe
            {
                fixed (byte* Buffer = buffer)
                    *((ushort*)(Buffer + offset)) = arg;
            }
        }
    }
    public void WriteUInt32(uint arg, int offset )
    {
        if (buffer.Length >= offset + sizeof(uint))
        {
            unsafe
            {
                fixed (byte* Buffer = buffer)
                    *((uint*)(Buffer + offset)) = arg;

            }
        }
    }
    public void WriteUInt64(ulong arg, int offset )
    {
        if (buffer.Length >= offset + sizeof(ulong))
        {
            unsafe
            {
                fixed (byte* Buffer = buffer)
                    *((ulong*)(Buffer + offset)) = arg;

            }
        }
    }
    public void WriteStringList(List<string> arg, int offset )
    {

        buffer[offset] = (byte)arg.Count;
        offset++;
        foreach (string str in arg)
        {
            buffer[offset] = (byte)str.Length;
            WriteString(str, offset + 1);
            offset += str.Length + 1;
        }
    }
}


Make the class unsafe, then make a pointer within the class, instead declaring it everytime you're writing an offset.
Code:

byte* m_ptr
{
get
{
fixed (byte* ptr = buffer)
return ptr;
}
}

Now you don't need to declare an unsafe/fixed everytime. I think that's what Korvacs meant.

I don't know if it could help anything, but this is my packet-builder.
Code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ConquerServerProject.Core;

namespace ConquerServerProject.Packets
{
    public unsafe class ConquerPacket
    {
        public ConquerPacket(int Length, bool AddTQ)
        {
            if (Length > Kernel.MaxPacketSize)
                throw new Exception("Invalid Packet Length.");

            m_packet = new byte[Length + 8];

            if (AddTQ)
                Write(Kernel.ServerPrefix);
        }
        public int Length { get { return m_packet.Length; } }
        private byte* m_ptr
        {
            get
            {
                fixed (byte* ptr = m_packet)
                    return ptr;
            }
        }
        private byte[] m_packet;
        private int m_offset;

        public void Write(byte Value)
        {
            *((byte*)(m_ptr + m_offset)) = (byte)Value;
            m_offset++;
        }
        public void Write(byte[] Value)
        {
            foreach (byte b in Value)
                Write(b);
        }
        public void Write(ushort Value)
        {
            *((ushort*)(m_ptr + m_offset)) = (ushort)Value;
            m_offset += 2;
        }
        public void Write(uint Value)
        {
            *((uint*)(m_ptr + m_offset)) = (uint)Value;
            m_offset += 4;
        }
        public void Write(ulong Value)
        {
            *((uint*)(m_ptr + m_offset)) = (uint)Value;
            m_offset += 8;
        }
        public void Write(string Value)
        {
            for (int i = 0; i < Value.Length; i++)
            {
                *((byte*)(m_ptr + m_offset)) = Convert.ToByte(Value[i]);
                m_offset++;
            }
        }
        public void WriteString(string Value)
        {
            Write((byte)Value.Length);
            m_offset++;
            for (int i = 0; i < Length; i++)
            {
                *((byte*)(m_ptr + m_offset)) = Convert.ToByte(Value[i]);
                m_offset++;
            }
        }
        public void Move(int AddOffset)
        {
            m_offset += AddOffset;
        }

        public static implicit operator byte[](ConquerPacket Packet)
        {
            return Packet.m_packet;
        }
    }
}


nTL3fTy 10/19/2011 12:33

Quote:

Originally Posted by BaussHacker (Post 13425916)
...

You could also declare the pointer, and set some allocated space to it (like in COAI):
Code:

ptr = (byte*)(void*)Marshal.AllocHGlobal(size);
where size could be variable or a max packet length (1024 for example).

BaussHacker 10/19/2011 13:48

Quote:

Originally Posted by nTL3fTy (Post 13426598)
You could also declare the pointer, and set some allocated space to it (like in COAI):
Code:

ptr = (byte*)(void*)Marshal.AllocHGlobal(size);
where size could be variable or a max packet length (1024 for example).

Never knew of that. I will look up on that ;O

IAmHawtness 10/19/2011 13:48

Quote:

Originally Posted by nTL3fTy (Post 13426598)
You could also declare the pointer, and set some allocated space to it (like in COAI):
Code:

ptr = (byte*)(void*)Marshal.AllocHGlobal(size);
where size could be variable or a max packet length (1024 for example).

What would the benefit be using AllocHGlobal instead of just "new byte[1024]"? They both allocate memory on the heap, but with AllocHGlobal you have to manually deallocate the memory when you're done using it.

InfamousNoone 10/19/2011 19:20

Quote:

Originally Posted by IAmHawtness (Post 13427485)
What would the benefit be using AllocHGlobal instead of just "new byte[1024]"? They both allocate memory on the heap, but with AllocHGlobal you have to manually deallocate the memory when you're done using it.

Using the 'new' operator in C# means you're allocating managed memory. Which means, everytime you want to write to it using pointer logic, you have to fix it down. Fixing it down means your forcibly preventing the GC from moving the data to some other location in the memory.

Moral of the story, constantly/repetitively fixing down an array is expensive in contrast to doing it once (or not at all).

_DreadNought_ 10/19/2011 21:36

Infamous, How do you structure your packets and whats your fav way of doing it?(curious)

InfamousNoone 10/20/2011 07:09

I generally stick to the C/C++ way of doing it first demonstrated by bone-you.
i.e.
Code:

typedef packet0x420 struct {
        PACKETHEADER Header;
        DWORD Argument;
} MSG_TRADE;

So in C#, my code would look like,
Code:

struct MsgTrade
{
        public short Size;
        public short Type;
        public int Argument;
}

Code:

var msg = new MsgTrade();
msg.Size = sizeof(MsgTrade);
msg.Type = PacketTypes.Trade;
msg.Argument = ivar;
Client.Send(&msg);

And then for any packets that have non-static sizes (for instance, the synchronization, message, etc packet) I implement an interface that a GetBytes() function, and a FromBytes() function.

ConquerAI however uses a packet builder for everything, this system was already set up when I joined the project so I decided to just follow suite instead of changing it to work to my liking.

Korvacs 10/21/2011 01:14

Quote:

Originally Posted by Korvacs (Post 13425337)
Mine doesn't require the unsafe or fixed declarations in every method, but yeah something like that.

Ironically just dropped this method all together today on my current project lol.


All times are GMT +2. The time now is 23:19.

Powered by vBulletin®
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.
SEO by vBSEO ©2011, Crawlability, Inc.