104 lines
4.0 KiB
C#
104 lines
4.0 KiB
C#
// Copyright (c) .NET Foundation. All rights reserved.
|
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
|
|
using System;
|
|
using System.Buffers;
|
|
using System.Buffers.Binary;
|
|
using System.Collections.Generic;
|
|
using System.IO.Pipelines;
|
|
using System.Net.Http.HPack;
|
|
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2;
|
|
|
|
namespace Microsoft.AspNetCore.Testing
|
|
{
|
|
internal static class PipeWriterHttp2FrameExtensions
|
|
{
|
|
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 static void WriteStartStream(this PipeWriter writer, int streamId, Http2HeadersEnumerator headers, byte[] headerEncodingBuffer, bool endStream, Http2Frame frame = null)
|
|
{
|
|
frame ??= new Http2Frame();
|
|
frame.PrepareHeaders(Http2HeadersFrameFlags.NONE, streamId);
|
|
|
|
var buffer = headerEncodingBuffer.AsSpan();
|
|
var done = HPackHeaderWriter.BeginEncodeHeaders(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 = HPackHeaderWriter.ContinueEncodeHeaders(headers, buffer, out length);
|
|
frame.PayloadLength = length;
|
|
|
|
if (done)
|
|
{
|
|
frame.ContinuationFlags = Http2ContinuationFrameFlags.END_HEADERS;
|
|
}
|
|
|
|
Http2FrameWriter.WriteHeader(frame, writer);
|
|
writer.Write(buffer.Slice(0, length));
|
|
}
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
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 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);
|
|
}
|
|
}
|
|
}
|