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

08/13/2010 17:04 Basser#1
I got my answer, remove this thread.
08/13/2010 17:38 pro4never#2
It's def interesting.

Personally i'm a fan of older style packet builders like coemu/llots/immune's source where you can just setup the values and run w/o needing a whole slew of different things for one ppacket. It's sexeh how you have it... it's just not the way i tend to think and therefor becomes awkward to code.
08/13/2010 17:54 Basser#3
Immunes source used offsets right? So if 2 offsets changed, you would actually have to change all offsets affected, for this one, you dont.
Also I will not use this for very big packets with lots of gaps and strings without a fixed length.
08/13/2010 18:14 bone-you#4
I'm curious if my method I used for packets is able to work in C#. It is quite similar to yours minus the get accessors. It had a huge enum and all the structs made out but for packets with dynamic sizes (like strings) it did a little behind the scenes work like what you pasted to make it work right. Do you have this actually working on a large scale?
08/13/2010 18:43 Korvacs#5
I use packets like this for my proxy, except that in C# theres no physical way of using structs for packets which contain dynamic length strings, unfortunately. So these work well for everything except for ChatPacket(1004) and CharInfo(1006).

They are really handy for unions, makes life alot easier.
08/13/2010 19:00 bone-you#6
Quote:
Originally Posted by Korvacs View Post
I use packets like this for my proxy, except that in C# theres no physical way of using structs for packets which contain dynamic length strings, unfortunately. So these work well for everything except for ChatPacket(1004) and CharInfo(1006).

They are really handy for unions, makes life alot easier.
Sure there is. You do it like he did it and like how I did it in C++. There will obviously be a function call required to "construct" the packet but it would indeed work very well.

