コード例 #1
0
            public bool ConsumeBytes(IHttp2Stream stream, int numBytes)
            {
                Http2Decompressor decompressor = _frameListener.Decompressor(stream);

                if (decompressor is object)
                {
                    // Convert the decompressed bytes to compressed (on the wire) bytes.
                    numBytes = decompressor.ConsumeBytes(stream.Id, numBytes);
                }
                try
                {
                    return(_flowController.ConsumeBytes(stream, numBytes));
                }
                catch (Http2Exception)
                {
                    throw;
                }
                catch (Exception t)
                {
                    // The stream should be closed at this point. We have already changed our state tracking the compressed
                    // bytes, and there is no guarantee we can recover if the underlying flow controller throws.
                    return(ThrowHelper.ThrowStreamError_ErrorWhileReturningBytesToFlowControlWindow(stream.Id, t));
                }
            }
コード例 #2
0
        public override int OnDataRead(IChannelHandlerContext ctx, int streamId, IByteBuffer data, int padding, bool endOfStream)
        {
            IHttp2Stream      stream       = _connection.Stream(streamId);
            Http2Decompressor decompressor = Decompressor(stream);

            if (decompressor is null)
            {
                // The decompressor may be null if no compatible encoding type was found in this stream's headers
                return(_listener.OnDataRead(ctx, streamId, data, padding, endOfStream));
            }

            EmbeddedChannel channel         = decompressor.Decompressor;
            int             compressedBytes = data.ReadableBytes + padding;

            decompressor.IncrementCompressedBytes(compressedBytes);
            try
            {
                // call retain here as it will call release after its written to the channel
                _ = channel.WriteInbound(data.Retain());
                var buf = NextReadableBuf(channel);
                if (buf is null && endOfStream && channel.Finish())
                {
                    buf = NextReadableBuf(channel);
                }
                if (buf is null)
                {
                    if (endOfStream)
                    {
                        _ = _listener.OnDataRead(ctx, streamId, Unpooled.Empty, padding, true);
                    }
                    // No new decompressed data was extracted from the compressed data. This means the application could
                    // not be provided with data and thus could not return how many bytes were processed. We will assume
                    // there is more data coming which will complete the decompression block. To allow for more data we
                    // return all bytes to the flow control window (so the peer can send more data).
                    decompressor.IncrementDecompressedBytes(compressedBytes);
                    return(compressedBytes);
                }
                try
                {
                    IHttp2LocalFlowController flowController = _connection.Local.FlowController;
                    decompressor.IncrementDecompressedBytes(padding);
                    while (true)
                    {
                        var nextBuf = NextReadableBuf(channel);
                        var decompressedEndOfStream = nextBuf is null && endOfStream;
                        if (decompressedEndOfStream && channel.Finish())
                        {
                            nextBuf = NextReadableBuf(channel);
                            decompressedEndOfStream = nextBuf is null;
                        }

                        decompressor.IncrementDecompressedBytes(buf.ReadableBytes);
                        // Immediately return the bytes back to the flow controller. ConsumedBytesConverter will convert
                        // from the decompressed amount which the user knows about to the compressed amount which flow
                        // control knows about.
                        _ = flowController.ConsumeBytes(stream,
                                                        _listener.OnDataRead(ctx, streamId, buf, padding, decompressedEndOfStream));
                        if (nextBuf is null)
                        {
                            break;
                        }

                        padding = 0; // Padding is only communicated once on the first iteration.
                        _       = buf.Release();
                        buf     = nextBuf;
                    }
                    // We consume bytes each time we call the listener to ensure if multiple frames are decompressed
                    // that the bytes are accounted for immediately. Otherwise the user may see an inconsistent state of
                    // flow control.
                    return(0);
                }
                finally
                {
                    _ = buf.Release();
                }
            }
            catch (Http2Exception)
            {
                throw;
            }
            catch (Exception t)
            {
                return(ThrowHelper.ThrowStreamError_DecompressorErrorDetectedWhileDelegatingDataReadOnStream(stream.Id, t));
            }
        }