예제 #1
0
        /* https://tools.ietf.org/html/rfc7540#section-6.2
         +-+-------------+-----------------------------------------------+
         |E|                 Stream Dependency? (31)                     |
         +-+-------------+-----------------------------------------------+
         |  Weight? (8)  |
         +-+-------------+-----------------------------------------------+
         |                   Header Block Fragment (*)                 ...
         +---------------------------------------------------------------+
         */
        public Task SendHeadersWithPriorityAsync(int streamId, IEnumerable <KeyValuePair <string, string> > headers, byte priority, int streamDependency, bool endStream)
        {
            var writableBuffer = _pair.Application.Output;
            var tcs            = new TaskCompletionSource <object>(TaskCreationOptions.RunContinuationsAsynchronously);

            var frame = new Http2Frame();

            frame.PrepareHeaders(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.PRIORITY, streamId);
            frame.HeadersPriorityWeight   = priority;
            frame.HeadersStreamDependency = streamDependency;

            var extendedHeaderLength = 5; // stream dependency + weight
            var buffer         = _headerEncodingBuffer.AsSpan();
            var extendedHeader = buffer.Slice(0, extendedHeaderLength);

            Bitshifter.WriteUInt31BigEndian(extendedHeader, (uint)streamDependency);
            extendedHeader[4] = priority;
            var payload = buffer.Slice(extendedHeaderLength);

            _hpackEncoder.BeginEncode(headers, payload, out var length);

            frame.PayloadLength = extendedHeaderLength + length;

            if (endStream)
            {
                frame.HeadersFlags |= Http2HeadersFrameFlags.END_STREAM;
            }

            Http2FrameWriter.WriteHeader(frame, writableBuffer);
            writableBuffer.Write(buffer.Slice(0, frame.PayloadLength));
            return(FlushAsync(writableBuffer));
        }
예제 #2
0
        /* https://tools.ietf.org/html/rfc7540#section-6.2
         +---------------+
         |Pad Length? (8)|
         +-+-------------+-----------------------------------------------+
         |                   Header Block Fragment (*)                 ...
         +---------------------------------------------------------------+
         |                           Padding (*)                       ...
         +---------------------------------------------------------------+
         */
        public Task SendHeadersWithPaddingAsync(int streamId, IEnumerable <KeyValuePair <string, string> > headers, byte padLength, bool endStream)
        {
            var writableBuffer = _pair.Application.Output;
            var tcs            = new TaskCompletionSource <object>(TaskCreationOptions.RunContinuationsAsynchronously);

            var frame = new Http2Frame();

            frame.PrepareHeaders(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.PADDED, streamId);
            frame.HeadersPadLength = padLength;

            var extendedHeaderLength = 1; // Padding length field
            var buffer         = _headerEncodingBuffer.AsSpan();
            var extendedHeader = buffer.Slice(0, extendedHeaderLength);

            extendedHeader[0] = padLength;
            var payload = buffer.Slice(extendedHeaderLength, buffer.Length - padLength - extendedHeaderLength);

            _hpackEncoder.BeginEncode(headers, payload, out var length);
            var padding = buffer.Slice(extendedHeaderLength + length, padLength);

            padding.Fill(0);

            frame.PayloadLength = extendedHeaderLength + length + padLength;

            if (endStream)
            {
                frame.HeadersFlags |= Http2HeadersFrameFlags.END_STREAM;
            }

            Http2FrameWriter.WriteHeader(frame, writableBuffer);
            writableBuffer.Write(buffer.Slice(0, frame.PayloadLength));
            return(FlushAsync(writableBuffer));
        }
예제 #3
0
 public static void WriteWindowUpdateAsync(this PipeWriter writer, int streamId, int sizeIncrement, Http2Frame frame = null)
 {
     frame ??= new Http2Frame();
     frame.PrepareWindowUpdate(streamId, sizeIncrement);
     Http2FrameWriter.WriteHeader(frame, writer);
     BinaryPrimitives.WriteUInt32BigEndian(writer.GetSpan(4), (uint)sizeIncrement);
     writer.Advance(4);
 }
