PDA

View Full Version : Help with encoding/decoding packets in C#


punky
05-12-2010, 07:03 AM
Hi all.

I'm trying to do a BC2 query tool using C# and i'm really struggling with the encoding/decoding packets. I just can't get it to make sense in my head what the process is.

I have tried reading the EA PDF which doesn't make it clear
I have tried reading the protocol info on b2tech.org, likewise

I have tried to port it over from examples:

1. I tried to extract the methods out of Procon but its so integrated it makes my head spin.

2. I tried porting BC2RCON (from VB both by hand and by online converter) and I get to a point and fail.

3. I tried porting PHP scripts but the typeless nature is confusing.

4. I tried porting over a Java version but I get to where the bitwise operations are and fail.


The problem is i'm an accompished programmer but not really used bitwise operations and byte arrays before so when porting i'm not sure.

Can someone either explain in clear english the process of encoding and decoding a packet so I can code it myself or can the port the python functions over to C#? I can post some of my previous attempts that can be fixed if you prefer.

Many thanks in advance. I'm starting to have dreams about byte arrays and uints now!

Phogue
05-12-2010, 07:43 AM
If it's flat encoding/decoding packets in C# then you can just look at the Packet class in procon, if that narrows it down the search a little =)

http://procon.codeplex.com/SourceControl/changeset/view/233c85cb14dd#src%2fPRoCon.Core%2fPacket.cs

Using the procon class the psuedocode for looping in a recv for incoming packets:
Connection = Connect()

byte[] FullByteStream;

While (Connection.Open == true) {

// You might not receive a full packet in one ReadBytes() call.
FullByteStream += Connection.ReadBytes()

if (FullByteStream.Length >= 12) {

// Read an int from the start of the byte stream
int PacketLength = BitConverter.ToUInt32(FullByteStream, 4);

if (PacketLength <= FullByteStream.Length) {

// We've read in enough data for a full packet
// The following assumes you are using the Packet class from procon.
Packet RecievedPacket = new Packet(FullByteStream[0, PacketLength]);

// Remove the full packet from the beginning of the read byte stream.
FullByteStream = FullByteStream[PacketLength, FullByteStream.Length]

}
}

}

Let us know how you go.

punky
05-12-2010, 08:22 AM
Dude, I love you. Thanks so much. Got it working fine now.

I was making far too much work trying to extract your methods to put into mine. Didn't occur to me at the time I could just import your Packet class and use that. So simple, easy and elegant.

Thanks again mate :)

PsycX0r
05-12-2010, 08:35 AM
Here is (a reduced version of) the low level protocol class of my tool (more about that when the version for R12 is out..).
Should be more usable than the vb.net implementation in this forum:)
It reads from the socket in a seperate thread and has event handling etc.

punky
05-12-2010, 09:09 AM
Here is (a reduced version of) the low level protocol class of my tool (more about that when the version for R12 is out..).
Should be more usable than the vb.net implementation in this forum:)
It reads from the socket in a seperate thread and has event handling etc.

Excellent mate, many thanks for your help too. I'm sure it'll come in handy as it builds up the functionality a bit more.

While i'm here I do have another quick question, its not clear how the server events work. Is it like this?


client........................server

socket.send -------> login.plainText password
socket.receive <------- OK
socket.receive <-------
[wait]
.
.
.
.
socket.receive <------- player.onJoin playername
socket.send -------> OK
socket.receive <-------
[wait]
.
.
.
[etc]

and then just parse out the players name from DecodePacket using the receive buffer that contains the player.onJoin?

PsycX0r
05-12-2010, 05:31 PM
Not sure what you mean, but generally remember that event packets can come at any time, so you have to use the packet IDs and not just wait for the next 'OK' answer. And I also think it's best "manners" to receive/decode the whole packet before you send your 'OK'.
Also remember that a simple socket.receive may give you data for several packages, so it's probably best to just ask for the few header bytes, and then for the exact remaining size of that packet. I see procon is doing the same.

punky
05-12-2010, 08:44 PM
Not sure what you mean, but generally remember that event packets can come at any time, so you have to use the packet IDs and not just wait for the next 'OK' answer. And I also think it's best "manners" to receive/decode the whole packet before you send your 'OK'.
Also remember that a simple socket.receive may give you data for several packages, so it's probably best to just ask for the few header bytes, and then for the exact remaining size of that packet. I see procon is doing the same.

Ahh OK that makes sense. Cheers dude.