Code:
char * CXSPackets::BuildPacket(int type)
{
	switch (type)
	{
	case 0x03E9:
		CreateCharacterPacket.type = type;
		CreateCharacterPacket.size = sizeof(CreateCharacterPacket);
		return (char *)&CreateCharacterPacket;
	case 0x03EC:
		ZeroMemory(&buffer, sizeof(buffer));
		*(WORD*)(buffer) = size;
		*(WORD*)(buffer+2) = packetid;
		*(int*)(buffer+4) = ChatPacket.color;
		*(int*)(buffer+8) = ChatPacket.chattype;
		memcpy(buffer+12, ChatPacket.time, 4);
		*(int*)(buffer+16) = ChatPacket.unknown1;
		*(int*)(buffer+20) = ChatPacket.display;
		*(char*)(buffer+24) = ChatPacket.unknown2;
		*(char*)(buffer+25) = ChatPacket.fromcount;
		memcpy(buffer+26, ChatPacket.from, ChatPacket.fromcount);
		*(char*)(buffer+26+ChatPacket.fromcount) = ChatPacket.tocount;
		memcpy(buffer+27+ChatPacket.fromcount, ChatPacket.to, ChatPacket.tocount);
		*(char*)(buffer+28+ChatPacket.fromcount+ChatPacket.tocount) = ChatPacket.stringcount;
		memcpy(buffer+29+ChatPacket.fromcount+ChatPacket.tocount, ChatPacket.string, ChatPacket.stringcount);
		*(WORD*)(buffer) = size = 29 + ChatPacket.fromcount + ChatPacket.tocount + ChatPacket.stringcount;
		return (char *)buffer;
	case 0x03ED:
		MovePacket.type = type;
		MovePacket.size = sizeof(MovePacket);
		return (char *)&MovePacket;
	case 0x041B:
		LoginPacket.type = type;
		LoginPacket.size = sizeof(LoginPacket);
		return (char *)&LoginPacket;
	case 0x041C:
		LanguagePacket.type = type;
		LanguagePacket.size = sizeof(LanguagePacket);
		return (char *)&LanguagePacket;
	case 0x03EE:
		ZeroMemory(&buffer, sizeof(buffer));
		CharacterDataPacket.type = type;
		CharacterDataPacket.size = sizeof(CharacterDataPacket);
		memcpy(buffer, &CharacterDataPacket, 68);
		*(char*)(buffer+68) = CharacterDataPacket.charnamecount;
		memcpy(buffer+69, CharacterDataPacket.charactername, CharacterDataPacket.charnamecount);
		*(char*)(buffer+69+CharacterDataPacket.charnamecount) = CharacterDataPacket.spousenamecount;
		memcpy(buffer+70+CharacterDataPacket.charnamecount, CharacterDataPacket.spousename, CharacterDataPacket.spousenamecount);
		*(WORD*)(buffer) = size = 67 + CharacterDataPacket.spousenamecount + CharacterDataPacket.charnamecount + 4;

		return (char *)buffer;
etc etc
08/13/2010 19:05 Korvacs#7
Using a dynamic char[] in the struct for CharInfo, and then trying to do this:

Code:
CharacterInfo* Packet = (CharacterInfo*)Pointer;
Returns this compiler error:

Code:
Error	1	Cannot take the address of, get the size of, or declare a pointer to a managed type ('MiningBot.Networking.Packets.CharacterInfo')	C:\Users\Jack\Documents\Visual Studio 2010\Projects\MiningBot\MiningBot\Networking\PacketHandler.cs	60	25	MiningBot
So tell me again how i could get around that issue using a struct?
08/13/2010 19:22 bone-you#8
Quote:
Originally Posted by Korvacs View Post
Using a dynamic char[] in the struct for CharInfo, and then trying to do this:

Code:
CharacterInfo* Packet = (CharacterInfo*)Pointer;
Returns this compiler error:

Code:
Error	1	Cannot take the address of, get the size of, or declare a pointer to a managed type ('MiningBot.Networking.Packets.CharacterInfo')	C:\Users\Jack\Documents\Visual Studio 2010\Projects\MiningBot\MiningBot\Networking\PacketHandler.cs	60	25	MiningBot
So tell me again how i could get around that issue using a struct?
If you're asking me, ask Basser. He seems to have gotten it to work. As for your attitude of "impossible!", that is not the attitude of a true developer/programmer. Nothing is impossible. While I know it is not impossible to do it in C# entirely, if you absolutely desired to, you could even import these functions from a DLL of another language to accomplish it. It is not impossible to get the desired results in C#.


I think I get your question though. You can't have dynamic sizes in essence. In C++ you'd use pointers, create the memory, then memcpy to a temp buffer in order to return a full packet. You'd have to find a method of doing that in C#.
08/13/2010 19:32 Korvacs#9
My attitude isnt "Impossible!", my attitude is, ive spent months looking into this and ive found that you just cannot do it with dynamic values in a fixed struct, Basser has created a packet with no dynamic values, which i have also done:

Code:
ItemDataPacket* Packet = (ItemDataPacket*)Pointer;
Compiles with no issues. However you cannot have a dynamic value in a fixed struct, you just cant do it.

Google it, research it, contact microsoft about it, it cant be done in C#.
08/13/2010 19:49 ImmuneOne#10
Quote:
Originally Posted by Korvacs View Post
My attitude isnt "Impossible!", my attitude is, ive spent months looking into this and ive found that you just cannot do it with dynamic values in a fixed struct, Basser has created a packet with no dynamic values, which i have also done:

Code:
ItemDataPacket* Packet = (ItemDataPacket*)Pointer;
Compiles with no issues. However you cannot have a dynamic value in a fixed struct, you just cant do it.

Google it, research it, contact microsoft about it, it cant be done in C#.
Code:
        [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
        struct MessagePacket
        {
            public PacketHeader Header;//0-4
            public UInt32 Msg_Color;//4-8
            public UInt32 Msg_Type;//8-12
            public UInt32 Msg_ID;//12-16
            public UInt64 Unknown;//16-24
            public Byte String_Count;//24-25
            public Byte String_From_Length;//25-26
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
            public String String_From;//26-27 + pos
            public Byte String_To_Length;//27 + pos - 28 + pos
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
            public String String_To;//28 + pos - 29 + pos
            public Byte Blank;//29 + pos - 30 + pos
            public Byte String_Message_Length;//30 + pos - 31 + pos
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
            public String String_Message;//31 + pos - 32 + pos
        }

//Get the size; Marshal.SizeOf(Instance);
//Set the length of each string to 16.
You gotta thank Nullable for the constant length fix though, I personally thought the client would not trim these.
08/13/2010 19:50 ImFlamedCOD#11
Basser that is a good method to do you packets with. Used it before and use a variation of it now. So in my opinion yea it is a good method.
08/13/2010 19:53 bone-you#12
Quote:
Originally Posted by Korvacs View Post
My attitude isnt "Impossible!", my attitude is, ive spent months looking into this and ive found that you just cannot do it with dynamic values in a fixed struct, Basser has created a packet with no dynamic values, which i have also done:

Code:
ItemDataPacket* Packet = (ItemDataPacket*)Pointer;
Compiles with no issues. However you cannot have a dynamic value in a fixed struct, you just cant do it.

Google it, research it, contact microsoft about it, it cant be done in C#.
Ok Mr Hostility. My first reply was explaining in general that it was possible. You came back with a "it's not possible to do X, tell me how to do it!" trying to pick a fight as if I said you could do it the way you're trying lol.

I'm not saying you can do it with dynamic values. Maybe in the future you can with a high-level language like C#, but for now no. You have to do it with fixed-size structs like you always have... hence the need for a "construct" function to build the packet of a "variable-size" struct into a buffer.
08/13/2010 20:03 Korvacs#13
Quote:
Originally Posted by ImmuneOne View Post
Code:
        [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
        struct MessagePacket
        {
            public PacketHeader Header;//0-4
            public UInt32 Msg_Color;//4-8
            public UInt32 Msg_Type;//8-12
            public UInt32 Msg_ID;//12-16
            public UInt64 Unknown;//16-24
            public Byte String_Count;//24-25
            public Byte String_From_Length;//25-26
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
            public String String_From;//26-27 + pos
            public Byte String_To_Length;//27 + pos - 28 + pos
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
            public String String_To;//28 + pos - 29 + pos
            public Byte Blank;//29 + pos - 30 + pos
            public Byte String_Message_Length;//30 + pos - 31 + pos
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
            public String String_Message;//31 + pos - 32 + pos
        }

//Get the size; Marshal.SizeOf(Instance);
//Set the length of each string to 16.
You gotta thank Nullable for the constant length fix though, I personally thought the client would not trim these.
Again, that doesnt work for dynamic length strings, i explored that but what your doing there is assigning the string a fixed length in memory, so if the string is say 4 bytes long, then when you assign the data from the pointer to the struct you read a further 12 bytes into invalid memory, because the packet you assigned only have 4 bytes of data at that location.

Honestly, i explored every option for this, it cannot be done.

@Bone, actually in my original post i said that it works well for everything except to packets which dont work because of the need for variable sized arrays, and you came back with of course it can be done with dynamic values, so im not being hostile, im just being correct, you cannot do it thats the end of it. You can work around it using constructs which of course can be done, sadly its alot less elegant and requires more processing and cpu time. But that is a work around to something that they should have more sense about when designing the language. :(
08/13/2010 20:09 Basser#14
@Bone, well Korvacs is right, and I did know this. It is not impossible, but I have no idea how to make it possible though. =/
@Korvacs, Yes, unfortunately this is the case, however for the other structures, I do like this, glad you do too. I didnt know other people used this method already =P
I came up with it when I was trying to learn more about pointer usage in my source.
08/13/2010 20:14 ImmuneOne#15
Quote:
Originally Posted by Korvacs View Post
...
This method works very well for every auth/game packet I use.