예제 #4
0
        public Task SendGoAwayAsync()
        {
            var outputWriter = _pair.Application.Output;
            var frame        = new Http2Frame();

            frame.PrepareGoAway(0, Http2ErrorCode.NO_ERROR);
            Http2FrameWriter.WriteHeader(frame, outputWriter);
            return(SendAsync(new byte[frame.PayloadLength]));
        }
예제 #5
0
        internal Task SendPingAsync(Http2PingFrameFlags flags)
        {
            var outputWriter = _pair.Application.Output;
            var pingFrame    = new Http2Frame();

            pingFrame.PreparePing(flags);
            Http2FrameWriter.WriteHeader(pingFrame, outputWriter);
            return(SendAsync(new byte[8])); // Empty payload
        }
예제 #6
0
        public Task SendInvalidWindowUpdateAsync(int streamId, int sizeIncrement, int length)
        {
            var outputWriter = _pair.Application.Output;
            var frame        = new Http2Frame();

            frame.PrepareWindowUpdate(streamId, sizeIncrement);
            frame.PayloadLength = length;
            Http2FrameWriter.WriteHeader(frame, outputWriter);
            return(SendAsync(new byte[length]));
        }
예제 #7
0
    public static void WriteData(this PipeWriter writer, int streamId, Memory <byte> data, bool endStream, Http2Frame frame = null)
    {
        frame ??= new Http2Frame();
        frame.PrepareData(streamId);
        frame.PayloadLength = data.Length;
        frame.DataFlags     = endStream ? Http2DataFrameFlags.END_STREAM : Http2DataFrameFlags.NONE;

        Http2FrameWriter.WriteHeader(frame, writer);
        writer.Write(data.Span);
    }
예제 #8
0
        public Task SendPingWithInvalidLengthAsync(int length)
        {
            var outputWriter = _pair.Application.Output;
            var pingFrame    = new Http2Frame();

            pingFrame.PreparePing(Http2PingFrameFlags.NONE);
            pingFrame.PayloadLength = length;
            Http2FrameWriter.WriteHeader(pingFrame, outputWriter);
            return(SendAsync(new byte[length]));
        }
예제 #9
0
        public async Task SendSettingsAckWithInvalidLengthAsync(int length)
        {
            var writableBuffer = _pair.Application.Output;
            var frame          = new Http2Frame();

            frame.PrepareSettings(Http2SettingsFrameFlags.ACK);
            frame.PayloadLength = length;
            Http2FrameWriter.WriteHeader(frame, writableBuffer);
            await SendAsync(new byte[length]);
        }
예제 #10
0
        public Task SendInvalidRstStreamFrameAsync(int streamId, int length)
        {
            var outputWriter = _pair.Application.Output;
            var frame        = new Http2Frame();

            frame.PrepareRstStream(streamId, Http2ErrorCode.CANCEL);
            frame.PayloadLength = length;
            Http2FrameWriter.WriteHeader(frame, outputWriter);
            return(SendAsync(new byte[length]));
        }
예제 #11
0
        internal async Task SendHeadersAsync(int streamId, Http2HeadersFrameFlags flags, byte[] headerBlock)
        {
            var outputWriter = _pair.Application.Output;
            var frame        = new Http2Frame();

            frame.PrepareHeaders(flags, streamId);
            frame.PayloadLength = headerBlock.Length;

            Http2FrameWriter.WriteHeader(frame, outputWriter);
            await SendAsync(headerBlock);
        }
예제 #12
0
        internal Task SendEmptyContinuationFrameAsync(int streamId, Http2ContinuationFrameFlags flags)
        {
            var outputWriter = _pair.Application.Output;
            var frame        = new Http2Frame();

            frame.PrepareContinuation(flags, streamId);
            frame.PayloadLength = 0;

            Http2FrameWriter.WriteHeader(frame, outputWriter);
            return(FlushAsync(outputWriter));
        }
