示例#1
0
 // note that this may behave strangely when used for the initial upgrade
 // message when using h2c, since that message is ineligible for flow
 // control, but there is not yet an API for signaling that.
 internal static void Handle(IChannelHandlerContext ctx, IHttp2Connection connection,
                             IHttp2FrameListener listener, IFullHttpMessage message)
 {
     try
     {
         int          streamId = GetStreamId(connection, message.Headers);
         IHttp2Stream stream   = connection.Stream(streamId);
         if (stream is null)
         {
             stream = connection.Remote.CreateStream(streamId, false);
         }
         _ = message.Headers.Set(HttpConversionUtil.ExtensionHeaderNames.Scheme, HttpScheme.Http.Name);
         IHttp2Headers messageHeaders = HttpConversionUtil.ToHttp2Headers(message, true);
         var           hasContent     = message.Content.IsReadable();
         var           hasTrailers    = !message.TrailingHeaders.IsEmpty;
         listener.OnHeadersRead(ctx, streamId, messageHeaders, 0, !(hasContent || hasTrailers));
         if (hasContent)
         {
             _ = listener.OnDataRead(ctx, streamId, message.Content, 0, !hasTrailers);
         }
         if (hasTrailers)
         {
             IHttp2Headers headers = HttpConversionUtil.ToHttp2Headers(message.TrailingHeaders, true);
             listener.OnHeadersRead(ctx, streamId, headers, 0, true);
         }
         _ = stream.CloseRemoteSide();
     }
     finally
     {
         _ = message.Release();
     }
 }
示例#2
0
 public FrameAdapter(IHttp2Connection connection, DefaultHttp2FrameReader reader, IHttp2FrameListener listener,
                     CountdownEvent latch)
 {
     this.connection = connection;
     this.listener   = listener;
     this.reader     = reader;
     this.latch      = latch;
 }
示例#3
0
 public Http2FrameListenerDecorator(IHttp2FrameListener listener)
 {
     if (listener is null)
     {
         ThrowHelper.ThrowArgumentNullException(ExceptionArgument.listener);
     }
     _listener = listener;
 }
示例#4
0
 public Http2EmptyDataFrameListener(IHttp2FrameListener listener, int maxConsecutiveEmptyFrames)
     : base(listener)
 {
     if ((uint)(maxConsecutiveEmptyFrames - 1) > SharedConstants.TooBigOrNegative)
     {
         ThrowHelper.ThrowArgumentException_Positive(maxConsecutiveEmptyFrames, ExceptionArgument.maxConsecutiveEmptyFrames);
     }
     _maxConsecutiveEmptyFrames = maxConsecutiveEmptyFrames;
 }
示例#5
0
        public DelegatingDecompressorFrameListener(IHttp2Connection connection, IHttp2FrameListener listener, bool strict)
            : base(listener)
        {
            _connection = connection;
            _strict     = strict;

            _propertyKey = connection.NewKey();
            _connection.AddListener(new DelegatingConnectionAdapter(this));
        }
示例#6
0
 public FrameCountDown(IHttp2FrameListener listener, CountdownEvent settingsAckLatch, CountdownEvent messageLatch,
                       CountdownEvent dataLatch, CountdownEvent trailersLatch, CountdownEvent goAwayLatch)
 {
     this.listener         = listener;
     this.messageLatch     = messageLatch;
     this.settingsAckLatch = settingsAckLatch;
     this.dataLatch        = dataLatch;
     this.trailersLatch    = trailersLatch;
     this.goAwayLatch      = goAwayLatch;
 }
示例#7
0
        void ReadWindowUpdateFrame(IChannelHandlerContext ctx, IByteBuffer payload, IHttp2FrameListener listener)
        {
            int windowSizeIncrement = Http2CodecUtil.ReadUnsignedInt(payload);

            if (0u >= (uint)windowSizeIncrement)
            {
                ThrowHelper.ThrowStreamError_ReceivedWindowUpdateWithDelta0ForStream(_streamId);
            }

            listener.OnWindowUpdateRead(ctx, _streamId, windowSizeIncrement);
        }
示例#8
0
 void ReadPingFrame(IChannelHandlerContext ctx, long data, IHttp2FrameListener listener)
 {
     if (_flags.Ack())
     {
         listener.OnPingAckRead(ctx, data);
     }
     else
     {
         listener.OnPingRead(ctx, data);
     }
 }
