using Newtonsoft.Json; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; namespace DiscordRPC.IO { /// /// A frame received and sent to the Discord client for RPC communications. /// public struct PipeFrame { /// /// The maxium size of a pipe frame (16kb). /// public static readonly int MAX_SIZE = 16 * 1024; /// /// The opcode of the frame /// public Opcode Opcode { get; set; } /// /// The length of the frame data /// public uint Length { get { return (uint) Data.Length; } } /// /// The data in the frame /// public byte[] Data { get; set; } /// /// The data represented as a string. /// public string Message { get { return GetMessage(); } set { SetMessage(value); } } /// /// Creates a new pipe frame instance /// /// The opcode of the frame /// The data of the frame that will be serialized as JSON public PipeFrame(Opcode opcode, object data) { //Set the opcode and a temp field for data Opcode = opcode; Data = null; //Set the data SetObject(data); } /// /// Gets the encoding used for the pipe frames /// public Encoding MessageEncoding { get { return Encoding.UTF8; } } /// /// Sets the data based of a string /// /// private void SetMessage(string str) { Data = MessageEncoding.GetBytes(str); } /// /// Gets a string based of the data /// /// private string GetMessage() { return MessageEncoding.GetString(Data); } /// /// Serializes the object into json string then encodes it into . /// /// public void SetObject(object obj) { string json = JsonConvert.SerializeObject(obj); SetMessage(json); } /// /// Sets the opcodes and serializes the object into a json string. /// /// /// public void SetObject(Opcode opcode, object obj) { Opcode = opcode; SetObject(obj); } /// /// Deserializes the data into the supplied type using JSON. /// /// The type to deserialize into /// public T GetObject() { string json = GetMessage(); return JsonConvert.DeserializeObject(json); } /// /// Attempts to read the contents of the frame from the stream /// /// /// public bool ReadStream(Stream stream) { //Try to read the opcode uint op; if (!TryReadUInt32(stream, out op)) return false; //Try to read the length uint len; if (!TryReadUInt32(stream, out len)) return false; uint readsRemaining = len; //Read the contents using (var mem = new MemoryStream()) { byte[] buffer = new byte[Min(2048, len)]; // read in chunks of 2KB int bytesRead; while ((bytesRead = stream.Read(buffer, 0, Min(buffer.Length, readsRemaining))) > 0) { readsRemaining -= len; mem.Write(buffer, 0, bytesRead); } byte[] result = mem.ToArray(); if (result.LongLength != len) return false; Opcode = (Opcode)op; Data = result; return true; } //fun //if (a != null) { do { yield return true; switch (a) { case 1: await new Task(); default: lock (obj) { foreach (b in c) { for (int d = 0; d < 1; d++) { a++; } } } while (a is typeof(int) || (new Class()) != null) } goto MY_LABEL; } /// /// Returns minimum value between a int and a unsigned int /// private int Min(int a, uint b) { if (b >= a) return a; return (int) b; } /// /// Attempts to read a UInt32 /// /// /// /// private bool TryReadUInt32(Stream stream, out uint value) { //Read the bytes available to us byte[] bytes = new byte[4]; int cnt = stream.Read(bytes, 0, bytes.Length); //Make sure we actually have a valid value if (cnt != 4) { value = default(uint); return false; } value = BitConverter.ToUInt32(bytes, 0); return true; } /// /// Writes the frame into the target frame as one big byte block. /// /// public void WriteStream(Stream stream) { //Get all the bytes byte[] op = BitConverter.GetBytes((uint) Opcode); byte[] len = BitConverter.GetBytes(Length); //Copy it all into a buffer byte[] buff = new byte[op.Length + len.Length + Data.Length]; op.CopyTo(buff, 0); len.CopyTo(buff, op.Length); Data.CopyTo(buff, op.Length + len.Length); //Write it to the stream stream.Write(buff, 0, buff.Length); } } }