[Opinion] Do you like how these Packet Structures work?

08/13/2010 23:17 Basser#31
Justice smells good, doesn't it?
08/13/2010 23:21 bone-you#32
It is because you are assuming the names will always be 16 bytes long. There is no effective way to just throw it into a struct. You have to build it into one manually.

My C++ packet class. You need to do something similar for dynamic sized packets.
Code:
PacketType CXSPackets::ParsePacket(char * packet)
{
	packetid = *((WORD*)(packet+2));
	size = *((WORD*)(packet));
	switch (*((WORD*)(packet+2)))
	{
	case 0x03E9:
		ZeroMemory(&CreateCharacterPacket, sizeof(CreateCharacterPacket));
		memcpy(&CreateCharacterPacket, packet, size);
		return PacketType(packetid);
	case 0x03EC:
		ZeroMemory(&ChatPacket, sizeof(ChatPacket));
		ChatPacket.size = *(WORD*)(packet);
		ChatPacket.type = *((WORD*)(packet+2));
		ChatPacket.color = *((int*)(packet+4));
		ChatPacket.chattype = *((int*)(packet+8));
		memcpy(ChatPacket.time, packet+12, 4);
		ChatPacket.unknown1 = *((int*)(packet+16));
		ChatPacket.display = *((int*)(packet+20));
		ChatPacket.unknown2 = *((char*)(packet+24));
		ChatPacket.fromcount = *((char*)(packet+25));
		memcpy(ChatPacket.from, packet+26, ChatPacket.fromcount);
		ChatPacket.tocount = *((char*)(packet+26+ChatPacket.fromcount));
		memcpy(ChatPacket.to, packet+27+ChatPacket.fromcount, ChatPacket.tocount);
		ChatPacket.stringcount = *((char*)(packet+28+ChatPacket.fromcount+ChatPacket.tocount));
		memcpy(ChatPacket.string, packet+29+ChatPacket.fromcount+ChatPacket.tocount, ChatPacket.stringcount);
		return PacketType(packetid);
	case 0x03ED:
		ZeroMemory(&MovePacket, sizeof(MovePacket));
		memcpy(&MovePacket, packet, size);
		return PacketType(packetid);
	case 0x041B:
		ZeroMemory(&LoginPacket, sizeof(LoginPacket));
		memcpy(&LoginPacket, packet, size);
		return PacketType(packetid);
08/13/2010 23:23 Korvacs#33
Quote:
Originally Posted by bone-you View Post
It is because you are assuming the names will always be 16 bytes long. There is no effective way to just throw it into a struct. You have to build it into one manually.
Thats my point, you cannot just define a fixed array for strings, therefore dynamic arrays are required and therefore you cannot use a struct in that way (Sadly) in C# for anything that requires a dynamic length string.

I think that just about clears up everything =x
08/13/2010 23:25 bone-you#34
Quote:
Originally Posted by Korvacs View Post
Thats my point, you cannot just define a fixed array for strings, therefore dynamic arrays are required and therefore you cannot use a struct in that way (Sadly) in C# for anything that requires a dynamic length string.

I think that just about clears up everything =x
You cannot do what you were trying to do which was point to a managed struct with a dynamic var IN the struct. You CAN on the other hand use a DYNAMIC sized struct to COPY the data into effectively achieving the same result which is what I was saying this entire time lol. The same process would go for constructing the packet when trying to send data. You'd copy FROM the dynamic sized struct into a buffer instead of using the struct itself as one.
08/13/2010 23:27 ImmuneOne#35
Quote:
Originally Posted by Korvacs View Post
Just decided to have a go with your packet and this:

Code:
MessagePacket* Packet = (MessagePacket*)Pointer;
Does not compile, go figure.

So i went ahead and modified it so that it would atleast compile using fixed sbyte buffers:

Code:
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public unsafe struct MessagePacket
    {
        public ushort Lenght;
        public ushort Type;//0-4
        public uint Msg_Color;//4-8
        public uint Msg_Type;//8-12
        public uint Msg_ID;//12-16
        public ulong Unknown;//16-24
        public byte String_Count;//24-25
        public byte String_From_Length;//25-26
        public fixed sbyte String_From[16];//26-27 + pos
        public byte String_To_Length;//27 + pos - 28 + pos
        public fixed sbyte String_To[16];//28 + pos - 29 + pos
        public byte Blank;//29 + pos - 30 + pos
        public byte String_Message_Length;//30 + pos - 31 + pos        
        public fixed sbyte String_Message[16];//31 + pos - 32 + pos
    }
And then i sent a chat packet and used this method to demonstrate the issues with it, its not exactly clean but its a valid way of doing it:

Code:
                        MessagePacket* Packet = (MessagePacket*)Pointer;

                        Console.WriteLine("[ChatPacket] From {0} To {1} : {2}", new string(Packet->String_From), new string(Packet->String_To), new string(Packet->String_Message));
And this is the outcome:

[Only registered and activated users can see links. Click Here To Register...]

Now honestly, i dont pretend to be an expert, but that doesnt work does it. As far as i can tell theres nothing especially wrong with my implementation of it unless someone else can suggest a more appropriate method?
Write method:
Code:
            IntPtr Ptr = Marshal.AllocHGlobal(Packet.Length);
            Marshal.StructureToPtr(Struct, Ptr, false);

            fixed (byte* pckt = this.Packet)
            {
                Native.memcpy(pckt, Ptr.ToPointer(), Packet.Length);
            }
On de-serializing:
Code:
        public void Deserialize(IConquerPacket ConquerPacket)
        {
            fixed (byte* Packet = ConquerPacket.ToArray())
            {
                MsgPacket = *((MessagePacket*)(Packet));
                fixed (MessagePacket* Msg = &MsgPacket)
                {
                     this.Msg_From = new string(Msg->String_From);
                     this.Msg_To = new string(Msg->String_To);
                     this.Msg_Data = new string(Msg->String_Message);
                }
            }
        }
08/14/2010 00:30 Korvacs#36
Well, thanks for clarifying that aspect of it, wish you could have done that 2 pages ago instead of me doing all of that >.<!
08/14/2010 00:33 ImmuneOne#37
Quote:
Originally Posted by Korvacs View Post
Well, thanks for clarifying that aspect of it, wish you could have done that 2 pages ago instead of me doing all of that >.<!
Haha forgive me:p
08/14/2010 05:05 _tao4229_#38
You guys are doing it wrong. Don't assume TQ will send null terminators.
ie: new string ((sbyte*)addr->Offset, offset, addr->Length);

Just saying.
08/14/2010 12:55 ImmuneOne#39
Quote:
Originally Posted by _tao4229_ View Post
You guys are doing it wrong. Don't assume TQ will send null terminators.
ie: new string ((sbyte*)addr->Offset, offset, addr->Length);

Just saying.
He was using fixed sbyte in his struct, that's why I showed him that method. And it works perfectly fine if you just trim the string.