示例#9
0
        public void ReadFrame(IChannelHandlerContext ctx, IByteBuffer input, IHttp2FrameListener listener)
        {
            if (_readError)
            {
                _ = input.SkipBytes(input.ReadableBytes);
                return;
            }

            try
            {
                do
                {
                    if (_readingHeaders)
                    {
                        ProcessHeaderState(input);
                        if (_readingHeaders)
                        {
                            // Wait until the entire header has arrived.
                            return;
                        }
                    }

                    // The header is complete, fall into the next case to process the payload.
                    // This is to ensure the proper handling of zero-length payloads. In this
                    // case, we don't want to loop around because there may be no more data
                    // available, causing us to exit the loop. Instead, we just want to perform
                    // the first pass at payload processing now.
                    ProcessPayloadState(ctx, input, listener);
                    if (!_readingHeaders)
                    {
                        // Wait until the entire payload has arrived.
                        return;
                    }
                }while (input.IsReadable());
            }
            catch (Http2Exception e)
            {
                _readError = !Http2Exception.IsStreamError(e);
                throw;
            }
            catch (Http2RuntimeException)
            {
                _readError = true;
                throw;
            }
            catch (Exception)
            {
                _readError = true;
                throw;
            }
        }
        /// <summary>Create a new instance.</summary>
        /// <param name="connection">The <see cref="IHttp2Connection"/> associated with this decoder.</param>
        /// <param name="encoder">The <see cref="IHttp2ConnectionEncoder"/> associated with this decoder.</param>
        /// <param name="frameReader">Responsible for reading/parsing the raw frames. As opposed to this object which applies
        /// h2 semantics on top of the frames.</param>
        /// <param name="requestVerifier">Determines if push promised streams are valid.</param>
        /// <param name="autoAckSettings"><c>false</c> to disable automatically applying and sending settings acknowledge frame.
        /// The <paramref name="encoder"/> is expected to be an instance of
        /// <see cref="IHttp2SettingsReceivedConsumer"/> and will apply the earliest received but not yet
        /// ACKed SETTINGS when writing the SETTINGS ACKs. <c>true</c> to enable automatically
        /// applying and sending settings acknowledge frame.</param>
        /// <param name="autoAckPing"><c>false</c> to disable automatically sending ping acknowledge frame. <c>true</c> to enable
        /// automatically sending ping ack frame.</param>
        public DefaultHttp2ConnectionDecoder(IHttp2Connection connection,
                                             IHttp2ConnectionEncoder encoder, IHttp2FrameReader frameReader, IHttp2PromisedRequestVerifier requestVerifier,
                                             bool autoAckSettings, bool autoAckPing)
        {
            if (connection is null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.connection);
            }
            if (frameReader is null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.frameReader);
            }
            if (encoder is null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.encoder);
            }
            if (requestVerifier is null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.requestVerifier);
            }

            _autoAckPing = autoAckPing;
            if (autoAckSettings)
            {
                _settingsReceivedConsumer = null;
            }
            else
            {
                var receivedConsumer = encoder as IHttp2SettingsReceivedConsumer;
                if (receivedConsumer is null)
                {
                    ThrowHelper.ThrowInvalidOperationException_disabling_autoAckSettings_requires_encoder_IHttp2SettingsReceivedConsumer();
                }
                _settingsReceivedConsumer = receivedConsumer;
            }
            _connection      = connection;
            _frameReader     = frameReader;
            _encoder         = encoder;
            _requestVerifier = requestVerifier;
            var connLocal = connection.Local;

            if (connLocal.FlowController is null)
            {
                connLocal.FlowController = new DefaultHttp2LocalFlowController(connection);
            }
            _ = connLocal.FlowController.FrameWriter(encoder.FrameWriter);

            _internalFrameListener = new PrefaceFrameListener(this);
        }
示例#11
0
        void ReadPriorityFrame(IChannelHandlerContext ctx, IByteBuffer payload, IHttp2FrameListener listener)
        {
            long word1            = payload.ReadUnsignedInt();
            bool exclusive        = (word1 & 0x80000000L) != 0;
            int  streamDependency = (int)(uint)(word1 & 0x7FFFFFFFL);

            if (streamDependency == _streamId)
            {
                ThrowHelper.ThrowStreamError_AStreamCannotDependOnItself(_streamId);
            }

            short weight = (short)(payload.ReadByte() + 1);

            listener.OnPriorityRead(ctx, _streamId, streamDependency, weight, exclusive);
        }
示例#12
0
        public void Decoration()
        {
            var decoder0 = new Mock <IHttp2ConnectionDecoder>();

            decoder0.Setup(x => x.FrameListener);
            IHttp2FrameListener listenerArgumentCaptor = null;

            decoder0.SetupSet(p => p.FrameListener = It.IsAny <IHttp2FrameListener>()).Callback <IHttp2FrameListener>(value => listenerArgumentCaptor = value);
            decoder0.SetupGet(p => p.FrameListener).Returns(() => listenerArgumentCaptor);

            var listener = new Mock <IHttp2FrameListener>();
            Http2EmptyDataFrameConnectionDecoder decoder = new Http2EmptyDataFrameConnectionDecoder(decoder0.Object, 2);

            decoder.FrameListener = listener.Object;
            // verify(delegate).frameListener(listenerArgumentCaptor.capture())
            Assert.False(decoder.FrameListener is Http2EmptyDataFrameListener);
            Assert.IsType <Http2EmptyDataFrameListener>(decoder.FrameListener0);
        }