예제 #13
0
        public Task SendUnknownFrameTypeAsync(int streamId, int frameType)
        {
            var outputWriter = _pair.Application.Output;
            var frame        = new Http2Frame();

            frame.StreamId      = streamId;
            frame.Type          = (Http2FrameType)frameType;
            frame.PayloadLength = 0;
            Http2FrameWriter.WriteHeader(frame, outputWriter);
            return(FlushAsync(outputWriter));
        }
예제 #14
0
        public Task SendInvalidPriorityFrameAsync(int streamId, int length)
        {
            var outputWriter  = _pair.Application.Output;
            var priorityFrame = new Http2Frame();

            priorityFrame.PreparePriority(streamId, streamDependency: 0, exclusive: false, weight: 0);
            priorityFrame.PayloadLength = length;

            Http2FrameWriter.WriteHeader(priorityFrame, outputWriter);
            return(SendAsync(new byte[length]));
        }
예제 #15
0
        internal async Task SendContinuationAsync(int streamId, Http2ContinuationFrameFlags flags, byte[] payload)
        {
            var outputWriter = _pair.Application.Output;
            var frame        = new Http2Frame();

            frame.PrepareContinuation(flags, streamId);
            frame.PayloadLength = payload.Length;

            Http2FrameWriter.WriteHeader(frame, outputWriter);
            await SendAsync(payload);
        }
예제 #16
0
        public Task SendPingWithInvalidStreamIdAsync(int streamId)
        {
            Assert.NotEqual(0, streamId);

            var outputWriter = _pair.Application.Output;
            var pingFrame    = new Http2Frame();

            pingFrame.PreparePing(Http2PingFrameFlags.NONE);
            pingFrame.StreamId = streamId;
            Http2FrameWriter.WriteHeader(pingFrame, outputWriter);
            return(SendAsync(new byte[pingFrame.PayloadLength]));
        }
예제 #17
0
        public Task SendDataAsync(int streamId, Memory <byte> data, bool endStream)
        {
            var outputWriter = _pair.Application.Output;
            var frame        = new Http2Frame();

            frame.PrepareData(streamId);
            frame.PayloadLength = data.Length;
            frame.DataFlags     = endStream ? Http2DataFrameFlags.END_STREAM : Http2DataFrameFlags.NONE;

            Http2FrameWriter.WriteHeader(frame, outputWriter);
            return(SendAsync(data.Span));
        }
예제 #18
0
        public Task SendPushPromiseFrameAsync()
        {
            var writableBuffer = _pair.Application.Output;
            var frame          = new Http2Frame();

            frame.PayloadLength = 0;
            frame.Type          = Http2FrameType.PUSH_PROMISE;
            frame.StreamId      = 1;

            Http2FrameWriter.WriteHeader(frame, writableBuffer);
            return(FlushAsync(writableBuffer));
        }
예제 #19
0
        /* https://tools.ietf.org/html/rfc7540#section-6.4
         +---------------------------------------------------------------+
         |                        Error Code (32)                        |
         +---------------------------------------------------------------+
         */
        public Task SendRstStreamAsync(int streamId)
        {
            var outputWriter   = _pair.Application.Output;
            var rstStreamFrame = new Http2Frame();

            rstStreamFrame.PrepareRstStream(streamId, Http2ErrorCode.CANCEL);
            var payload = new byte[rstStreamFrame.PayloadLength];

            BinaryPrimitives.WriteUInt32BigEndian(payload, (uint)Http2ErrorCode.CANCEL);

            Http2FrameWriter.WriteHeader(rstStreamFrame, outputWriter);
            return(SendAsync(payload));
        }
