// 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(); } }
public FrameAdapter(IHttp2Connection connection, DefaultHttp2FrameReader reader, IHttp2FrameListener listener, CountdownEvent latch) { this.connection = connection; this.listener = listener; this.reader = reader; this.latch = latch; }
public Http2FrameListenerDecorator(IHttp2FrameListener listener) { if (listener is null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.listener); } _listener = listener; }
public Http2EmptyDataFrameListener(IHttp2FrameListener listener, int maxConsecutiveEmptyFrames) : base(listener) { if ((uint)(maxConsecutiveEmptyFrames - 1) > SharedConstants.TooBigOrNegative) { ThrowHelper.ThrowArgumentException_Positive(maxConsecutiveEmptyFrames, ExceptionArgument.maxConsecutiveEmptyFrames); } _maxConsecutiveEmptyFrames = maxConsecutiveEmptyFrames; }
public DelegatingDecompressorFrameListener(IHttp2Connection connection, IHttp2FrameListener listener, bool strict) : base(listener) { _connection = connection; _strict = strict; _propertyKey = connection.NewKey(); _connection.AddListener(new DelegatingConnectionAdapter(this)); }
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; }
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); }
void ReadPingFrame(IChannelHandlerContext ctx, long data, IHttp2FrameListener listener) { if (_flags.Ack()) { listener.OnPingAckRead(ctx, data); } else { listener.OnPingRead(ctx, data); } }
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); }
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); }
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); }
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); } }
public DelegatingFrameListener(IHttp2FrameListener listener, IHttp2FrameLogger logger) { _listener = listener; _logger = logger; }
public void ReadFrame(IChannelHandlerContext ctx, IByteBuffer input, IHttp2FrameListener listener) { _reader.ReadFrame(ctx, input, new DelegatingFrameListener(listener, _logger)); }
void ReadRstStreamFrame(IChannelHandlerContext ctx, IByteBuffer payload, IHttp2FrameListener listener) { long errorCode = payload.ReadUnsignedInt(); listener.OnRstStreamRead(ctx, _streamId, (Http2Error)errorCode); }
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()); }
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()); } }
public TempHttp2FrameListener(FrameAdapter frameAdapter, IHttp2FrameListener listener, CountdownEvent latch) { this.frameAdapter = frameAdapter; this.listener = listener; this.latch = latch; }
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); } }
public FrameAdapter(IHttp2Connection connection, IHttp2FrameListener listener, CountdownEvent latch) : this(connection, new DefaultHttp2FrameReader(false), listener, latch) { }
/// <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);
void ReadUnknownFrame(IChannelHandlerContext ctx, IByteBuffer payload, int payloadEndIndex, IHttp2FrameListener listener) { payload = payload.ReadSlice(payloadEndIndex - payload.ReaderIndex); listener.OnUnknownFrame(ctx, _frameType, _streamId, _flags, payload); }
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()); }
public DelegatingDecompressorFrameListener(IHttp2Connection connection, IHttp2FrameListener listener) : this(connection, listener, true) { }
public FrameCountDown(IHttp2FrameListener listener, CountdownEvent settingsAckLatch, CountdownEvent messageLatch) : this(listener, settingsAckLatch, messageLatch, null, null) { }
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()); }
public FrameCountDown(IHttp2FrameListener listener, CountdownEvent settingsAckLatch, CountdownEvent messageLatch, CountdownEvent dataLatch, CountdownEvent trailersLatch) : this(listener, settingsAckLatch, messageLatch, dataLatch, trailersLatch, messageLatch) { }
public FrameAdapter(IHttp2FrameListener listener, CountdownEvent latch) : this(null, listener, latch) { }
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); }