示例#13
0
        void ReadSettingsFrame(IChannelHandlerContext ctx, IByteBuffer payload, IHttp2FrameListener listener)
        {
            if (_flags.Ack())
            {
                listener.OnSettingsAckRead(ctx);
            }
            else
            {
                int           numSettings = _payloadLength / Http2CodecUtil.SettingEntryLength;
                Http2Settings settings    = new Http2Settings();
                for (int index = 0; index < numSettings; ++index)
                {
                    char id    = (char)payload.ReadUnsignedShort();
                    long value = payload.ReadUnsignedInt();
                    try
                    {
                        _ = settings.Put(id, value);
                    }
                    catch (ArgumentException e)
                    {
                        switch (id)
                        {
                        case Http2CodecUtil.SettingsMaxFrameSize:
                            ThrowHelper.ThrowConnectionError(Http2Error.ProtocolError, e);
                            break;

                        case Http2CodecUtil.SettingsInitialWindowSize:
                            ThrowHelper.ThrowConnectionError(Http2Error.FlowControlError, e);
                            break;

                        default:
                            ThrowHelper.ThrowConnectionError(Http2Error.ProtocolError, e);
                            break;
                        }
                    }
                }

                listener.OnSettingsRead(ctx, settings);
            }
        }
示例#14
0
 public DelegatingFrameListener(IHttp2FrameListener listener, IHttp2FrameLogger logger)
 {
     _listener = listener;
     _logger   = logger;
 }
示例#15
0
 public void ReadFrame(IChannelHandlerContext ctx, IByteBuffer input, IHttp2FrameListener listener)
 {
     _reader.ReadFrame(ctx, input, new DelegatingFrameListener(listener, _logger));
 }
示例#16
0
        void ReadRstStreamFrame(IChannelHandlerContext ctx, IByteBuffer payload, IHttp2FrameListener listener)
        {
            long errorCode = payload.ReadUnsignedInt();

            listener.OnRstStreamRead(ctx, _streamId, (Http2Error)errorCode);
        }
示例#17
0
        void ReadPushPromiseFrame(IChannelHandlerContext ctx, IByteBuffer payload, int payloadEndIndex, IHttp2FrameListener listener)
        {
            int pushPromiseStreamId = _streamId;
            int padding             = ReadPadding(payload);

            VerifyPadding(padding);
            int promisedStreamId = Http2CodecUtil.ReadUnsignedInt(payload);

            // Create a handler that invokes the listener when the header block is complete.
            _headersContinuation = new PushPromiseFrameHeadersContinuation(this,
                                                                           ctx, pushPromiseStreamId, padding, promisedStreamId);

            // Process the initial fragment, invoking the listener's callback if end of headers.
            int dataLength = LengthWithoutTrailingPadding(payloadEndIndex - payload.ReaderIndex, padding);

            _headersContinuation.ProcessFragment(_flags.EndOfHeaders(), payload, dataLength, listener);
            ResetHeadersContinuationIfEnd(_flags.EndOfHeaders());
        }
示例#18
0
 public override void ProcessFragment(bool endOfHeaders, IByteBuffer fragment, int len, IHttp2FrameListener listener)
 {
     _builder.AddFragment(fragment, len, _ctx.Allocator, endOfHeaders);
     if (endOfHeaders)
     {
         listener.OnHeadersRead(_ctx, _streamId, _builder.Headers(), _streamDependency,
                                _weight, _exclusive, _padding, _headersFlags.EndOfStream());
     }
 }
示例#19
0
 public TempHttp2FrameListener(FrameAdapter frameAdapter, IHttp2FrameListener listener, CountdownEvent latch)
 {
     this.frameAdapter = frameAdapter;
     this.listener     = listener;
     this.latch        = latch;
 }
示例#20
0
 public override void ProcessFragment(bool endOfHeaders, IByteBuffer fragment, int len, IHttp2FrameListener listener)
 {
     _builder.AddFragment(fragment, len, _ctx.Allocator, endOfHeaders);
     if (endOfHeaders)
     {
         listener.OnPushPromiseRead(_ctx, _streamId, _promisedStreamId, _builder.Headers(), _padding);
     }
 }
示例#21
0
 public FrameAdapter(IHttp2Connection connection, IHttp2FrameListener listener, CountdownEvent latch)
     : this(connection, new DefaultHttp2FrameReader(false), listener, latch)
 {
 }
