Пример #1
0
        public const int SettingSize = 6; // 2 bytes for the id, 4 bytes for the value.

        public static bool ReadFrame(ReadOnlySequence <byte> readableBuffer, Proto2Frame frame, uint maxFrameSize, out ReadOnlySequence <byte> framePayload)
        {
            framePayload = ReadOnlySequence <byte> .Empty;

            if (readableBuffer.Length < HeaderLength)
            {
                return(false);
            }

            var headerSlice = readableBuffer.Slice(0, HeaderLength);
            var header      = headerSlice.ToSpan();

            var payloadLength = (int)Bitshifter.ReadUInt24BigEndian(header);

            if (payloadLength > maxFrameSize)
            {
                throw new Proto2ConnectionErrorException(CoreStrings.FormatProto2ErrorFrameOverLimit(payloadLength, maxFrameSize), Proto2ErrorCode.FRAME_SIZE_ERROR);
            }

            // Make sure the whole frame is buffered
            var frameLength = HeaderLength + payloadLength;

            if (readableBuffer.Length < frameLength)
            {
                return(false);
            }

            frame.PayloadLength = payloadLength;
            frame.Type          = (Proto2FrameType)header[TypeOffset];
            frame.Flags         = header[FlagsOffset];
            frame.StreamId      = (int)Bitshifter.ReadUInt31BigEndian(header.Slice(StreamIdOffset));

            var extendedHeaderLength = ReadExtendedFields(frame, readableBuffer);

            // The remaining payload minus the extra fields
            framePayload = readableBuffer.Slice(HeaderLength + extendedHeaderLength, payloadLength - extendedHeaderLength);

            return(true);
        }
Пример #2
0
        private static int ReadExtendedFields(Proto2Frame frame, ReadOnlySequence <byte> readableBuffer)
        {
            // Copy in any extra fields for the given frame type
            var extendedHeaderLength = GetPayloadFieldsLength(frame);

            if (extendedHeaderLength > frame.PayloadLength)
            {
                throw new Proto2ConnectionErrorException(
                          CoreStrings.FormatProto2ErrorUnexpectedFrameLength(frame.Type, expectedLength: extendedHeaderLength), Proto2ErrorCode.FRAME_SIZE_ERROR);
            }

            var extendedHeaders = readableBuffer.Slice(HeaderLength, extendedHeaderLength).ToSpan();

            // Parse frame type specific fields
            switch (frame.Type)
            {
            /*
             +---------------+
             |Pad Length? (8)|
             +---------------+-----------------------------------------------+
             |                            Data (*)                         ...
             +---------------------------------------------------------------+
             |                           Padding (*)                       ...
             +---------------------------------------------------------------+
             */
            case Proto2FrameType.DATA:     // Variable 0 or 1
                frame.DataPadLength = frame.DataHasPadding ? extendedHeaders[0] : (byte)0;
                break;

            /* https://tools.ietf.org/html/rfc7540#section-6.2
             +---------------+
             |Pad Length? (8)|
             +-+-------------+-----------------------------------------------+
             |E|                 Stream Dependency? (31)                     |
             +-+-------------+-----------------------------------------------+
             |  Weight? (8)  |
             +-+-------------+-----------------------------------------------+
             |                   Header Block Fragment (*)                 ...
             +---------------------------------------------------------------+
             |                           Padding (*)                       ...
             +---------------------------------------------------------------+
             */
            case Proto2FrameType.HEADERS:
                if (frame.HeadersHasPadding)
                {
                    frame.HeadersPadLength = extendedHeaders[0];
                    extendedHeaders        = extendedHeaders.Slice(1);
                }
                else
                {
                    frame.HeadersPadLength = 0;
                }

                if (frame.HeadersHasPriority)
                {
                    frame.HeadersStreamDependency = (int)Bitshifter.ReadUInt31BigEndian(extendedHeaders);
                    frame.HeadersPriorityWeight   = extendedHeaders.Slice(4)[0];
                }
                else
                {
                    frame.HeadersStreamDependency = 0;
                    frame.HeadersPriorityWeight   = 0;
                }
                break;

            /* https://tools.ietf.org/html/rfc7540#section-6.8
             +-+-------------------------------------------------------------+
             |R|                  Last-Stream-ID (31)                        |
             +-+-------------------------------------------------------------+
             |                      Error Code (32)                          |
             +---------------------------------------------------------------+
             |                  Additional Debug Data (*)                    |
             +---------------------------------------------------------------+
             */
            case Proto2FrameType.GOAWAY:
                frame.GoAwayLastStreamId = (int)Bitshifter.ReadUInt31BigEndian(extendedHeaders);
                frame.GoAwayErrorCode    = (Proto2ErrorCode)BinaryPrimitives.ReadUInt32BigEndian(extendedHeaders.Slice(4));
                break;

            /* https://tools.ietf.org/html/rfc7540#section-6.3
             +-+-------------------------------------------------------------+
             |E|                  Stream Dependency (31)                     |
             +-+-------------+-----------------------------------------------+
             |   Weight (8)  |
             +-+-------------+
             */
            case Proto2FrameType.PRIORITY:
                frame.PriorityStreamDependency = (int)Bitshifter.ReadUInt31BigEndian(extendedHeaders);
                frame.PriorityWeight           = extendedHeaders.Slice(4)[0];
                break;

            /* https://tools.ietf.org/html/rfc7540#section-6.4
             +---------------------------------------------------------------+
             |                        Error Code (32)                        |
             +---------------------------------------------------------------+
             */
            case Proto2FrameType.RST_STREAM:
                frame.RstStreamErrorCode = (Proto2ErrorCode)BinaryPrimitives.ReadUInt32BigEndian(extendedHeaders);
                break;

            /* https://tools.ietf.org/html/rfc7540#section-6.9
             +-+-------------------------------------------------------------+
             |R|              Window Size Increment (31)                     |
             +-+-------------------------------------------------------------+
             */
            case Proto2FrameType.WINDOW_UPDATE:
                frame.WindowUpdateSizeIncrement = (int)Bitshifter.ReadUInt31BigEndian(extendedHeaders);
                break;

            case Proto2FrameType.PING:         // Opaque payload 8 bytes long
            case Proto2FrameType.SETTINGS:     // Settings are general payload
            case Proto2FrameType.CONTINUATION: // None
            case Proto2FrameType.PUSH_PROMISE: // Not implemented frames are ignored at this phase
            default:
                return(0);
            }

            return(extendedHeaderLength);
        }