/// <summary> /// Receives the data. /// </summary> /// <returns></returns> private byte[] ReceiveData() { byte[] frameHeader = new byte[8]; if (!FillBuffer(frameHeader, 0)) { if (this.OnError != null) { var connWasLostEx = new Exception("Connection was lost!"); this.OnError(this, new ProtocolErrorEventArgs(connWasLostEx)); } } byte[] frameBytes = new byte[0]; int frameLenInBytes = 8 + BinaryHelper.Int32FromBytes(new ArraySegment <byte>(frameHeader, 5, 3)); frameBytes = new byte[frameLenInBytes]; Buffer.BlockCopy(frameHeader, 0, frameBytes, 0, frameHeader.Length); if (!FillBuffer(frameBytes, 8)) { if (this.OnError != null) { var connWasLostEx = new Exception("Connection was lost!"); this.OnError(this, new ProtocolErrorEventArgs(connWasLostEx)); } } return(frameBytes); }
/// <summary> /// Parses HTTP headers of Http2 control frame. /// </summary> /// <param name="frame">The frame.</param> /// <param name="data">The data.</param> /// <param name="offset">Offset of HTTP headers in the data.</param> private void ParseControlFrameHeaders(ref ControlFrame frame, byte[] data, int offset) { var headers = new byte[data.Length - offset]; Array.Copy(data, offset, headers, 0, headers.Length); if (headers.Length > 0) { ProcessorRun(ref headers, DirectionProcessType.Inbound, frame.Flags); } int headersOffset = 0; int numberOfKeyValue = BinaryHelper.Int32FromBytes(new ArraySegment <byte>(headers, headersOffset, 4)); headersOffset += 4; for (int i = 0; i < numberOfKeyValue; ++i) { int nameLength = BinaryHelper.Int32FromBytes(new ArraySegment <byte>(headers, headersOffset, 4)); headersOffset += 4; string name = Encoding.UTF8.GetString(headers, headersOffset, nameLength); headersOffset += nameLength; int valLength = BinaryHelper.Int32FromBytes(new ArraySegment <byte>(headers, headersOffset, 4)); headersOffset += 4; string val = Encoding.UTF8.GetString(headers, headersOffset, valLength); headersOffset += valLength; // Ensure no duplicates. if (frame.Headers.ContainsKey(name)) { throw new ProtocolExeption(StatusCode.InternalError); } frame.Headers.Add(name, val); } }
/// <summary> /// Deserializes the Http2 Close Extension Data. /// </summary> /// <param name="data">The data.</param> /// <returns>Deserialized Extension Data.</returns> public CloseFrameExt DeserializeCloseFrameExt(byte[] data) { var extData = new CloseFrameExt(); extData.StatusCode = BinaryHelper.Int16FromBytes(data[0], data[1], 0); extData.LastGoodSessionId = BinaryHelper.Int32FromBytes(new ArraySegment <byte>(data, 2, 4)); return(extData); }
/// <summary> /// Parses HTTP header of Http2 control frame. /// </summary> /// <param name="frame">The frame.</param> /// <param name="data">The data.</param> private static void ParseControlFrameHeader(ref ControlFrame frame, byte[] data) { frame.Version = BinaryHelper.Int16FromBytes(data[0], data[1], 1); frame.Type = (FrameType)BinaryHelper.Int16FromBytes(data[2], data[3]); frame.Flags = data[4]; // it would be always 4 th byte for flags in spec. frame.Length = BinaryHelper.Int32FromBytes(new ArraySegment <byte>(data, 5, 3)); frame.IsFinal = (frame.Flags & 0x01) != 0; }
/// <summary> /// Parses HTTP header of Http2 data frame. /// </summary> /// <param name="frame">The frame.</param> /// <param name="data">The data.</param> private static void ParseDataFrameHeader(ref DataFrame frame, byte[] data) { frame.StreamId = BinaryHelper.Int32FromBytes(new ArraySegment <byte>(data, 0, 4), 0); frame.Flags = data[4]; frame.IsFinal = (frame.Flags & 0x01) != 0; }
/// <summary> /// Deserializes the data into control frame. /// </summary> /// <param name="data">The data.</param> /// <returns>Deserialized frame.</returns> private BaseFrame DeserializeControlFrame(byte[] data) { FrameType type = GetFrameType(data); ControlFrame frame = new ControlFrame(); switch (type) { case FrameType.RTS: frame.StreamId = BinaryHelper.Int32FromBytes(new ArraySegment <byte>(data, 8, 4)); frame.StatusCode = (StatusCode)BinaryHelper.Int32FromBytes(new ArraySegment <byte>(data, 12, 4)); break; case FrameType.Headers: case FrameType.SynReply: ParseControlFrameHeader(ref frame, data); frame.StreamId = BinaryHelper.Int32FromBytes(new ArraySegment <byte>(data, 8, 4)); ParseControlFrameHeaders(ref frame, data, 12); break; case FrameType.SynStream: ParseControlFrameHeader(ref frame, data); frame.StreamId = BinaryHelper.Int32FromBytes(new ArraySegment <byte>(data, 8, 4)); frame.AssociatedToStreamId = BinaryHelper.Int32FromBytes(new ArraySegment <byte>(data, 12, 4)); frame.Priority = (byte)(data[16] >> 5); frame.Slot = data[17]; ParseControlFrameHeaders(ref frame, data, 18); break; case FrameType.Settings: int numberOfEntries = BinaryHelper.Int32FromBytes(new ArraySegment <byte>(data, 8, 4)); frame = new SettingsFrame(numberOfEntries); int headersOffset = 12; for (int i = 0; i < numberOfEntries; i++) { int key = BinaryHelper.Int32FromBytes(new ArraySegment <byte>(data, headersOffset, 4)); headersOffset += 4; int value = BinaryHelper.Int32FromBytes(new ArraySegment <byte>(data, headersOffset, 4)); headersOffset += 4; frame.SettingsHeaders.Add(key, value); } ParseControlFrameHeader(ref frame, data); break; case FrameType.GoAway: int lastSeenGoodStreamId = BinaryHelper.Int32FromBytes(new ArraySegment <byte>(data, 8, 4)); StatusCode status = StatusCode.Success; if (data.Length > 12) { status = (StatusCode)BinaryHelper.Int32FromBytes(new ArraySegment <byte>(data, 12, 4)); } frame = new GoAwayFrame(lastSeenGoodStreamId, status); ParseControlFrameHeader(ref frame, data); break; case FrameType.Ping: int streamID = BinaryHelper.Int32FromBytes(new ArraySegment <byte>(data, 4, 4)); frame = new ControlFrame { StreamId = streamID }; ParseControlFrameHeader(ref frame, data); break; case FrameType.WindowUpdate: int streamId = BinaryHelper.Int32FromBytes(new ArraySegment <byte>(data, 4, 4)); int deltaWindowSize = BinaryHelper.Int32FromBytes(new ArraySegment <byte>(data, 8, 4)); frame = new WindowUpdateFrame(streamId, deltaWindowSize); ParseControlFrameHeader(ref frame, data); break; } frame.Type = type; return(frame); }