void ProcessCall(uint callId, uint type, BufferView data) { object inflatedData; // Check the sequence id if (callId != ++LastReceivedId) { ProtocolError(); return; } // Get call definition Registry.RegisteredCall call = Registry.GetServerCall(type); if (call == null) { ProtocolError(); return; } // Read the incoming data try { inflatedData = InflateData.Inflate(data, call.ArgsFormat); } catch { ProtocolError(); return; } // Emit the "call" event if (OnCall != null) { OnCall(this, new CallEventArgs(call, inflatedData, this, callId)); } }
/// <summary> /// Extract a single element from the view /// </summary> /// <param name="buffer">A view with the encoded data</param> /// <param name="data">The data ArrayList to store the extracted data</param> /// <param name="format">The format of the data to be extracted</param> /// <returns>Return the view parameter</returns> static BufferView ReadElement(BufferView buffer, ArrayList data, Format.ElementsArray format) { for (int i = 0; i < format.Elements.Count; i++) { switch (format.Elements[i].ElementType) { case Format.Element.Type.ARRAY: data.Add(ReadArray(buffer, (Format.ElementsArray)format.Elements[i])); break; case Format.Element.Type.UINT: data.Add(ReadUint(buffer)); break; case Format.Element.Type.INT: data.Add(ReadInt(buffer)); break; case Format.Element.Type.FLOAT: data.Add(ReadFloat(buffer)); break; case Format.Element.Type.TOKEN: data.Add(ReadToken(buffer)); break; case Format.Element.Type.STRING: data.Add(ReadString(buffer)); break; } } return(buffer); }
void Socket_OnData(object sender, EventSocket.DataEventArgs args) { // Store the data Cache.Concat(args.Data); // Try to read messages while (true) { int length; BufferView backup = new BufferView(Cache); try { // Extract the size of the message length = (int)InflateData.ReadUint(Cache); } catch (Exception e) { if (!(e is InflateData.NotEnoughData)) { ProtocolError(); } break; } if (Cache.Length < length) { Cache = backup; break; } ProcessMessage(Cache.ExtractSlice(length)); } }
/// <summary> /// Extract an array /// </summary> /// <param name="buffer">A view with the encoded data</param> /// <param name="format">A component of an inflated format object</param> /// <returns>Return the extracted data</returns> static ArrayList ReadArray(BufferView buffer, Format.ElementsArray format) { int length; // Get the number of elements length = (int)ReadUint(buffer); // Extract each element ArrayList array = new ArrayList(); if (format.Elements.Count == 1) { for (int i = 0; i < length; i++) { ReadElement(buffer, array, format); } } else { for (int i = 0; i < length; i++) { ArrayList subArray = new ArrayList(); ReadElement(buffer, subArray, format); array.Add(subArray); } } return(array); }
void ProcessReturn(uint callId, BufferView data) { PendingCall callInfo = FetchPendingCall(callId); if (callInfo == null) { // Received a timeouted (or invalid) answer ProtocolError(); return; } // Read the incoming data object inflatedData; try { inflatedData = InflateData.Inflate(data, callInfo.Call.ReturnFormat); } catch { ProtocolError(); return; } // Clear the timeout if (callInfo.Interval != null) { callInfo.Interval.Stop(); } // Call the callback if (callInfo.OnReturn != null) { callInfo.OnReturn(this, inflatedData); } }
/// <summary> /// Inflate the data with the given format stored in a buffer /// </summary> /// <param name="buffer">A view with the encoded data</param> /// <param name="format">An inflated format object</param> /// <returns>Return null, an ArrayList or a single value (ulong, long, float, Token or string)</returns> internal static object Inflate(BufferView buffer, Format format) { ArrayList data = new ArrayList(); if (InflateData.ReadElement(buffer, data, format.Root).Length != 0) throw new ArgumentException("Unable to read data in the given format"); return data.Count == 0 ? null : (data.Count == 1 ? data[0] : data); }
/// <summary> /// Inflate the data with the given format stored in a buffer /// </summary> /// <param name="buffer">A view with the encoded data</param> /// <param name="format">An inflated format object</param> /// <returns>Return null, an ArrayList or a single value (ulong, long, float, Token or string)</returns> internal static object Inflate(BufferView buffer, Format format) { ArrayList data = new ArrayList(); if (InflateData.ReadElement(buffer, data, format.Root).Length != 0) { throw new ArgumentException("Unable to read data in the given format"); } return(data.Count == 0 ? null : (data.Count == 1 ? data[0] : data)); }
/// <summary> /// Extract a Token /// </summary> /// <param name="buffer">A view with the encoded data</param> /// <returns>Return the extracted data</returns> static Token ReadToken(BufferView buffer) { if (buffer.Length < 16) { throw new NotEnoughData("Unable to extract Token"); } Token r = new Token(buffer.GetBytes(16)); buffer.Slice(16); return(r); }
/// <summary> /// Extract an unsigned integer /// </summary> /// <param name="buffer">A view with the encoded data</param> /// <returns>Return the extracted data</returns> internal static ulong ReadUint(BufferView buffer) { byte firstByte; int length, shifts; ulong u; // Get the first byte if (buffer.Length == 0) throw new NotEnoughData("Unable to extract unsigned integer"); firstByte = buffer[0]; // Get the total length and the first bits if (firstByte < Data.OFFSET_2_B) { // Fast path buffer.Slice(1); return (ulong)firstByte; } else if (firstByte < Data.OFFSET_3_B) { length = 1; u = (ulong)(firstByte & Data.MASK_6_B); } else if (firstByte < Data.OFFSET_4_B) { length = 2; u = (ulong)(firstByte & Data.MASK_5_B); } else if (firstByte < Data.OFFSET_5_B) { length = 3; u = (ulong)(firstByte & Data.MASK_4_B); } else if (firstByte < Data.OFFSET_6_B) { length = 4; u = (ulong)(firstByte & Data.MASK_3_B); } else if (firstByte < Data.OFFSET_7_B) { length = 5; u = (ulong)(firstByte & Data.MASK_2_B); } else if (firstByte < Data.OFFSET_8_B) { length = 6; u = (ulong)(firstByte & Data.MASK_1_B); } else if (firstByte == Data.OFFSET_8_B) { length = 7; u = 0; } else throw new InvalidOperationException("Unable to extract unsigned integer"); // Get the remaining bytes if (buffer.Length <= length) throw new NotEnoughData("Unable to extract unsigned integer"); shifts = 7 - length; for (int i = 1; i <= length; i++) { ulong temp = buffer[i]; u += temp << shifts; shifts += 8; } buffer.Slice(length + 1); return u; }
/// <summary> /// Extract initial bytes from this view /// </summary> /// <param name="size">The number of bytes to extract</param> /// <returns>Return a new BufferView with the desired number of bytes</returns> public BufferView ExtractSlice(int size) { if (size < 0 || size > Length) { throw new ArgumentException("Invalid size"); } BufferView r = new BufferView(Buffer, Offset, size); Offset += size; Length -= size; return(r); }
/// <summary> /// Extract a float /// </summary> /// <param name="buffer">A view with the encoded data</param> /// <returns>Return the extracted data</returns> static float ReadFloat(BufferView buffer) { if (buffer.Length < 4) { throw new NotEnoughData("Unable to extract float"); } byte[] temp = buffer.GetBytes(4); if (!BitConverter.IsLittleEndian) { Array.Reverse(temp); } buffer.Slice(4); return(BitConverter.ToSingle(temp, 0)); }
void ProcessException(uint callId, uint type, BufferView data) { PendingCall callInfo = FetchPendingCall(callId); if (callInfo == null) { // Received a timeouted (or invalid) answer ProtocolError(); return; } if (!callInfo.Call.HasException(type)) { // Received an invalid exception type ProtocolError(); return; } // Get exception definition Registry.RegisteredException exception = Registry.GetException(type); if (exception == null) { ProtocolError(); return; } // Read the incoming data object inflatedData; try { inflatedData = InflateData.Inflate(data, exception.DataFormat); } catch { ProtocolError(); return; } // Clear the timeout if (callInfo.Interval != null) { callInfo.Interval.Stop(); } // Call the callback if (callInfo.OnException != null) { callInfo.OnException(this, (int)type, inflatedData); } }
/// <summary> /// Extract a string /// </summary> /// <param name="buffer">A view with the encoded data</param> /// <returns>Return the extracted data</returns> static string ReadString(BufferView buffer) { int length; // Get the string length length = (int)ReadUint(buffer); if (buffer.Length < length) { throw new NotEnoughData("Unable to extract string"); } string r = Encoding.UTF8.GetString(buffer.GetBytes(length)); buffer.Slice(length); return(r); }
void ProcessMessage(BufferView message) { uint type, callId; // Extract the message type and sequence id try { type = (uint)InflateData.ReadUint(message); callId = (uint)InflateData.ReadUint(message); } catch { ProtocolError(); return; } if (type != 0) { // A call from the other side ProcessCall(callId, type, message); } else { try { type = (uint)InflateData.ReadUint(message); } catch { ProtocolError(); return; } if (type != 0) { // An exception from the other side ProcessException(callId, type, message); } else { // A return from the other side ProcessReturn(callId, message); } } }
/// <summary> /// Extract a Token /// </summary> /// <param name="buffer">A view with the encoded data</param> /// <returns>Return the extracted data</returns> static Token ReadToken(BufferView buffer) { if (buffer.Length < 16) throw new NotEnoughData("Unable to extract Token"); Token r = new Token(buffer.GetBytes(16)); buffer.Slice(16); return r; }
/// <summary> /// Extract initial bytes from this view /// </summary> /// <param name="size">The number of bytes to extract</param> /// <returns>Return a new BufferView with the desired number of bytes</returns> public BufferView ExtractSlice(int size) { if (size < 0 || size > Length) throw new ArgumentException("Invalid size"); BufferView r = new BufferView(Buffer, Offset, size); Offset += size; Length -= size; return r; }
/// <summary> /// Extract a string /// </summary> /// <param name="buffer">A view with the encoded data</param> /// <returns>Return the extracted data</returns> static string ReadString(BufferView buffer) { int length; // Get the string length length = (int)ReadUint(buffer); if (buffer.Length < length) throw new NotEnoughData("Unable to extract string"); string r = Encoding.UTF8.GetString(buffer.GetBytes(length)); buffer.Slice(length); return r; }
/// <summary> /// Extract a float /// </summary> /// <param name="buffer">A view with the encoded data</param> /// <returns>Return the extracted data</returns> static float ReadFloat(BufferView buffer) { if (buffer.Length < 4) throw new NotEnoughData("Unable to extract float"); byte[] temp = buffer.GetBytes(4); if (!BitConverter.IsLittleEndian) Array.Reverse(temp); buffer.Slice(4); return BitConverter.ToSingle(temp, 0); }
/// <summary> /// Extract a signed integer /// </summary> /// <param name="buffer">A view with the encoded data</param> /// <returns>Return the extracted data</returns> static long ReadInt(BufferView buffer) { byte firstByte; long i; int length, shifts; // Get the first byte if (buffer.Length == 0) throw new NotEnoughData("Unable to extract signed integer"); firstByte = buffer[0]; // Get the total length and the first bits if (firstByte < Data.OFFSET_2_B) { // Fast path buffer.Slice(1); return (long)firstByte + Data.MIN_INT_1_B; } else if (firstByte < Data.OFFSET_3_B) { length = 1; i = (long)(firstByte & Data.MASK_6_B) + Data.MIN_INT_2_B; } else if (firstByte < Data.OFFSET_4_B) { length = 2; i = (long)(firstByte & Data.MASK_5_B) + Data.MIN_INT_3_B; } else if (firstByte < Data.OFFSET_5_B) { length = 3; i = (long)(firstByte & Data.MASK_4_B) + Data.MIN_INT_4_B; } else if (firstByte < Data.OFFSET_6_B) { length = 4; i = (long)(firstByte & Data.MASK_3_B) + Data.MIN_INT_5_B; } else if (firstByte < Data.OFFSET_7_B) { length = 5; i = (long)(firstByte & Data.MASK_2_B) + Data.MIN_INT_6_B; } else if (firstByte < Data.OFFSET_8_B) { length = 6; i = (long)(firstByte & Data.MASK_1_B) + Data.MIN_INT_7_B; } else if (firstByte == Data.OFFSET_8_B) { length = 7; i = Data.MIN_INT_8_B; } else throw new InvalidOperationException("Unable to extract signed integer"); // Get the remaining bytes if (buffer.Length <= length) throw new NotEnoughData("Unable to extract signed integer"); shifts = 7 - length; for (int j = 1; j <= length; j++) { long temp = buffer[j]; i += temp << shifts; shifts += 8; } buffer.Slice(length + 1); return i; }
void Socket_OnData(object sender, EventSocket.DataEventArgs args) { // Store the data Cache.Concat(args.Data); // Try to read messages while (true) { int length; BufferView backup = new BufferView(Cache); try { // Extract the size of the message length = (int)InflateData.ReadUint(Cache); } catch (Exception e) { if (!(e is InflateData.NotEnoughData)) ProtocolError(); break; } if (Cache.Length < length) { Cache = backup; break; } ProcessMessage(Cache.ExtractSlice(length)); } }
/// <summary> /// Extract a single element from the view /// </summary> /// <param name="buffer">A view with the encoded data</param> /// <param name="data">The data ArrayList to store the extracted data</param> /// <param name="format">The format of the data to be extracted</param> /// <returns>Return the view parameter</returns> static BufferView ReadElement(BufferView buffer, ArrayList data, Format.ElementsArray format) { for (int i = 0; i < format.Elements.Count; i++) { switch (format.Elements[i].ElementType) { case Format.Element.Type.ARRAY: data.Add(ReadArray(buffer, (Format.ElementsArray)format.Elements[i])); break; case Format.Element.Type.UINT: data.Add(ReadUint(buffer)); break; case Format.Element.Type.INT: data.Add(ReadInt(buffer)); break; case Format.Element.Type.FLOAT: data.Add(ReadFloat(buffer)); break; case Format.Element.Type.TOKEN: data.Add(ReadToken(buffer)); break; case Format.Element.Type.STRING: data.Add(ReadString(buffer)); break; } } return buffer; }
void ProcessMessage(BufferView message) { uint type, callId; // Extract the message type and sequence id try { type = (uint)InflateData.ReadUint(message); callId = (uint)InflateData.ReadUint(message); } catch { ProtocolError(); return; } if (type != 0) // A call from the other side ProcessCall(callId, type, message); else { try { type = (uint)InflateData.ReadUint(message); } catch { ProtocolError(); return; } if (type != 0) // An exception from the other side ProcessException(callId, type, message); else // A return from the other side ProcessReturn(callId, message); } }
void ProcessReturn(uint callId, BufferView data) { PendingCall callInfo = FetchPendingCall(callId); if (callInfo == null) { // Received a timeouted (or invalid) answer ProtocolError(); return; } // Read the incoming data object inflatedData; try { inflatedData = InflateData.Inflate(data, callInfo.Call.ReturnFormat); } catch { ProtocolError(); return; } // Clear the timeout if (callInfo.Interval != null) callInfo.Interval.Stop(); // Call the callback if (callInfo.OnReturn != null) callInfo.OnReturn(this, inflatedData); }
void ProcessException(uint callId, uint type, BufferView data) { PendingCall callInfo = FetchPendingCall(callId); if (callInfo == null) { // Received a timeouted (or invalid) answer ProtocolError(); return; } if (!callInfo.Call.HasException(type)) { // Received an invalid exception type ProtocolError(); return; } // Get exception definition Registry.RegisteredException exception = Registry.GetException(type); if (exception == null) { ProtocolError(); return; } // Read the incoming data object inflatedData; try { inflatedData = InflateData.Inflate(data, exception.DataFormat); } catch { ProtocolError(); return; } // Clear the timeout if (callInfo.Interval != null) callInfo.Interval.Stop(); // Call the callback if (callInfo.OnException != null) callInfo.OnException(this, (int)type, inflatedData); }
void ProcessCall(uint callId, uint type, BufferView data) { object inflatedData; // Check the sequence id if (callId != ++LastReceivedId) { ProtocolError(); return; } // Get call definition Registry.RegisteredCall call = Registry.GetServerCall(type); if (call == null) { ProtocolError(); return; } // Read the incoming data try { inflatedData = InflateData.Inflate(data, call.ArgsFormat); } catch { ProtocolError(); return; } // Emit the "call" event if (OnCall != null) OnCall(this, new CallEventArgs(call, inflatedData, this, callId)); }
/// <summary> /// Clone a given view /// </summary> /// <param name="buffer">The old object to clone</param> public BufferView(BufferView buffer) : this(buffer.Buffer, buffer.Offset, buffer.Length) { }
/// <summary> /// Clone a given view /// </summary> /// <param name="buffer">The old object to clone</param> public BufferView(BufferView buffer) : this(buffer.Buffer, buffer.Offset, buffer.Length) { }
/// <summary> /// Extract a signed integer /// </summary> /// <param name="buffer">A view with the encoded data</param> /// <returns>Return the extracted data</returns> static long ReadInt(BufferView buffer) { byte firstByte; long i; int length, shifts; // Get the first byte if (buffer.Length == 0) { throw new NotEnoughData("Unable to extract signed integer"); } firstByte = buffer[0]; // Get the total length and the first bits if (firstByte < Data.OFFSET_2_B) { // Fast path buffer.Slice(1); return((long)firstByte + Data.MIN_INT_1_B); } else if (firstByte < Data.OFFSET_3_B) { length = 1; i = (long)(firstByte & Data.MASK_6_B) + Data.MIN_INT_2_B; } else if (firstByte < Data.OFFSET_4_B) { length = 2; i = (long)(firstByte & Data.MASK_5_B) + Data.MIN_INT_3_B; } else if (firstByte < Data.OFFSET_5_B) { length = 3; i = (long)(firstByte & Data.MASK_4_B) + Data.MIN_INT_4_B; } else if (firstByte < Data.OFFSET_6_B) { length = 4; i = (long)(firstByte & Data.MASK_3_B) + Data.MIN_INT_5_B; } else if (firstByte < Data.OFFSET_7_B) { length = 5; i = (long)(firstByte & Data.MASK_2_B) + Data.MIN_INT_6_B; } else if (firstByte < Data.OFFSET_8_B) { length = 6; i = (long)(firstByte & Data.MASK_1_B) + Data.MIN_INT_7_B; } else if (firstByte == Data.OFFSET_8_B) { length = 7; i = Data.MIN_INT_8_B; } else { throw new InvalidOperationException("Unable to extract signed integer"); } // Get the remaining bytes if (buffer.Length <= length) { throw new NotEnoughData("Unable to extract signed integer"); } shifts = 7 - length; for (int j = 1; j <= length; j++) { long temp = buffer[j]; i += temp << shifts; shifts += 8; } buffer.Slice(length + 1); return(i); }
/// <summary> /// Extract an array /// </summary> /// <param name="buffer">A view with the encoded data</param> /// <param name="format">A component of an inflated format object</param> /// <returns>Return the extracted data</returns> static ArrayList ReadArray(BufferView buffer, Format.ElementsArray format) { int length; // Get the number of elements length = (int)ReadUint(buffer); // Extract each element ArrayList array = new ArrayList(); if (format.Elements.Count == 1) for (int i = 0; i < length; i++) ReadElement(buffer, array, format); else for (int i = 0; i < length; i++) { ArrayList subArray = new ArrayList(); ReadElement(buffer, subArray, format); array.Add(subArray); } return array; }
/// <summary> /// Extract an unsigned integer /// </summary> /// <param name="buffer">A view with the encoded data</param> /// <returns>Return the extracted data</returns> internal static ulong ReadUint(BufferView buffer) { byte firstByte; int length, shifts; ulong u; // Get the first byte if (buffer.Length == 0) { throw new NotEnoughData("Unable to extract unsigned integer"); } firstByte = buffer[0]; // Get the total length and the first bits if (firstByte < Data.OFFSET_2_B) { // Fast path buffer.Slice(1); return((ulong)firstByte); } else if (firstByte < Data.OFFSET_3_B) { length = 1; u = (ulong)(firstByte & Data.MASK_6_B); } else if (firstByte < Data.OFFSET_4_B) { length = 2; u = (ulong)(firstByte & Data.MASK_5_B); } else if (firstByte < Data.OFFSET_5_B) { length = 3; u = (ulong)(firstByte & Data.MASK_4_B); } else if (firstByte < Data.OFFSET_6_B) { length = 4; u = (ulong)(firstByte & Data.MASK_3_B); } else if (firstByte < Data.OFFSET_7_B) { length = 5; u = (ulong)(firstByte & Data.MASK_2_B); } else if (firstByte < Data.OFFSET_8_B) { length = 6; u = (ulong)(firstByte & Data.MASK_1_B); } else if (firstByte == Data.OFFSET_8_B) { length = 7; u = 0; } else { throw new InvalidOperationException("Unable to extract unsigned integer"); } // Get the remaining bytes if (buffer.Length <= length) { throw new NotEnoughData("Unable to extract unsigned integer"); } shifts = 7 - length; for (int i = 1; i <= length; i++) { ulong temp = buffer[i]; u += temp << shifts; shifts += 8; } buffer.Slice(length + 1); return(u); }