private byte[] HeaderPayload(int streamId, IHttp2Headers headers)
        {
            var byteBuf = Unpooled.Buffer();

            try
            {
                _http2HeadersEncoder.EncodeHeaders(streamId, headers, byteBuf);
                byte[] bytes = new byte[byteBuf.ReadableBytes];
                byteBuf.ReadBytes(bytes);
                return(bytes);
            }
            finally
            {
                byteBuf.Release();
            }
        }
Exemple #2
0
        public virtual Task WritePushPromiseAsync(IChannelHandlerContext ctx, int streamId,
                                                  int promisedStreamId, IHttp2Headers headers, int padding, IPromise promise)
        {
            IByteBuffer             headerBlock       = null;
            SimplePromiseAggregator promiseAggregator = new SimplePromiseAggregator(promise);

            try
            {
                if ((uint)(streamId - 1) > SharedConstants.TooBigOrNegative)
                {
                    ThrowHelper.ThrowArgumentException_Positive(ExceptionArgument.StreamID);
                }
                if (promisedStreamId <= 0)
                {
                    ThrowHelper.ThrowArgumentException_Positive(ExceptionArgument.PromisedStreamId);
                }
                Http2CodecUtil.VerifyPadding(padding);

                // Encode the entire header block into an intermediate buffer.
                headerBlock = ctx.Allocator.Buffer();
                _headersEncoder.EncodeHeaders(streamId, headers, headerBlock);

                // Read the first fragment (possibly everything).
                Http2Flags flags = new Http2Flags().PaddingPresent(padding > 0);
                // IntFieldLength is for the length of the promisedStreamId
                int         nonFragmentLength = Http2CodecUtil.IntFieldLength + padding;
                int         maxFragmentLength = _maxFrameSize - nonFragmentLength;
                IByteBuffer fragment          = headerBlock.ReadRetainedSlice(Math.Min(headerBlock.ReadableBytes, maxFragmentLength));

                _ = flags.EndOfHeaders(!headerBlock.IsReadable());

                int         payloadLength = fragment.ReadableBytes + nonFragmentLength;
                IByteBuffer buf           = ctx.Allocator.Buffer(Http2CodecUtil.PushPromiseFrameHeaderLength);
                Http2CodecUtil.WriteFrameHeaderInternal(buf, payloadLength, Http2FrameTypes.PushPromise, flags, streamId);
                WritePaddingLength(buf, padding);

                // Write out the promised stream ID.
                _ = buf.WriteInt(promisedStreamId);
                _ = ctx.WriteAsync(buf, promiseAggregator.NewPromise());

                // Write the first fragment.
                _ = ctx.WriteAsync(fragment, promiseAggregator.NewPromise());

                // Write out the padding, if any.
                if (PaddingBytes(padding) > 0)
                {
                    _ = ctx.WriteAsync(ZeroBuffer.Slice(0, PaddingBytes(padding)), promiseAggregator.NewPromise());
                }

                if (!flags.EndOfHeaders())
                {
                    _ = WriteContinuationFramesAsync(ctx, streamId, headerBlock, promiseAggregator);
                }
            }
            catch (Http2Exception e)
            {
                promiseAggregator.SetException(e);
            }
            catch (Exception t)
            {
                promiseAggregator.SetException(t);
                _ = promiseAggregator.DoneAllocatingPromises();
                throw;
            }
            finally
            {
                if (headerBlock is object)
                {
                    _ = headerBlock.Release();
                }
            }

            _ = promiseAggregator.DoneAllocatingPromises();
            return(promiseAggregator.Task);
        }