예제 #20
0
    public static void WriteSettings(this PipeWriter writer, Http2PeerSettings clientSettings)
    {
        var frame = new Http2Frame();

        frame.PrepareSettings(Http2SettingsFrameFlags.NONE);
        var settings = clientSettings.GetNonProtocolDefaults();
        var payload  = new byte[settings.Count * Http2FrameReader.SettingSize];

        frame.PayloadLength = payload.Length;
        Http2FrameWriter.WriteSettings(settings, payload);
        Http2FrameWriter.WriteHeader(frame, writer);
        writer.Write(payload);
    }
예제 #21
0
        public Task SendWindowUpdateAsync(int streamId, int sizeIncrement)
        {
            var outputWriter = _pair.Application.Output;
            var frame        = new Http2Frame();

            frame.PrepareWindowUpdate(streamId, sizeIncrement);
            Http2FrameWriter.WriteHeader(frame, outputWriter);
            var buffer = outputWriter.GetSpan(4);

            BinaryPrimitives.WriteUInt32BigEndian(buffer, (uint)sizeIncrement);
            outputWriter.Advance(4);
            return(FlushAsync(outputWriter));
        }
예제 #22
0
        protected async Task SendSettingsWithInvalidLengthAsync(int length)
        {
            var writableBuffer = _pair.Application.Output;
            var frame          = new Http2Frame();

            frame.PrepareSettings(Http2SettingsFrameFlags.NONE);

            frame.PayloadLength = length;
            var payload = new byte[length];

            Http2FrameWriter.WriteHeader(frame, writableBuffer);
            await SendAsync(payload);
        }
예제 #23
0
        public async Task SendSettingsAsync()
        {
            var writableBuffer = _pair.Application.Output;
            var frame          = new Http2Frame();

            frame.PrepareSettings(Http2SettingsFrameFlags.NONE);
            var settings = _clientSettings.GetNonProtocolDefaults();
            var payload  = new byte[settings.Count * Http2FrameReader.SettingSize];

            frame.PayloadLength = payload.Length;
            Http2FrameWriter.WriteSettings(settings, payload);
            Http2FrameWriter.WriteHeader(frame, writableBuffer);
            await SendAsync(payload);
        }
예제 #24
0
        /* https://tools.ietf.org/html/rfc7540#section-6.3
         +-+-------------------------------------------------------------+
         |E|                  Stream Dependency (31)                     |
         +-+-------------+-----------------------------------------------+
         |   Weight (8)  |
         +-+-------------+
         */
        public Task SendPriorityAsync(int streamId, int streamDependency = 0)
        {
            var outputWriter  = _pair.Application.Output;
            var priorityFrame = new Http2Frame();

            priorityFrame.PreparePriority(streamId, streamDependency: streamDependency, exclusive: false, weight: 0);

            var payload = new byte[priorityFrame.PayloadLength].AsSpan();

            Bitshifter.WriteUInt31BigEndian(payload, (uint)streamDependency);
            payload[4] = 0; // Weight

            Http2FrameWriter.WriteHeader(priorityFrame, outputWriter);
            return(SendAsync(payload));
        }
예제 #25
0
    public static void WriteStartStream(this PipeWriter writer, int streamId, Span <byte> headerData, bool endStream, Http2Frame frame = null)
    {
        frame ??= new Http2Frame();
        frame.PrepareHeaders(Http2HeadersFrameFlags.NONE, streamId);
        frame.PayloadLength = headerData.Length;
        frame.HeadersFlags  = Http2HeadersFrameFlags.END_HEADERS;

        if (endStream)
        {
            frame.HeadersFlags |= Http2HeadersFrameFlags.END_STREAM;
        }

        Http2FrameWriter.WriteHeader(frame, writer);
        writer.Write(headerData);
    }
예제 #26
0
        protected async Task <bool> SendContinuationAsync(int streamId, Http2ContinuationFrameFlags flags)
        {
            var outputWriter = _pair.Application.Output;
            var frame        = new Http2Frame();

            frame.PrepareContinuation(flags, streamId);
            var buffer = _headerEncodingBuffer.AsMemory();
            var done   = _hpackEncoder.Encode(buffer.Span, out var length);

            frame.PayloadLength = length;

            Http2FrameWriter.WriteHeader(frame, outputWriter);
            await SendAsync(buffer.Span.Slice(0, length));

            return(done);
        }
