예제 #1
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));
        }
예제 #2
0
    /* https://tools.ietf.org/html/rfc7540#section-4.1
     +-----------------------------------------------+
     |                 Length (24)                   |
     +---------------+---------------+---------------+
     |   Type (8)    |   Flags (8)   |
     +-+-------------+---------------+-------------------------------+
     |R|                 Stream Identifier (31)                      |
     +=+=============================================================+
     |                   Frame Payload (0...)                      ...
     +---------------------------------------------------------------+
     */
    internal static void WriteHeader(Http2Frame frame, PipeWriter output)
    {
        var buffer = output.GetSpan(Http2FrameReader.HeaderLength);

        Bitshifter.WriteUInt24BigEndian(buffer, (uint)frame.PayloadLength);
        buffer = buffer.Slice(3);

        buffer[0] = (byte)frame.Type;
        buffer[1] = frame.Flags;
        buffer    = buffer.Slice(2);

        Bitshifter.WriteUInt31BigEndian(buffer, (uint)frame.StreamId, preserveHighestBit: false);

        output.Advance(Http2FrameReader.HeaderLength);
    }
예제 #3
0
        public async Task SendSettingsWithInvalidStreamIdAsync(int streamId)
        {
            var writableBuffer = _pair.Application.Output;
            var frame          = new Http2Frame();

            frame.PrepareSettings(Http2SettingsFrameFlags.NONE);
            frame.StreamId = streamId;
            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);
        }
        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;

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

            return(done);
        }
예제 #5
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);
        }
예제 #6
0
        protected Task SendSettingsWithInvalidParameterValueAsync(Http2SettingsParameter parameter, uint value)
        {
            var frame = new Http2Frame(Http2Limits.MinAllowedMaxFrameSize);

            frame.PrepareSettings(Http2SettingsFrameFlags.NONE);
            frame.PayloadLength = 6;

            frame.Payload[0] = (byte)((ushort)parameter >> 8);
            frame.Payload[1] = (byte)(ushort)parameter;
            frame.Payload[2] = (byte)(value >> 24);
            frame.Payload[3] = (byte)(value >> 16);
            frame.Payload[4] = (byte)(value >> 8);
            frame.Payload[5] = (byte)value;

            return(SendAsync(frame.Raw));
        }
예제 #7
0
        public static void WriteStartStream(this PipeWriter writer, int streamId, Span <byte> headerData, bool endStream)
        {
            var 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);
        }
예제 #8
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));
        }
예제 #9
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());
        }
예제 #10
0
    public Task StartStreamAsync(int streamId, IEnumerable <KeyValuePair <string, string> > headers, bool endStream)
    {
        var writableBuffer = _pair.Application.Output;

        var frame = new Http2Frame();

        frame.PrepareHeaders(Http2HeadersFrameFlags.NONE, streamId);

        var buffer            = _headerEncodingBuffer.AsSpan();
        var headersEnumerator = GetHeadersEnumerator(headers);
        var done = HPackHeaderWriter.BeginEncodeHeaders(headersEnumerator, buffer, out var length);

        frame.PayloadLength = length;

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

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

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

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

            done = HPackHeaderWriter.ContinueEncodeHeaders(headersEnumerator, buffer, out length);
            frame.PayloadLength = length;

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

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

        return(FlushAsync(writableBuffer));
    }
        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';

            WriteHeader(frame, outputWriter);
            await SendAsync(payload);
        }
        internal async Task SendSettingsWithInvalidParameterValueAsync(Http2SettingsParameter parameter, uint value)
        {
            var writableBuffer = _pair.Application.Output;
            var frame          = new Http2Frame();

            frame.PrepareSettings(Http2SettingsFrameFlags.NONE);
            frame.PayloadLength = 6;
            var payload = new byte[Http2FrameReader.SettingSize];

            payload[0] = (byte)((ushort)parameter >> 8);
            payload[1] = (byte)(ushort)parameter;
            payload[2] = (byte)(value >> 24);
            payload[3] = (byte)(value >> 16);
            payload[4] = (byte)(value >> 8);
            payload[5] = (byte)value;

            WriteHeader(frame, writableBuffer);
            await SendAsync(payload);
        }
        public async Task SendInvalidHeadersFrameAsync(int streamId, int payloadLength, byte padLength)
        {
            Assert.True(padLength >= payloadLength, $"{nameof(padLength)} must be greater than or equal to {nameof(payloadLength)} to create an invalid frame.");

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

            frame.PrepareHeaders(Http2HeadersFrameFlags.PADDED, streamId);
            frame.PayloadLength = payloadLength;
            var payload = new byte[payloadLength];

            if (payloadLength > 0)
            {
                payload[0] = padLength;
            }

            WriteHeader(frame, outputWriter);
            await SendAsync(payload);
        }
        public async Task SendDataWithPaddingAsync(int streamId, Memory <byte> data, byte padLength, bool endStream)
        {
            var outputWriter = _pair.Application.Output;
            var frame        = new Http2Frame();

            frame.PrepareData(streamId, padLength);
            frame.PayloadLength = data.Length + 1 + padLength;

            if (endStream)
            {
                frame.DataFlags |= Http2DataFrameFlags.END_STREAM;
            }

            WriteHeader(frame, outputWriter);
            outputWriter.GetSpan(1)[0] = padLength;
            outputWriter.Advance(1);
            await SendAsync(data.Span);
            await SendAsync(new byte[padLength]);
        }
        public Task SendInvalidDataFrameAsync(int streamId, int frameLength, byte padLength)
        {
            Assert.True(padLength >= frameLength, $"{nameof(padLength)} must be greater than or equal to {nameof(frameLength)} to create an invalid frame.");

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

            frame.PrepareData(streamId);
            frame.DataFlags     = Http2DataFrameFlags.PADDED;
            frame.PayloadLength = frameLength;
            var payload = new byte[frameLength];

            if (frameLength > 0)
            {
                payload[0] = padLength;
            }

            WriteHeader(frame, outputWriter);
            return(SendAsync(payload));
        }
        public static void WriteStartStream(this PipeWriter writer, int streamId, Http2HeadersEnumerator headers, HPackEncoder hpackEncoder, byte[] headerEncodingBuffer, bool endStream)
        {
            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, writer);
            writer.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, writer);
                writer.Write(buffer.Slice(0, length));
            }
        }
