• Welcome to Valhalla Legends Archive.
 

[C#]Combination Packet Buffer/Debuffer

Started by shout, March 13, 2005, 09:01 AM

Previous topic - Next topic

shout


using System;
using System.Text;

namespace Packet
{
internal class FIFOByteBuffer
{
byte[] data;

public FIFOByteBuffer()
{
data = new byte[0];
}

#region private functions

void AppendByte(byte Data)
{
byte[] tmp = new byte[data.Length + 1];
Buffer.BlockCopy(data, 0, tmp, 0, data.Length);
tmp[data.Length] = Data;

data = tmp;
}

public byte PeekByte()
{
if (data.Length > 1)
return data[0];
return 0;
}

public byte PeekByte(int Index)
{
if (Length - 1 > Index)
{
return data[Index];
}
return 0;
}

byte RetriveByte()
{
if (data.Length == 0)
return 0;
byte[] tmp = new byte[0];
tmp = new byte[data.Length - 1];
Buffer.BlockCopy(data, 1, tmp, 0, data.Length - 1);

byte Data = data[0];
data = tmp;

return Data;
}

#endregion

#region Byte

public void InsertByte(byte Data)
{
this.AppendByte(Data);
}

public byte GetByte()
{
return this.RetriveByte();
}

public byte GetByte(int Index)
{
return this.RetriveByte(Index);
}

public void InsertByteArray(byte[] Data)
{
for (int i = 0; i < Data.Length; i++)
this.AppendByte(Data[i]);
}

public byte[] GetByteArray(int Length)
{
byte[] rBytes = new byte[Length];
for (int i = 0; i < Length; i++)
{
rBytes[i] = this.RetriveByte();
}
return rBytes;
}
#endregion

#region Word

public void InsertWord(short Data)
{
byte[] tmp = BitConverter.GetBytes(Data);
for (int i = 0; i < tmp.Length; i++)
this.AppendByte(tmp[i]);
}

public short GetWord()
{
byte[] tmp = new byte[2];
for (int i = 0; i > tmp.Length; i++)
tmp[i] = this.RetriveByte();

return BitConverter.ToInt16(tmp, 0);
}

public void InsertWordArray(short[] Data)
{
for (int i = 0; i < Data.Length; i++)
this.InsertWord(Data[i]);
}

public short[] GetWordArray(int Length)
{
short[] rShorts = new short[Length];
for (int i = 0; i < Length; i++)
rShorts[i] = this.GetWord();
return rShorts;
}

#endregion

#region Dword

public void InsertDword(int Data)
{
byte[] tmp = BitConverter.GetBytes(Data);
for (int i = 0; i < tmp.Length; i++)
this.AppendByte(tmp[i]);
}

public int GetDword()
{
byte[] tmp = new byte[4];
for (int i = 0; i < tmp.Length; i++)
tmp[i] = this.RetriveByte();

return BitConverter.ToInt32(tmp, 0);
}

public int GetDword(int Index)
{
byte[] tmp = new byte[4];
for (int i = 0; i < tmp.Length; i++)
tmp[i] = this.RetriveByte(Index + i);

return BitConverter.ToInt32(tmp, 0);
}

public void InsertDwordArray(int[] Data)
{
for (int i = 0; i < Data.Length; i++)
{
this.InsertDword(Data[i]);
}
}

public int[] GetDwordArray(int Length)
{
int[] rDwords = new int[Length];
for (int i = 0; i < rDwords.Length; i++)
{
rDwords[i] = this.GetDword();
}
return rDwords;
}

#endregion

#region Strings

public void InsertWideString(string Data)
{
byte[] tmp = Encoding.UTF8.GetBytes(Data);
for (int i = 0; i < tmp.Length; i++)
this.AppendByte(tmp[i]);
if (data[data.Length - 1] != 0x00)
this.AppendByte(0x00);
}

public void InsertString(string Data)
{
if (Data == string.Empty)
return;
if (Data == null)
return;
char[] ctmp = Data.ToCharArray();
byte[] tmp = new byte[ctmp.Length];
for (int i = 0; i < ctmp.Length; i++)
{
tmp[i] = (byte)ctmp[i];
}
for (int i = 0; i < tmp.Length; i++)
this.AppendByte(tmp[i]);
if (Data[Data.Length - 1] != 0x00)
this.AppendByte(0x00);
}

public string GetWideString()
{
int i = 0;
for (i = 0; ;i++)
{
if (this.PeekByte(i) == 0x00) //Finds out how long string is
break;
}

byte[] tmp = new byte[i];
for (int j = 0; j < i; j++)
tmp[j] = this.RetriveByte(); //Gets the string as a byte array

return Encoding.UTF8.GetString(tmp);
}

public string GetString()
{
int i = 0;
for (i = 0; ;i++)
{
if (this.PeekByte(i) == 0x00) //Finds out how long string is
break;
}

char[] ctmp = new char[i];
for (int j = 0; j < i; j++)
ctmp[j] = (char)this.GetByte(); //Gets the string as a byte array
this.RetriveByte(); //Null term

return new string(ctmp);
}

#endregion

public static implicit operator byte[](FIFOByteBuffer buff)
{
return buff.data;
}

public static implicit operator FIFOByteBuffer(byte[] buff)
{
FIFOByteBuffer x = new FIFOByteBuffer();
for (int i = 0; i < buff.Length; i++)
x.InsertByte(buff[i]);
return x;
}

public byte this [int Index]
{
get
{
return data[Index];
}
set
{
data[Index] = value;
}
}

public byte[] GetBnetPacket(byte PacketID)
{
FIFOByteBuffer buffer = new FIFOByteBuffer();
buffer.InsertByte(0xFF);
buffer.InsertByte(PacketID);
buffer.InsertWord((short)(this.data.Length + 4));
buffer.InsertByteArray(this.data);
return buffer;
}

public void InsertStringAsDword(string Data)
{
for (int i = 3; i > -1; i--)
this.AppendByte((byte)Data[i]);
}

public int Length
{
get
{
return data.Length;
}
}

public FIFOByteBuffer(byte[] buff)
{
this.data = buff;
}

public static FIFOByteBuffer operator +(FIFOByteBuffer x, FIFOByteBuffer y)
{
FIFOByteBuffer buff = x;
buff.InsertByteArray(y);
return buff;
}

public static bool operator ==(FIFOByteBuffer x, FIFOByteBuffer y)
{
if (x.Length != y.Length)
return false;
for (int i = 0; i < x.Length; i++)
{
if (x[i] != y[i])
return false;
}

return true;
}

public static bool operator !=(FIFOByteBuffer x, FIFOByteBuffer y)
{
if (x == y)
{
return false;
}

return true;
}

public override bool Equals(object obj)
{
return base.Equals (obj);
}

public override int GetHashCode()
{
return base.GetHashCode ();
}

public override string ToString()
{
return base.ToString();
}

public byte[] toByteArray()
{
byte[] tmp = this.data;
return tmp;
}

public int GetBnetPacketLength()
{
byte[] bLength = new byte[2];
bLength[0] = data[2];
bLength[1] = data[3];
return (int)BitConverter.ToInt16(bLength, 0);
}
}
}


Example with parsing packets:


public static byte[] Build(Client client)
{
if (client == Client.WarCraft2)
throw new PacketException("Invalid client for this packet");
if (client == Client.WarCraft3 || client == Client.WarCraft3TFT)
throw new NotSupportedException("This packet does not support this client in this version");
FIFOByteBuffer pbuffer = new FIFOByteBuffer();
pbuffer.InsertDword(0x0000000);
pbuffer.InsertStringAsDword("IX86");
switch (client)
{
case Client.BroodWar:
pbuffer.InsertStringAsDword("SEXP");
pbuffer.InsertDword(0x000000CB);
break;

case Client.StarCraft:
pbuffer.InsertStringAsDword("STAR");
pbuffer.InsertDword(0x000000CB);
break;

case Client.Diablo2:
pbuffer.InsertStringAsDword("D2DV");
pbuffer.InsertDword(0x0000000A);
break;

case Client.Diablo2LOD:
pbuffer.InsertStringAsDword("D2XP");
pbuffer.InsertDword(0x0000000A);
break;
}
pbuffer.InsertStringAsDword("enUS");
int[] zeros = new int[4] {0,0,0,0};
pbuffer.InsertDwordArray(zeros);
pbuffer.InsertString("USA");
pbuffer.InsertString("United States");
socket.send(pbuffer.GetBnetPacket(0x50));
}


Example de-buffer-ing :P:


private void packetstuff(byte[] recbuff)
{
FIFOByteBuffer pbuff = recbuff; //Implicit conversion from byte array
PacketHeader phead = pbuff.GetDword(); //Gets the first DWORD from the head of the buffer
int logontype = pbuff.GetDword();
int servertoken = pbuff.GetDword();
int UDPValue = pbuff.GetDword();
DateTime filetime = pbuff.GetFileTime(); //Something I forgot to put in this one...
string MPQString = pbuff.GetString(); //Reads bytes until it hits a null
//terminator, then returns as a string
int MPQVer = int.Parse(MPQString[8].ToString());
byte[] serversig;
if (logontype > 0)
serversig = pbuff.GetByteArray(128);
}


It is also useful in hashing:



int[] keyValue = DecodeKey(key);
FIFOByteBuffer buff = new FIFOByteBuffer();
buff.InsertDword(key.Length);
buff.InsertDword(keyValue[0]);
buff.InsertDword(keyValue[1]);
buff.InsertDword(0); // 0 Unknown

FIFOByteBuffer hashbuff = new FIFOByteBuffer();
hashbuff.InsertDword(ClientToken);
hashbuff.InsertDword(ServerToken);
hashbuff.InsertDword(keyValue[0]);
hashbuff.InsertDword(keyValue[1]);
hashbuff.InsertDword(0x00); //0 unknown
hashbuff.InsertDword(keyValue[2]);

return buff + XSha1.HashData(hashbuff);



Edit: Changed code a tidbit

MyndFyre

I'm still not quite sure what this does.  Is it like a Stream?
QuoteEvery generation of humans believed it had all the answers it needed, except for a few mysteries they assumed would be solved at any moment. And they all believed their ancestors were simplistic and deluded. What are the odds that you are the first generation of humans who will understand reality?

After 3 years, it's on the horizon.  The new JinxBot, and BN#, the managed Battle.net Client library.

Quote from: chyea on January 16, 2009, 05:05 PM
You've just located global warming.

shout

Quote from: MyndFyre on March 14, 2005, 08:43 PM
I'm still not quite sure what this does. Is it like a Stream?

Yeah, I guess.

I would say its more like a byte queue class.

Eric

#3
Note that a packet buffer handles both outgoing and incoming packets.