예제 #27
0
        internal async Task <bool> SendContinuationAsync(int streamId, Http2ContinuationFrameFlags flags, IEnumerable <KeyValuePair <string, string> > headers)
        {
            var outputWriter = _pair.Application.Output;
            var frame        = new Http2Frame();

            frame.PrepareContinuation(flags, streamId);
            var buffer = _headerEncodingBuffer.AsMemory();
            var done   = _hpackEncoder.BeginEncode(headers, buffer.Span, out var length);

            frame.PayloadLength = length;

            Http2FrameWriter.WriteHeader(frame, outputWriter);
            await SendAsync(buffer.Span.Slice(0, length));

            return(done);
        }
예제 #28
0
        protected Task StartStreamAsync(int streamId, IEnumerable <KeyValuePair <string, string> > headers, bool endStream)
        {
            var writableBuffer = _pair.Application.Output;
            var tcs            = new TaskCompletionSource <object>(TaskCreationOptions.RunContinuationsAsynchronously);

            _runningStreams[streamId] = tcs;

            var frame = new Http2Frame();

            frame.PrepareHeaders(Http2HeadersFrameFlags.NONE, streamId);

            var buffer = _headerEncodingBuffer.AsSpan();
            var done   = _hpackEncoder.BeginEncode(headers, buffer, out var length);

            frame.PayloadLength = length;

            if (done)
            {
                frame.HeadersFlags = Http2HeadersFrameFlags.END_HEADERS;
            }

            if (endStream)
            {
                frame.HeadersFlags |= Http2HeadersFrameFlags.END_STREAM;
            }

            Http2FrameWriter.WriteHeader(frame, writableBuffer);
            writableBuffer.Write(buffer.Slice(0, length));

            while (!done)
            {
                frame.PrepareContinuation(Http2ContinuationFrameFlags.NONE, streamId);

                done = _hpackEncoder.Encode(buffer, out length);
                frame.PayloadLength = length;

                if (done)
                {
                    frame.ContinuationFlags = Http2ContinuationFrameFlags.END_HEADERS;
                }

                Http2FrameWriter.WriteHeader(frame, writableBuffer);
                writableBuffer.Write(buffer.Slice(0, length));
            }

            return(FlushAsync(writableBuffer));
        }
예제 #29
0
        public async Task WriteHeader_UnsetsReservedBit()
        {
            // Arrange
            var pipe  = new Pipe(new PipeOptions(_dirtyMemoryPool, PipeScheduler.Inline, PipeScheduler.Inline));
            var frame = new Http2Frame();

            frame.PreparePing(Http2PingFrameFlags.NONE);

            // Act
            Http2FrameWriter.WriteHeader(frame, pipe.Writer);
            await pipe.Writer.FlushAsync();

            // Assert
            var payload = await pipe.Reader.ReadForLengthAsync(Http2FrameReader.HeaderLength);

            Assert.Equal(new byte[] { 0x00, 0x00, 0x00, 0x00 }, payload.Skip(5).Take(4).ToArray());
        }
예제 #30
0
        public async Task SendIncompleteContinuationFrameAsync(int streamId)
        {
            var outputWriter = _pair.Application.Output;
            var frame        = new Http2Frame();

            frame.PrepareContinuation(Http2ContinuationFrameFlags.END_HEADERS, streamId);
            frame.PayloadLength = 3;
            var payload = new byte[3];

            // Set up an incomplete Literal Header Field w/ Incremental Indexing frame,
            // with an incomplete new name
            payload[0] = 0;
            payload[1] = 2;
            payload[2] = (byte)'a';

            Http2FrameWriter.WriteHeader(frame, outputWriter);
            await SendAsync(payload);
        }