/* 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; } Http2FrameWriter.WriteHeader(frame, writableBuffer); writableBuffer.Write(buffer.Slice(0, frame.PayloadLength)); return(FlushAsync(writableBuffer)); }
public static void WriteWindowUpdateAsync(this PipeWriter writer, int streamId, int sizeIncrement, Http2Frame frame = null) { frame ??= new Http2Frame(); frame.PrepareWindowUpdate(streamId, sizeIncrement); Http2FrameWriter.WriteHeader(frame, writer); BinaryPrimitives.WriteUInt32BigEndian(writer.GetSpan(4), (uint)sizeIncrement); writer.Advance(4); }
public Task SendGoAwayAsync() { var outputWriter = _pair.Application.Output; var frame = new Http2Frame(); frame.PrepareGoAway(0, Http2ErrorCode.NO_ERROR); Http2FrameWriter.WriteHeader(frame, outputWriter); return(SendAsync(new byte[frame.PayloadLength])); }
internal Task SendPingAsync(Http2PingFrameFlags flags) { var outputWriter = _pair.Application.Output; var pingFrame = new Http2Frame(); pingFrame.PreparePing(flags); Http2FrameWriter.WriteHeader(pingFrame, outputWriter); return(SendAsync(new byte[8])); // Empty payload }
public Task SendInvalidWindowUpdateAsync(int streamId, int sizeIncrement, int length) { var outputWriter = _pair.Application.Output; var frame = new Http2Frame(); frame.PrepareWindowUpdate(streamId, sizeIncrement); frame.PayloadLength = length; Http2FrameWriter.WriteHeader(frame, outputWriter); return(SendAsync(new byte[length])); }
public static void WriteData(this PipeWriter writer, int streamId, Memory <byte> data, bool endStream, Http2Frame frame = null) { frame ??= new Http2Frame(); frame.PrepareData(streamId); frame.PayloadLength = data.Length; frame.DataFlags = endStream ? Http2DataFrameFlags.END_STREAM : Http2DataFrameFlags.NONE; Http2FrameWriter.WriteHeader(frame, writer); writer.Write(data.Span); }
public Task SendPingWithInvalidLengthAsync(int length) { var outputWriter = _pair.Application.Output; var pingFrame = new Http2Frame(); pingFrame.PreparePing(Http2PingFrameFlags.NONE); pingFrame.PayloadLength = length; Http2FrameWriter.WriteHeader(pingFrame, outputWriter); return(SendAsync(new byte[length])); }
public async Task SendSettingsAckWithInvalidLengthAsync(int length) { var writableBuffer = _pair.Application.Output; var frame = new Http2Frame(); frame.PrepareSettings(Http2SettingsFrameFlags.ACK); frame.PayloadLength = length; Http2FrameWriter.WriteHeader(frame, writableBuffer); await SendAsync(new byte[length]); }
public Task SendInvalidRstStreamFrameAsync(int streamId, int length) { var outputWriter = _pair.Application.Output; var frame = new Http2Frame(); frame.PrepareRstStream(streamId, Http2ErrorCode.CANCEL); frame.PayloadLength = length; Http2FrameWriter.WriteHeader(frame, outputWriter); return(SendAsync(new byte[length])); }
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; Http2FrameWriter.WriteHeader(frame, outputWriter); await SendAsync(headerBlock); }
internal Task SendEmptyContinuationFrameAsync(int streamId, Http2ContinuationFrameFlags flags) { var outputWriter = _pair.Application.Output; var frame = new Http2Frame(); frame.PrepareContinuation(flags, streamId); frame.PayloadLength = 0; Http2FrameWriter.WriteHeader(frame, outputWriter); return(FlushAsync(outputWriter)); }
public Task SendUnknownFrameTypeAsync(int streamId, int frameType) { var outputWriter = _pair.Application.Output; var frame = new Http2Frame(); frame.StreamId = streamId; frame.Type = (Http2FrameType)frameType; frame.PayloadLength = 0; Http2FrameWriter.WriteHeader(frame, outputWriter); return(FlushAsync(outputWriter)); }
public Task SendInvalidPriorityFrameAsync(int streamId, int length) { var outputWriter = _pair.Application.Output; var priorityFrame = new Http2Frame(); priorityFrame.PreparePriority(streamId, streamDependency: 0, exclusive: false, weight: 0); priorityFrame.PayloadLength = length; Http2FrameWriter.WriteHeader(priorityFrame, outputWriter); return(SendAsync(new byte[length])); }
internal async Task SendContinuationAsync(int streamId, Http2ContinuationFrameFlags flags, byte[] payload) { var outputWriter = _pair.Application.Output; var frame = new Http2Frame(); frame.PrepareContinuation(flags, streamId); frame.PayloadLength = payload.Length; Http2FrameWriter.WriteHeader(frame, outputWriter); await SendAsync(payload); }
public Task SendPingWithInvalidStreamIdAsync(int streamId) { Assert.NotEqual(0, streamId); var outputWriter = _pair.Application.Output; var pingFrame = new Http2Frame(); pingFrame.PreparePing(Http2PingFrameFlags.NONE); pingFrame.StreamId = streamId; Http2FrameWriter.WriteHeader(pingFrame, outputWriter); return(SendAsync(new byte[pingFrame.PayloadLength])); }
public Task SendDataAsync(int streamId, Memory <byte> data, bool endStream) { var outputWriter = _pair.Application.Output; var frame = new Http2Frame(); frame.PrepareData(streamId); frame.PayloadLength = data.Length; frame.DataFlags = endStream ? Http2DataFrameFlags.END_STREAM : Http2DataFrameFlags.NONE; Http2FrameWriter.WriteHeader(frame, outputWriter); return(SendAsync(data.Span)); }
public Task SendPushPromiseFrameAsync() { var writableBuffer = _pair.Application.Output; var frame = new Http2Frame(); frame.PayloadLength = 0; frame.Type = Http2FrameType.PUSH_PROMISE; frame.StreamId = 1; Http2FrameWriter.WriteHeader(frame, writableBuffer); return(FlushAsync(writableBuffer)); }
/* https://tools.ietf.org/html/rfc7540#section-6.4 +---------------------------------------------------------------+ | Error Code (32) | +---------------------------------------------------------------+ */ public Task SendRstStreamAsync(int streamId) { var outputWriter = _pair.Application.Output; var rstStreamFrame = new Http2Frame(); rstStreamFrame.PrepareRstStream(streamId, Http2ErrorCode.CANCEL); var payload = new byte[rstStreamFrame.PayloadLength]; BinaryPrimitives.WriteUInt32BigEndian(payload, (uint)Http2ErrorCode.CANCEL); Http2FrameWriter.WriteHeader(rstStreamFrame, outputWriter); return(SendAsync(payload)); }
public static void WriteSettings(this PipeWriter writer, Http2PeerSettings clientSettings) { var frame = new Http2Frame(); frame.PrepareSettings(Http2SettingsFrameFlags.NONE); var settings = clientSettings.GetNonProtocolDefaults(); var payload = new byte[settings.Count * Http2FrameReader.SettingSize]; frame.PayloadLength = payload.Length; Http2FrameWriter.WriteSettings(settings, payload); Http2FrameWriter.WriteHeader(frame, writer); writer.Write(payload); }
public Task SendWindowUpdateAsync(int streamId, int sizeIncrement) { var outputWriter = _pair.Application.Output; var frame = new Http2Frame(); frame.PrepareWindowUpdate(streamId, sizeIncrement); Http2FrameWriter.WriteHeader(frame, outputWriter); var buffer = outputWriter.GetSpan(4); BinaryPrimitives.WriteUInt32BigEndian(buffer, (uint)sizeIncrement); outputWriter.Advance(4); return(FlushAsync(outputWriter)); }
protected async Task SendSettingsWithInvalidLengthAsync(int length) { var writableBuffer = _pair.Application.Output; var frame = new Http2Frame(); frame.PrepareSettings(Http2SettingsFrameFlags.NONE); frame.PayloadLength = length; var payload = new byte[length]; Http2FrameWriter.WriteHeader(frame, writableBuffer); await SendAsync(payload); }
public async Task SendSettingsAsync() { var writableBuffer = _pair.Application.Output; var frame = new Http2Frame(); frame.PrepareSettings(Http2SettingsFrameFlags.NONE); var settings = _clientSettings.GetNonProtocolDefaults(); var payload = new byte[settings.Count * Http2FrameReader.SettingSize]; frame.PayloadLength = payload.Length; Http2FrameWriter.WriteSettings(settings, payload); Http2FrameWriter.WriteHeader(frame, writableBuffer); await SendAsync(payload); }
/* https://tools.ietf.org/html/rfc7540#section-6.3 +-+-------------------------------------------------------------+ |E| Stream Dependency (31) | +-+-------------+-----------------------------------------------+ | Weight (8) | +-+-------------+ */ public Task SendPriorityAsync(int streamId, int streamDependency = 0) { var outputWriter = _pair.Application.Output; var priorityFrame = new Http2Frame(); priorityFrame.PreparePriority(streamId, streamDependency: streamDependency, exclusive: false, weight: 0); var payload = new byte[priorityFrame.PayloadLength].AsSpan(); Bitshifter.WriteUInt31BigEndian(payload, (uint)streamDependency); payload[4] = 0; // Weight Http2FrameWriter.WriteHeader(priorityFrame, outputWriter); return(SendAsync(payload)); }
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); }
protected async Task <bool> SendContinuationAsync(int streamId, Http2ContinuationFrameFlags flags) { var outputWriter = _pair.Application.Output; var frame = new Http2Frame(); frame.PrepareContinuation(flags, streamId); var buffer = _headerEncodingBuffer.AsMemory(); var done = _hpackEncoder.Encode(buffer.Span, out var length); frame.PayloadLength = length; Http2FrameWriter.WriteHeader(frame, outputWriter); await SendAsync(buffer.Span.Slice(0, length)); return(done); }
internal async Task <bool> SendContinuationAsync(int streamId, Http2ContinuationFrameFlags flags, IEnumerable <KeyValuePair <string, string> > headers) { var outputWriter = _pair.Application.Output; var frame = new Http2Frame(); frame.PrepareContinuation(flags, streamId); var buffer = _headerEncodingBuffer.AsMemory(); var done = _hpackEncoder.BeginEncode(headers, buffer.Span, out var length); frame.PayloadLength = length; Http2FrameWriter.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 async Task WriteHeader_UnsetsReservedBit() { // Arrange var pipe = new Pipe(new PipeOptions(_dirtyMemoryPool, PipeScheduler.Inline, PipeScheduler.Inline)); var frame = new Http2Frame(); frame.PreparePing(Http2PingFrameFlags.NONE); // Act Http2FrameWriter.WriteHeader(frame, pipe.Writer); await pipe.Writer.FlushAsync(); // Assert var payload = await pipe.Reader.ReadForLengthAsync(Http2FrameReader.HeaderLength); Assert.Equal(new byte[] { 0x00, 0x00, 0x00, 0x00 }, payload.Skip(5).Take(4).ToArray()); }
public async Task SendIncompleteContinuationFrameAsync(int streamId) { var outputWriter = _pair.Application.Output; var frame = new Http2Frame(); frame.PrepareContinuation(Http2ContinuationFrameFlags.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'; Http2FrameWriter.WriteHeader(frame, outputWriter); await SendAsync(payload); }