Beispiel #1
0
        private async Task EncodeResetFrameAsync(EncodingContext context, HttpFrame frame)
        {
            if (context.FreeBytesLeftInBuffer < 4 + HeaderSize)
            {
                await context.SendAsync();
            }

            var resetFrame = (ResetStream)frame;

            AddHeader(context, frame.FrameType, 0, 4, frame.StreamIdentifier);
            context.Buffer[context.Offset++] = (byte)resetFrame.ErrorCode;
            context.Buffer[context.Offset++] = (byte)(resetFrame.ErrorCode & 0xff00);
            context.Buffer[context.Offset++] = (byte)(resetFrame.ErrorCode & 0xff0000);
            context.Buffer[context.Offset++] = (byte)(resetFrame.ErrorCode & 0xff000000);
            context.FreeBytesLeftInBuffer   -= 4;
        }
Beispiel #2
0
        private async Task EncodePriorityFrameAsync(EncodingContext context, HttpFrame frame)
        {
            if (context.FreeBytesLeftInBuffer < 5 + HeaderSize)
            {
                await context.SendAsync();
            }

            var prioFrame = (PriorityFrame)frame;

            AddHeader(context, frame.FrameType, 0, 5, frame.StreamIdentifier);
            context.Buffer[context.Offset++] = (byte)prioFrame.DependencyStreamId;
            context.Buffer[context.Offset++] = (byte)(prioFrame.DependencyStreamId & 0xff00);
            context.Buffer[context.Offset++] = (byte)(prioFrame.DependencyStreamId & 0xff0000);
            context.Buffer[context.Offset++] = (byte)(prioFrame.DependencyStreamId & 0xff000000);
            context.Buffer[context.Offset++] = (byte)prioFrame.Weight;
            context.FreeBytesLeftInBuffer   -= 5;
        }
Beispiel #3
0
        private async Task EncodeDataFrameAsync(EncodingContext context, HttpFrame frame)
        {
            var dataFrame = (DataFrame)frame;
            var flags     = dataFrame.IsEndOfStream ? 1 : 0;

            AddHeader(context, frame.FrameType, flags, (int)dataFrame.Data.Length, frame.StreamIdentifier);
            while (true)
            {
                var read = dataFrame.Data.Read(context.Buffer, context.Offset, context.FreeBytesLeftInBuffer);
                if (read == 0)
                {
                    break;
                }


                context.Offset += read;
                context.FreeBytesLeftInBuffer -= read;
                if (context.FreeBytesLeftInBuffer == 0)
                {
                    await context.SendAsync();
                }
            }
        }
Beispiel #4
0
        public async Task EncodeAsync(HttpFrame frame)
        {
            if (_context.FreeBytesLeftInBuffer < HeaderSize)
            {
                await _context.SendAsync();
            }


            int payloadLength = _context.Buffer[_context.Offset++];

            payloadLength += _context.Buffer[_context.Offset++] << 4;
            payloadLength += _context.Buffer[_context.Offset++] << 8;
            if (payloadLength > MaxFrameSize)
            {
                throw new EncoderException(Http2ErrorCode.FrameSizeError,
                                           $"Received HTTP frame have size {payloadLength} while this server allows maximum {MaxFrameSize} bytes.");
            }

            var type             = _context.Buffer[_context.Offset++];
            var flags            = _context.Buffer[_context.Offset++];
            var streamIdentifier = BitConverter.ToInt32(_context.Buffer, _context.Offset) & ~Bit32;

            _context.FreeBytesLeftInBuffer -= HeaderSize;

            switch (type)
            {
            case 0:
                await EncodeDataFrameAsync(_context, frame);

                break;

            case 1:
                await EncodeHeaderFrameAsync(_context, frame);

                break;

            case 2:
                await EncodePriorityFrameAsync(_context, frame);

                break;

            case 3:
                await EncodeResetFrameAsync(_context, frame);

                break;

            //case 4:
            //    return EncodeSettingsFrameAsync(_context, frame);
            //case 5:
            //    return EncodePushPromiseAsync(_context, frame);
            //case 6:
            //    return EncodePingAsync(_context, frame);
            //case 7:
            //    return EncodeGoAwayAsync(_context, frame);
            //case 8:
            //    return EncodeWindowUpdateAsync(_context, frame);
            case 9:
                throw new NotSupportedException("Delegate should ahve handled this");

            default:
                IFrameEncoder decoder;
                if (!_extraEncoders.TryGetValue(type, out decoder))
                {
                    return;
                }
                await decoder.EncodeAsync(_context, frame);

                break;
            }
        }