예제 #17
0
    public const int SettingSize = 6; // 2 bytes for the id, 4 bytes for the value.

    public static bool TryReadFrame(ref ReadOnlySequence <byte> buffer, Http2Frame frame, uint maxFrameSize, out ReadOnlySequence <byte> framePayload)
    {
        framePayload = ReadOnlySequence <byte> .Empty;

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

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

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

        if (payloadLength > maxFrameSize)
        {
            throw new Http2ConnectionErrorException(SharedStrings.FormatHttp2ErrorFrameOverLimit(payloadLength, maxFrameSize), Http2ErrorCode.FRAME_SIZE_ERROR);
        }

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

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

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

        var extendedHeaderLength = ReadExtendedFields(frame, buffer);

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

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

            _runningStreams[streamId] = tcs;

            var frame = new Http2Frame();

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

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

            extendedHeader[0] = padLength;
            Bitshifter.WriteUInt31BigEndian(extendedHeader.Slice(1), (uint)streamDependency);
            extendedHeader[5] = priority;
            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));
        }
예제 #19
0
        protected async Task StartStreamAsync(int streamId, IEnumerable <KeyValuePair <string, string> > headers, bool endStream)
        {
            var tcs = new TaskCompletionSource <object>(TaskCreationOptions.RunContinuationsAsynchronously);

            _runningStreams[streamId] = tcs;

            var frame = new Http2Frame(Http2Limits.MinAllowedMaxFrameSize);

            frame.PrepareHeaders(Http2HeadersFrameFlags.NONE, streamId);
            var done = _hpackEncoder.BeginEncode(headers, frame.HeadersPayload, out var length);

            frame.PayloadLength = length;

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

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

            await SendAsync(frame.Raw);

            while (!done)
            {
                frame.PrepareContinuation(Http2ContinuationFrameFlags.NONE, streamId);
                done = _hpackEncoder.Encode(frame.HeadersPayload, out length);
                frame.PayloadLength = length;

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

                await SendAsync(frame.Raw);
            }
        }
예제 #20
0
        protected async Task SendHeadersWithPaddingAsync(int streamId, IEnumerable <KeyValuePair <string, string> > headers, byte padLength, bool endStream)
        {
            var tcs = new TaskCompletionSource <object>(TaskCreationOptions.RunContinuationsAsynchronously);

            _runningStreams[streamId] = tcs;

            var frame = new Http2Frame(Http2Limits.MinAllowedMaxFrameSize);

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

            _hpackEncoder.BeginEncode(headers, frame.HeadersPayload, out var length);

            frame.PayloadLength = 1 + length + padLength;
            frame.Payload.Slice(1 + length).Fill(0);

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

            await SendAsync(frame.Raw);
        }
