Exemplo n.º 1
0
        /// <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);
        }