/* https://tools.ietf.org/html/rfc7540#section-6.2 +-+-------------+-----------------------------------------------+ |E| Stream Dependency? (31) | +-+-------------+-----------------------------------------------+ | Weight? (8) | +-+-------------+-----------------------------------------------+ | Header Block Fragment (*) ... +---------------------------------------------------------------+ */ public Task SendHeadersWithPriorityAsync(int streamId, IEnumerable <KeyValuePair <string, string> > headers, byte priority, int streamDependency, bool endStream) { var writableBuffer = _pair.Application.Output; var tcs = new TaskCompletionSource <object>(TaskCreationOptions.RunContinuationsAsynchronously); var frame = new Http2Frame(); frame.PrepareHeaders(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.PRIORITY, streamId); frame.HeadersPriorityWeight = priority; frame.HeadersStreamDependency = streamDependency; var extendedHeaderLength = 5; // stream dependency + weight var buffer = _headerEncodingBuffer.AsSpan(); var extendedHeader = buffer.Slice(0, extendedHeaderLength); Bitshifter.WriteUInt31BigEndian(extendedHeader, (uint)streamDependency); extendedHeader[4] = priority; var payload = buffer.Slice(extendedHeaderLength); _hpackEncoder.BeginEncode(headers, payload, out var length); frame.PayloadLength = extendedHeaderLength + length; if (endStream) { frame.HeadersFlags |= Http2HeadersFrameFlags.END_STREAM; } Http2FrameWriter.WriteHeader(frame, writableBuffer); writableBuffer.Write(buffer.Slice(0, frame.PayloadLength)); return(FlushAsync(writableBuffer)); }
/* https://tools.ietf.org/html/rfc7540#section-6.2 +---------------+ |Pad Length? (8)| +-+-------------+-----------------------------------------------+ | Header Block Fragment (*) ... +---------------------------------------------------------------+ | Padding (*) ... +---------------------------------------------------------------+ */ public Task SendHeadersWithPaddingAsync(int streamId, IEnumerable <KeyValuePair <string, string> > headers, byte padLength, bool endStream) { var writableBuffer = _pair.Application.Output; var tcs = new TaskCompletionSource <object>(TaskCreationOptions.RunContinuationsAsynchronously); var frame = new Http2Frame(); frame.PrepareHeaders(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.PADDED, streamId); frame.HeadersPadLength = padLength; var extendedHeaderLength = 1; // Padding length field var buffer = _headerEncodingBuffer.AsSpan(); var extendedHeader = buffer.Slice(0, extendedHeaderLength); extendedHeader[0] = padLength; var payload = buffer.Slice(extendedHeaderLength, buffer.Length - padLength - extendedHeaderLength); _hpackEncoder.BeginEncode(headers, payload, out var length); var padding = buffer.Slice(extendedHeaderLength + length, padLength); padding.Fill(0); frame.PayloadLength = extendedHeaderLength + length + padLength; if (endStream) { frame.HeadersFlags |= Http2HeadersFrameFlags.END_STREAM; } WriteHeader(frame, writableBuffer); writableBuffer.Write(buffer.Slice(0, frame.PayloadLength)); return(FlushAsync(writableBuffer)); }
/* https://tools.ietf.org/html/rfc7540#section-6.2 +---------------+ |Pad Length? (8)| +-+-------------+-----------------------------------------------+ | Header Block Fragment (*) ... +---------------------------------------------------------------+ | Padding (*) ... +---------------------------------------------------------------+ */ public Task SendHeadersWithPaddingAsync(int streamId, IEnumerable <KeyValuePair <string, string> > headers, byte padLength, bool endStream) { var writableBuffer = _pair.Application.Output; var frame = new Http2Frame(); frame.PrepareHeaders(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.PADDED, streamId); frame.HeadersPadLength = padLength; var extendedHeaderLength = 1; // Padding length field var buffer = _headerEncodingBuffer.AsSpan(); var extendedHeader = buffer.Slice(0, extendedHeaderLength); extendedHeader[0] = padLength; var payload = buffer.Slice(extendedHeaderLength, buffer.Length - padLength - extendedHeaderLength); HPackHeaderWriter.BeginEncodeHeaders(GetHeadersEnumerator(headers), payload, out var length); var padding = buffer.Slice(extendedHeaderLength + length, padLength); padding.Clear(); frame.PayloadLength = extendedHeaderLength + length + padLength; if (endStream) { frame.HeadersFlags |= Http2HeadersFrameFlags.END_STREAM; } WriteHeader(frame, writableBuffer); writableBuffer.Write(buffer.Slice(0, frame.PayloadLength)); return(FlushAsync(writableBuffer)); }
protected Task SendHeadersAsync(int streamId, Http2HeadersFrameFlags flags, byte[] headerBlock) { var frame = new Http2Frame(Http2Limits.MinAllowedMaxFrameSize); frame.PrepareHeaders(flags, streamId); frame.PayloadLength = headerBlock.Length; headerBlock.CopyTo(frame.HeadersPayload); return(SendAsync(frame.Raw)); }
internal async Task SendHeadersAsync(int streamId, Http2HeadersFrameFlags flags, byte[] headerBlock) { var outputWriter = _pair.Application.Output; var frame = new Http2Frame(); frame.PrepareHeaders(flags, streamId); frame.PayloadLength = headerBlock.Length; WriteHeader(frame, outputWriter); await SendAsync(headerBlock); }
protected async Task <bool> SendHeadersAsync(int streamId, Http2HeadersFrameFlags flags, IEnumerable <KeyValuePair <string, string> > headers) { var frame = new Http2Frame(Http2Limits.MinAllowedMaxFrameSize); frame.PrepareHeaders(flags, streamId); var done = _hpackEncoder.BeginEncode(headers, frame.Payload, out var length); frame.PayloadLength = length; await SendAsync(frame.Raw); return(done); }
protected Task SendInvalidHeadersFrameAsync(int streamId, int payloadLength, byte padLength) { Assert.True(padLength >= payloadLength, $"{nameof(padLength)} must be greater than or equal to {nameof(payloadLength)} to create an invalid frame."); var frame = new Http2Frame(Http2Limits.MinAllowedMaxFrameSize); frame.PrepareHeaders(Http2HeadersFrameFlags.PADDED, streamId); frame.Payload[0] = padLength; // Set length last so .Payload can be written to frame.PayloadLength = payloadLength; return(SendAsync(frame.Raw)); }
protected Task SendIncompleteHeadersFrameAsync(int streamId) { var frame = new Http2Frame(Http2Limits.MinAllowedMaxFrameSize); frame.PrepareHeaders(Http2HeadersFrameFlags.END_HEADERS, streamId); frame.PayloadLength = 3; // Set up an incomplete Literal Header Field w/ Incremental Indexing frame, // with an incomplete new name frame.Payload[0] = 0; frame.Payload[1] = 2; frame.Payload[2] = (byte)'a'; return(SendAsync(frame.Raw)); }
public static void WriteStartStream(this PipeWriter writer, int streamId, Span <byte> headerData, bool endStream, Http2Frame frame = null) { frame ??= new Http2Frame(); frame.PrepareHeaders(Http2HeadersFrameFlags.NONE, streamId); frame.PayloadLength = headerData.Length; frame.HeadersFlags = Http2HeadersFrameFlags.END_HEADERS; if (endStream) { frame.HeadersFlags |= Http2HeadersFrameFlags.END_STREAM; } Http2FrameWriter.WriteHeader(frame, writer); writer.Write(headerData); }
internal async Task <bool> SendHeadersAsync(int streamId, Http2HeadersFrameFlags flags, IEnumerable <KeyValuePair <string, string> > headers) { var outputWriter = _pair.Application.Output; var frame = new Http2Frame(); frame.PrepareHeaders(flags, streamId); var buffer = _headerEncodingBuffer.AsMemory(); var done = _hpackEncoder.BeginEncode(headers, buffer.Span, out var length); frame.PayloadLength = length; WriteHeader(frame, outputWriter); await SendAsync(buffer.Span.Slice(0, length)); return(done); }
protected Task StartStreamAsync(int streamId, IEnumerable <KeyValuePair <string, string> > headers, bool endStream) { var writableBuffer = _pair.Application.Output; var tcs = new TaskCompletionSource <object>(TaskCreationOptions.RunContinuationsAsynchronously); _runningStreams[streamId] = tcs; var frame = new Http2Frame(); frame.PrepareHeaders(Http2HeadersFrameFlags.NONE, streamId); var buffer = _headerEncodingBuffer.AsSpan(); var done = _hpackEncoder.BeginEncode(headers, buffer, out var length); frame.PayloadLength = length; if (done) { frame.HeadersFlags = Http2HeadersFrameFlags.END_HEADERS; } if (endStream) { frame.HeadersFlags |= Http2HeadersFrameFlags.END_STREAM; } Http2FrameWriter.WriteHeader(frame, writableBuffer); writableBuffer.Write(buffer.Slice(0, length)); while (!done) { frame.PrepareContinuation(Http2ContinuationFrameFlags.NONE, streamId); done = _hpackEncoder.Encode(buffer, out length); frame.PayloadLength = length; if (done) { frame.ContinuationFlags = Http2ContinuationFrameFlags.END_HEADERS; } Http2FrameWriter.WriteHeader(frame, writableBuffer); writableBuffer.Write(buffer.Slice(0, length)); } return(FlushAsync(writableBuffer)); }
public Task StartStreamAsync(int streamId, IEnumerable <KeyValuePair <string, string> > headers, bool endStream) { var writableBuffer = _pair.Application.Output; var frame = new Http2Frame(); frame.PrepareHeaders(Http2HeadersFrameFlags.NONE, streamId); var buffer = _headerEncodingBuffer.AsSpan(); var headersEnumerator = GetHeadersEnumerator(headers); var done = HPackHeaderWriter.BeginEncodeHeaders(headersEnumerator, buffer, out var length); frame.PayloadLength = length; if (done) { frame.HeadersFlags = Http2HeadersFrameFlags.END_HEADERS; } if (endStream) { frame.HeadersFlags |= Http2HeadersFrameFlags.END_STREAM; } WriteHeader(frame, writableBuffer); writableBuffer.Write(buffer.Slice(0, length)); while (!done) { frame.PrepareContinuation(Http2ContinuationFrameFlags.NONE, streamId); done = HPackHeaderWriter.ContinueEncodeHeaders(headersEnumerator, buffer, out length); frame.PayloadLength = length; if (done) { frame.ContinuationFlags = Http2ContinuationFrameFlags.END_HEADERS; } WriteHeader(frame, writableBuffer); writableBuffer.Write(buffer.Slice(0, length)); } return(FlushAsync(writableBuffer)); }
public async Task SendIncompleteHeadersFrameAsync(int streamId) { var outputWriter = _pair.Application.Output; var frame = new Http2Frame(); frame.PrepareHeaders(Http2HeadersFrameFlags.END_HEADERS, streamId); frame.PayloadLength = 3; var payload = new byte[3]; // Set up an incomplete Literal Header Field w/ Incremental Indexing frame, // with an incomplete new name payload[0] = 0; payload[1] = 2; payload[2] = (byte)'a'; WriteHeader(frame, outputWriter); await SendAsync(payload); }
public async Task SendInvalidHeadersFrameAsync(int streamId, int payloadLength, byte padLength) { Assert.True(padLength >= payloadLength, $"{nameof(padLength)} must be greater than or equal to {nameof(payloadLength)} to create an invalid frame."); var outputWriter = _pair.Application.Output; var frame = new Http2Frame(); frame.PrepareHeaders(Http2HeadersFrameFlags.PADDED, streamId); frame.PayloadLength = payloadLength; var payload = new byte[payloadLength]; if (payloadLength > 0) { payload[0] = padLength; } WriteHeader(frame, outputWriter); await SendAsync(payload); }
public static void WriteStartStream(this PipeWriter writer, int streamId, Http2HeadersEnumerator headers, HPackEncoder hpackEncoder, byte[] headerEncodingBuffer, bool endStream) { var frame = new Http2Frame(); frame.PrepareHeaders(Http2HeadersFrameFlags.NONE, streamId); var buffer = headerEncodingBuffer.AsSpan(); var done = hpackEncoder.BeginEncode(headers, buffer, out var length); frame.PayloadLength = length; if (done) { frame.HeadersFlags = Http2HeadersFrameFlags.END_HEADERS; } if (endStream) { frame.HeadersFlags |= Http2HeadersFrameFlags.END_STREAM; } Http2FrameWriter.WriteHeader(frame, writer); writer.Write(buffer.Slice(0, length)); while (!done) { frame.PrepareContinuation(Http2ContinuationFrameFlags.NONE, streamId); done = hpackEncoder.Encode(buffer, out length); frame.PayloadLength = length; if (done) { frame.ContinuationFlags = Http2ContinuationFrameFlags.END_HEADERS; } Http2FrameWriter.WriteHeader(frame, writer); writer.Write(buffer.Slice(0, length)); } }
protected async Task StartStreamAsync(int streamId, IEnumerable <KeyValuePair <string, string> > headers, bool endStream) { var tcs = new TaskCompletionSource <object>(TaskCreationOptions.RunContinuationsAsynchronously); _runningStreams[streamId] = tcs; var frame = new Http2Frame(Http2Limits.MinAllowedMaxFrameSize); frame.PrepareHeaders(Http2HeadersFrameFlags.NONE, streamId); var done = _hpackEncoder.BeginEncode(headers, frame.HeadersPayload, out var length); frame.PayloadLength = length; if (done) { frame.HeadersFlags = Http2HeadersFrameFlags.END_HEADERS; } if (endStream) { frame.HeadersFlags |= Http2HeadersFrameFlags.END_STREAM; } await SendAsync(frame.Raw); while (!done) { frame.PrepareContinuation(Http2ContinuationFrameFlags.NONE, streamId); done = _hpackEncoder.Encode(frame.HeadersPayload, out length); frame.PayloadLength = length; if (done) { frame.ContinuationFlags = Http2ContinuationFrameFlags.END_HEADERS; } await SendAsync(frame.Raw); } }
protected async Task SendHeadersWithPriorityAsync(int streamId, IEnumerable <KeyValuePair <string, string> > headers, byte priority, int streamDependency, bool endStream) { var tcs = new TaskCompletionSource <object>(TaskCreationOptions.RunContinuationsAsynchronously); _runningStreams[streamId] = tcs; var frame = new Http2Frame(Http2Limits.MinAllowedMaxFrameSize); frame.PrepareHeaders(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.PRIORITY, streamId); frame.HeadersPriorityWeight = priority; frame.HeadersStreamDependency = streamDependency; _hpackEncoder.BeginEncode(headers, frame.HeadersPayload, out var length); frame.PayloadLength = 5 + length; if (endStream) { frame.HeadersFlags |= Http2HeadersFrameFlags.END_STREAM; } await SendAsync(frame.Raw); }
protected async Task SendHeadersWithPaddingAsync(int streamId, IEnumerable <KeyValuePair <string, string> > headers, byte padLength, bool endStream) { var tcs = new TaskCompletionSource <object>(TaskCreationOptions.RunContinuationsAsynchronously); _runningStreams[streamId] = tcs; var frame = new Http2Frame(Http2Limits.MinAllowedMaxFrameSize); frame.PrepareHeaders(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.PADDED, streamId); frame.HeadersPadLength = padLength; _hpackEncoder.BeginEncode(headers, frame.HeadersPayload, out var length); frame.PayloadLength = 1 + length + padLength; frame.Payload.Slice(1 + length).Fill(0); if (endStream) { frame.HeadersFlags |= Http2HeadersFrameFlags.END_STREAM; } await SendAsync(frame.Raw); }
/* https://tools.ietf.org/html/rfc7540#section-6.2 +---------------+ |Pad Length? (8)| +-+-------------+-----------------------------------------------+ |E| Stream Dependency? (31) | +-+-------------+-----------------------------------------------+ | Weight? (8) | +-+-------------+-----------------------------------------------+ | Header Block Fragment (*) ... +---------------------------------------------------------------+ | Padding (*) ... +---------------------------------------------------------------+ */ public Task SendHeadersWithPaddingAndPriorityAsync(int streamId, IEnumerable <KeyValuePair <string, string> > headers, byte padLength, byte priority, int streamDependency, bool endStream) { var writableBuffer = _pair.Application.Output; var frame = new Http2Frame(); frame.PrepareHeaders(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.PADDED | Http2HeadersFrameFlags.PRIORITY, streamId); frame.HeadersPadLength = padLength; frame.HeadersPriorityWeight = priority; frame.HeadersStreamDependency = streamDependency; var extendedHeaderLength = 6; // pad length + stream dependency + weight var buffer = _headerEncodingBuffer.AsSpan(); var extendedHeader = buffer.Slice(0, extendedHeaderLength); extendedHeader[0] = padLength; Bitshifter.WriteUInt31BigEndian(extendedHeader.Slice(1), (uint)streamDependency); extendedHeader[5] = priority; var payload = buffer.Slice(extendedHeaderLength, buffer.Length - padLength - extendedHeaderLength); HPackHeaderWriter.BeginEncodeHeaders(GetHeadersEnumerator(headers), payload, out var length); var padding = buffer.Slice(extendedHeaderLength + length, padLength); padding.Clear(); frame.PayloadLength = extendedHeaderLength + length + padLength; if (endStream) { frame.HeadersFlags |= Http2HeadersFrameFlags.END_STREAM; } WriteHeader(frame, writableBuffer); writableBuffer.Write(buffer.Slice(0, frame.PayloadLength)); return(FlushAsync(writableBuffer)); }