| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201 | using InABox.Core;using System;using System.Collections.Generic;using System.IO;using System.Linq;using System.Reflection.Emit;using System.Text;using System.Threading.Tasks;namespace InABox.WebSocket.Shared{    public class ByteReader    {        public byte[] Data;        public int Index;        public ByteReader(byte[] data)        {            Data = data;            Index = 0;        }        public Guid ReadGuid()        {            var guid = new Guid(new ReadOnlySpan<byte>(Data, Index, 16));            Index += 16;            return guid;        }        public string ReadUTF8String()        {            int i = Index;            while (i < Data.Length && Data[i] != 0)            {                i++;            }            var str = Encoding.UTF8.GetString(Data, Index, i - Index);            Index = i + 1;            return str;        }        public byte ReadByte()        {            return Data[Index++];        }        public ByteReader Skip(int count)        {            Index += count;            return this;        }    }    public class ByteWriter    {        private Stream Stream;        public ByteWriter(Stream stream)        {            Stream = stream;        }        public ByteWriter WriteByte(byte b)        {            Stream.WriteByte(b);            return this;        }        public ByteWriter WriteGuid(Guid guid)        {            Stream.Write(guid.ToByteArray());            return this;        }        /// <summary>        /// Writes a null-terminated UTF-8 encoded string to the buffer        /// </summary>        /// <param name="str"></param>        /// <returns></returns>        public ByteWriter WriteUTF8String(string str)        {            Stream.Write(Encoding.UTF8.GetBytes(str));            Stream.WriteByte(0);            return this;        }    }    public abstract class SocketMessage    {        public enum MessageType        {            Initial = 0x00,            Push = 0x01        }        public abstract MessageType Type { get; }        protected abstract void Write(ByteWriter writer);        public void Write(Stream stream)        {            var writer = new ByteWriter(stream)                .WriteByte((byte)Type);            Write(writer);        }        public byte[] WriteToBytes()        {            using(var stream = new MemoryStream())            {                Write(stream);                return stream.GetBuffer().ToArray();            }        }        public static SocketMessage? ReadMessage(byte[] data)        {            try            {                var type = (MessageType)data[0];                var byteReader = new ByteReader(data).Skip(1);                switch (type)                {                    case MessageType.Initial:                        return InitialMessage.ReadMessage(byteReader);                    case MessageType.Push:                        return PushMessage.ReadMessage(byteReader);                }            }            catch (Exception)            {                return null;            }            return null;        }    }    public class InitialMessage : SocketMessage    {        public override MessageType Type => MessageType.Initial;        public Guid SessionID { get; set; }        public Platform Platform { get; set; }        public InitialMessage(Guid sessionID, Platform platform)        {            SessionID = sessionID;            Platform = platform;        }        protected override void Write(ByteWriter writer)        {            writer.WriteGuid(SessionID)                .WriteByte((byte)Platform);        }        public static InitialMessage ReadMessage(ByteReader data)        {            var session = data.ReadGuid();            var platform = (Platform)data.ReadByte();            return new InitialMessage(session, platform);        }    }    public class PushMessage : SocketMessage    {        public override MessageType Type => MessageType.Push;        public string EntityType;        public string EntityData;        private PushMessage(string entityType, string entityData)        {            EntityType = entityType;            EntityData = entityData;        }        protected override void Write(ByteWriter writer)        {            writer.WriteUTF8String(EntityType);            writer.WriteUTF8String(EntityData);        }        public static PushMessage ReadMessage(ByteReader reader)        {            var type = reader.ReadUTF8String();            var data = reader.ReadUTF8String();            return new PushMessage(type, data);        }        public static PushMessage Push<TPush>(TPush push)            where TPush : BaseObject        {            return new PushMessage(typeof(TPush).EntityName(), Serialization.Serialize(push));        }        public static PushMessage Push(Type TPush, object push)        {            return new PushMessage(TPush.EntityName(), Serialization.Serialize(push));        }    }}
 |