Beispiel #5
0
        private async Task EncodeHeaderFrameAsync(EncodingContext context, HttpFrame frame)
        {
            var headerFrame = (HeaderFrame)frame;

            var headerOffset = context.Offset;

            context.Offset += HeaderSize;

            var startOffset = context.Offset;

            foreach (var header in headerFrame)
            {
                //frame header(9) + padLength + streamDependency(4) + weight + header block extras (4)
                var size = header.Name.Length + header.Value.Length + 19;
                if (context.FreeBytesLeftInBuffer < size)
                {
                    var flags2         = frame.IsEndOfStream ? 1 : 0;
                    var payloadLength2 = context.Offset - startOffset;
                    context.Buffer[headerOffset]     = (byte)(payloadLength2 & (1 << 8));
                    context.Buffer[headerOffset + 1] = (byte)(payloadLength2 & (1 << 16));
                    context.Buffer[headerOffset + 2] = (byte)(payloadLength2 & (1 << 24));
                    context.Buffer[headerOffset + 3] = frame.FrameType;
                    context.Buffer[headerOffset + 4] = (byte)flags2;
                    context.Buffer[headerOffset + 5] = (byte)(frame.StreamIdentifier & (1 << 8));
                    context.Buffer[headerOffset + 6] = (byte)(frame.StreamIdentifier & (1 << 16));
                    context.Buffer[headerOffset + 7] = (byte)(frame.StreamIdentifier & (1 << 24));
                    context.Buffer[headerOffset + 8] = (byte)(frame.StreamIdentifier & (1 << 32));
                    await context.SendAsync();

                    startOffset  = context.Offset + HeaderSize;
                    headerOffset = context.Offset;
                }



                if (header.ContainsSensitiveData)
                {
                    _headerEncoder.EncodeSensitive(header.Name, header.Value, context.Buffer, ref context.Offset, ref context.FreeBytesLeftInBuffer);
                }
                else if (!header.IsIndexingAllowed)
                {
                    _headerEncoder.EncodeWithoutIndexing(header.Name, header.Value, context.Buffer, ref context.Offset, ref context.FreeBytesLeftInBuffer);
                }
                else
                {
                    _headerEncoder.Encode(header.Name, header.Value, context.Buffer, ref context.Offset, ref context.FreeBytesLeftInBuffer);
                }
            }


            //4 = END_HEADERS
            var flags         = frame.IsEndOfStream ? 5 : 4;
            var payloadLength = context.Offset - startOffset;

            context.Buffer[headerOffset]     = (byte)payloadLength;
            context.Buffer[headerOffset + 1] = (byte)(payloadLength & 0xff00);
            context.Buffer[headerOffset + 2] = (byte)(payloadLength & 0xff0000);
            context.Buffer[headerOffset + 3] = frame.FrameType;
            context.Buffer[headerOffset + 4] = (byte)flags;
            context.Buffer[headerOffset + 5] = (byte)frame.StreamIdentifier;
            context.Buffer[headerOffset + 6] = (byte)(frame.StreamIdentifier & 0xff00);
            context.Buffer[headerOffset + 7] = (byte)(frame.StreamIdentifier & 0xff0000);
            context.Buffer[headerOffset + 8] = (byte)(frame.StreamIdentifier & 0xff000000);
            await context.SendAsync();
        }