using System; using System.Collections.Generic; using System.Text; public class Packet { private List buffer = new List(); 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(); } } */ } }