Author | Message | Time |
---|---|---|
shout | [code] 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); } 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); } } } [/code] Example with parsing packets: [code] 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)); } [/code] Example de-buffer-ing :P: [code] 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); } [/code] It is also useful in hashing: [code] 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); [/code] [i]Edit: Changed code a tidbit | March 13, 2005, 3:01 PM |
Myndfyr | I'm still not quite sure what this does. Is it like a Stream? | March 15, 2005, 2:43 AM |
shout | [quote author=MyndFyre link=topic=10908.msg103883#msg103883 date=1110854580] I'm still not quite sure what this does. Is it like a Stream? [/quote] Yeah, I guess. I would say its more like a byte queue class. | March 15, 2005, 3:20 PM |
LoRd | Note that a packet buffer handles both outgoing and incoming packets. | March 27, 2005, 6:23 AM |