using System;
using System.Collections.Generic;
using System.Text;
public class Packet
{
private List<byte> buffer = new List<byte>();
private int byteIndex = 0;
private int maxByteIndex = 0;
public byte[] Buffer
{
get
{
return buffer.ToArray();
}
}
public int Length
{
get
{
return buffer.Count;
}
}
public int ByteIndex
{
get
{
return byteIndex;
}
set
{
if (value < 0 || value >= buffer.Count)
{
throw new ArgumentOutOfRangeException("ByteIndex must be an index in the Buffer");
}
byteIndex = value;
}
}
public bool HasHeader
{
get
{
return byteIndex >= 2;
}
}
public bool HasData
{
get
{
return byteIndex == maxByteIndex;
}
}
public void Begin()
{
buffer.Add(0);
buffer.Add(0);
byteIndex += 2;
}
public void End()
{
buffer[0] = (byte)(buffer.Count >> 8);
buffer[1] = (byte)buffer.Count;
}
public bool ReadHeader()
{
int previousByteIndex = byteIndex;
byteIndex = 0;
ushort length;
ReadUInt16(out length);
maxByteIndex = (int)length - 1;
byteIndex = previousByteIndex;
return maxByteIndex > 2;
}
public void WriteEventID(byte value)
{
buffer.Add(value);
byteIndex++;
}
public void WriteByte(byte value)
{
buffer.Add(value);
byteIndex++;
}
public void WriteUInt16(ushort value)
{
buffer.Add((byte)(value >> 8));
buffer.Add((byte)value);
byteIndex += 2;
}
public void WriteString(string value, int maxLength = 255)
{
if (maxLength < 0 || maxLength > ushort.MaxValue)
{
throw new ArgumentOutOfRangeException("maxLength must be in the range [0, 65535]");
}
if (value.Length > maxLength)
{
throw new ArgumentOutOfRangeException("String length was over the given max length");
}
WriteUInt16((ushort)value.Length);
var characters = System.Text.Encoding.ASCII.GetBytes(value);
foreach (var character in characters)
{
WriteByte(character);
}
}
public bool ReadEventID(out byte value)
{
return ReadByte(out value);
}
public bool ReadByte(out byte value)
{
value = 0;
if (byteIndex >= buffer.Count)
{
return false;
}
value = buffer[byteIndex];
byteIndex++;
return true;
}
public bool ReadUInt16(out ushort value)
{
value = 0;
if (byteIndex + 1 >= buffer.Count)
{
return false;
}
value = (ushort)(buffer[byteIndex] << 8);
value |= (ushort)buffer[byteIndex + 1];
byteIndex += 2;
return true;
}
public bool ReadString(out string value, int maxLength = 255)
{
value = string.Empty;
ushort length;
if (!ReadUInt16(out length) || length > maxLength || byteIndex + length > buffer.Count)
{
return false;
}
value = System.Text.Encoding.ASCII.GetString(buffer.ToArray(), byteIndex, (int)length);
byteIndex += length;
return true;
}
}
public class Test
{
public static void Main()
{
var packet = new Packet();
packet.Begin();
packet.WriteEventID(42);
packet.WriteByte(43);
packet.WriteUInt16(65535);
packet.WriteString("Hello World", 20);
packet.End();
packet.ByteIndex = 2;
byte eventID;
if (!packet.ReadEventID(out eventID)) { Console.WriteLine("Error reading"); return; }
Console.WriteLine(eventID);
byte byteValue;
if (!packet.ReadByte(out byteValue)) { Console.WriteLine("Error reading"); return; }
Console.WriteLine(byteValue);
ushort ushortValue;
if (!packet.ReadUInt16(out ushortValue)) { Console.WriteLine("Error reading"); return; }
Console.WriteLine(ushortValue);
string stringValue;
if (!packet.ReadString(out stringValue)) { Console.WriteLine("Error reading"); return; }
Console.WriteLine(stringValue);
/*
To read from a TCP stream:
// packet is a per end point object that persists through read callbacks
for (int readByteIndex = 0; readByteIndex < receiveBufferSize; ++readByteIndex)
{
packet.WriteByte(receiveBuffer[readByteIndex]);
if (!packet.HasHeader)
{
if (!packet.ReadHeader())
{
DisconnectEndPoint();
}
}
if (!packet.HasData)
{
// Packets is a ConcurrentQueue
endPoint.Packets.Enqueue(packet);
packet = new Packet();
}
}
*/
}
}