void VerifyHeadersFrame() { VerifyAssociatedWithAStream(); VerifyNotProcessingHeaders(); VerifyPayloadLength(_payloadLength); int requiredLength = _flags.GetPaddingPresenceFieldLength() + _flags.GetNumPriorityBytes(); if (_payloadLength < requiredLength) { ThrowHelper.ThrowStreamError_FrameLengthTooSmall(_streamId, _payloadLength); } }
Task WriteHeadersInternal(IChannelHandlerContext ctx, int streamId, IHttp2Headers headers, int padding, bool endOfStream, bool hasPriority, int streamDependency, short weight, bool exclusive, IPromise promise) { IByteBuffer headerBlock = null; SimplePromiseAggregator promiseAggregator = new SimplePromiseAggregator(promise); try { if ((uint)(streamId - 1) > SharedConstants.TooBigOrNegative) { ThrowHelper.ThrowArgumentException_Positive(ExceptionArgument.StreamID); } if (hasPriority) { if (streamDependency < 0) { ThrowHelper.ThrowArgumentException_PositiveOrZero(ExceptionArgument.StreamDependency); } Http2CodecUtil.VerifyPadding(padding); VerifyWeight(weight); } // Encode the entire header block. headerBlock = ctx.Allocator.Buffer(); _headersEncoder.EncodeHeaders(streamId, headers, headerBlock); Http2Flags flags = new Http2Flags().EndOfStream(endOfStream).PriorityPresent(hasPriority).PaddingPresent(padding > 0); // Read the first fragment (possibly everything). int nonFragmentBytes = padding + flags.GetNumPriorityBytes(); int maxFragmentLength = _maxFrameSize - nonFragmentBytes; IByteBuffer fragment = headerBlock.ReadRetainedSlice(Math.Min(headerBlock.ReadableBytes, maxFragmentLength)); // Set the end of headers flag for the first frame. _ = flags.EndOfHeaders(!headerBlock.IsReadable()); int payloadLength = fragment.ReadableBytes + nonFragmentBytes; IByteBuffer buf = ctx.Allocator.Buffer(Http2CodecUtil.HeadersFrameHeaderLength); Http2CodecUtil.WriteFrameHeaderInternal(buf, payloadLength, Http2FrameTypes.Headers, flags, streamId); WritePaddingLength(buf, padding); if (hasPriority) { _ = buf.WriteInt(exclusive ? (int)(uint)(0x80000000L | streamDependency) : streamDependency); // Adjust the weight so that it fits into a single byte on the wire. _ = buf.WriteByte(weight - 1); } _ = 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 { _ = (headerBlock?.Release()); } _ = promiseAggregator.DoneAllocatingPromises(); return(promiseAggregator.Task); }