예제 #21
0
        protected async Task SendHeadersWithPriorityAsync(int streamId, IEnumerable <KeyValuePair <string, string> > headers, byte priority, int streamDependency, bool endStream)
        {
            var tcs = new TaskCompletionSource <object>(TaskCreationOptions.RunContinuationsAsynchronously);

            _runningStreams[streamId] = tcs;

            var frame = new Http2Frame(Http2Limits.MinAllowedMaxFrameSize);

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

            _hpackEncoder.BeginEncode(headers, frame.HeadersPayload, out var length);

            frame.PayloadLength = 5 + length;

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

            await SendAsync(frame.Raw);
        }
    public virtual void GlobalSetup()
    {
        _memoryPool = PinnedBlockMemoryPoolFactory.Create();
        _httpFrame  = new Http2Frame();

        var options = new PipeOptions(_memoryPool, readerScheduler: PipeScheduler.Inline, writerScheduler: PipeScheduler.Inline, useSynchronizationContext: false);

        _connectionPair = DuplexPipe.CreateConnectionPair(options, options);

        _httpRequestHeaders = new HttpRequestHeaders();
        _httpRequestHeaders[HeaderNames.Method]    = new StringValues("GET");
        _httpRequestHeaders[HeaderNames.Path]      = new StringValues("/");
        _httpRequestHeaders[HeaderNames.Scheme]    = new StringValues("http");
        _httpRequestHeaders[HeaderNames.Authority] = new StringValues("localhost:80");

        _headersBuffer = new byte[1024 * 16];
        _hpackEncoder  = new DynamicHPackEncoder();

        var serviceContext = TestContextFactory.CreateServiceContext(
            serverOptions: new KestrelServerOptions(),
            dateHeaderValueManager: new DateHeaderValueManager(),
            systemClock: new MockSystemClock());

        serviceContext.DateHeaderValueManager.OnHeartbeat(default);
예제 #23
0
    /* https://tools.ietf.org/html/rfc7540#section-6.2
     +---------------+
     |Pad Length? (8)|
     +-+-------------+-----------------------------------------------+
     |E|                 Stream Dependency? (31)                     |
     +-+-------------+-----------------------------------------------+
     |  Weight? (8)  |
     +-+-------------+-----------------------------------------------+
     |                   Header Block Fragment (*)                 ...
     +---------------------------------------------------------------+
     |                           Padding (*)                       ...
     +---------------------------------------------------------------+
     */
    public Task SendHeadersWithPaddingAndPriorityAsync(int streamId, IEnumerable <KeyValuePair <string, string> > headers, byte padLength, byte priority, int streamDependency, bool endStream)
    {
        var writableBuffer = _pair.Application.Output;

        var frame = new Http2Frame();

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

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

        extendedHeader[0] = padLength;
        Bitshifter.WriteUInt31BigEndian(extendedHeader.Slice(1), (uint)streamDependency);
        extendedHeader[5] = priority;
        var payload = buffer.Slice(extendedHeaderLength, buffer.Length - padLength - extendedHeaderLength);

        HPackHeaderWriter.BeginEncodeHeaders(GetHeadersEnumerator(headers), payload, out var length);
        var padding = buffer.Slice(extendedHeaderLength + length, padLength);

        padding.Clear();

        frame.PayloadLength = extendedHeaderLength + length + padLength;

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

        WriteHeader(frame, writableBuffer);
        writableBuffer.Write(buffer.Slice(0, frame.PayloadLength));
        return(FlushAsync(writableBuffer));
    }
예제 #24
0
 public void Http2FrameSending(string connectionId, Http2Frame frame)
 {
     _http2FrameSending(_logger, connectionId, frame.Type, frame.StreamId, frame.PayloadLength, frame.ShowFlags(), null);
 }
예제 #25
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);
 }
예제 #26
0
 public Task OnDataAsync(Http2Frame dataFrame, in ReadOnlySequence <byte> payload)
예제 #27
0
 public void Http2FrameSending(string connectionId, Http2Frame frame)
 {
 }
예제 #28
0
 public void Http2FrameReceived(string connectionId, Http2Frame frame)
 {
 }
예제 #29
0
 public void Http2FrameSending(string connectionId, Http2Frame frame)
 {
     _trace1.Http2FrameSending(connectionId, frame);
     _trace2.Http2FrameSending(connectionId, frame);
 }
예제 #30
0
 public void Http2FrameReceived(string connectionId, Http2Frame frame)
 {
     _trace1.Http2FrameReceived(connectionId, frame);
     _trace2.Http2FrameReceived(connectionId, frame);
 }