示例#22
0
 /// <summary>
 /// Processes the next fragment for the current header block.
 /// </summary>
 /// <param name="endOfHeaders">whether the fragment is the last in the header block.</param>
 /// <param name="fragment">the fragment of the header block to be added.</param>
 /// <param name="len"></param>
 /// <param name="listener">the listener to be notified if the header block is completed.</param>
 public abstract void ProcessFragment(bool endOfHeaders, IByteBuffer fragment, int len, IHttp2FrameListener listener);
示例#23
0
 void ReadUnknownFrame(IChannelHandlerContext ctx, IByteBuffer payload, int payloadEndIndex, IHttp2FrameListener listener)
 {
     payload = payload.ReadSlice(payloadEndIndex - payload.ReaderIndex);
     listener.OnUnknownFrame(ctx, _frameType, _streamId, _flags, payload);
 }
示例#24
0
 void ReadContinuationFrame(IByteBuffer payload, int payloadEndIndex, IHttp2FrameListener listener)
 {
     // Process the initial fragment, invoking the listener's callback if end of headers.
     _headersContinuation.ProcessFragment(_flags.EndOfHeaders(), payload, payloadEndIndex - payload.ReaderIndex, listener);
     ResetHeadersContinuationIfEnd(_flags.EndOfHeaders());
 }
示例#25
0
 public DelegatingDecompressorFrameListener(IHttp2Connection connection, IHttp2FrameListener listener)
     : this(connection, listener, true)
 {
 }
示例#26
0
 public FrameCountDown(IHttp2FrameListener listener, CountdownEvent settingsAckLatch, CountdownEvent messageLatch)
     : this(listener, settingsAckLatch, messageLatch, null, null)
 {
 }
示例#27
0
        void ReadHeadersFrame(IChannelHandlerContext ctx, IByteBuffer payload, int payloadEndIndex, IHttp2FrameListener listener)
        {
            int        headersStreamId = _streamId;
            Http2Flags headersFlags    = _flags;
            int        padding         = ReadPadding(payload);

            VerifyPadding(padding);

            // The callback that is invoked is different depending on whether priority information
            // is present in the headers frame.
            if (headersFlags.PriorityPresent())
            {
                long word1            = payload.ReadUnsignedInt();
                bool exclusive        = (word1 & 0x80000000L) != 0;
                int  streamDependency = (int)(uint)(word1 & 0x7FFFFFFFL);
                if (streamDependency == headersStreamId)
                {
                    ThrowHelper.ThrowStreamError_AStreamCannotDependOnItself(headersStreamId);
                }

                short weight    = (short)(payload.ReadByte() + 1);
                int   lenToRead = LengthWithoutTrailingPadding(payloadEndIndex - payload.ReaderIndex, padding);

                // Create a handler that invokes the listener when the header block is complete.
                _headersContinuation = new PriorityHeadersFrameHeadersContinuation(this,
                                                                                   ctx, headersStreamId, padding, streamDependency, weight, exclusive, headersFlags);

                // Process the initial fragment, invoking the listener's callback if end of headers.
                _headersContinuation.ProcessFragment(headersFlags.EndOfHeaders(), payload, lenToRead, listener);
                ResetHeadersContinuationIfEnd(headersFlags.EndOfHeaders());
                return;
            }

            // The priority fields are not present in the frame. Prepare a continuation that invokes
            // the listener callback without priority information.
            _headersContinuation = new HeadersFrameHeadersContinuation(this,
                                                                       ctx, headersStreamId, padding, headersFlags);

            // Process the initial fragment, invoking the listener's callback if end of headers.
            int dataLength = LengthWithoutTrailingPadding(payloadEndIndex - payload.ReaderIndex, padding);

            _headersContinuation.ProcessFragment(headersFlags.EndOfHeaders(), payload, dataLength, listener);
            ResetHeadersContinuationIfEnd(headersFlags.EndOfHeaders());
        }
示例#28
0
 public FrameCountDown(IHttp2FrameListener listener, CountdownEvent settingsAckLatch, CountdownEvent messageLatch,
                       CountdownEvent dataLatch, CountdownEvent trailersLatch)
     : this(listener, settingsAckLatch, messageLatch, dataLatch, trailersLatch, messageLatch)
 {
 }
示例#29
0
 public FrameAdapter(IHttp2FrameListener listener, CountdownEvent latch)
     : this(null, listener, latch)
 {
 }
示例#30
0
        static void ReadGoAwayFrame(IChannelHandlerContext ctx, IByteBuffer payload, int payloadEndIndex, IHttp2FrameListener listener)
        {
            int         lastStreamId = Http2CodecUtil.ReadUnsignedInt(payload);
            var         errorCode    = (Http2Error)payload.ReadUnsignedInt();
            IByteBuffer debugData    = payload.ReadSlice(payloadEndIndex - payload.ReaderIndex);

            listener.OnGoAwayRead(ctx, lastStreamId, errorCode, debugData);
        }