File: src\Servers\Kestrel\shared\test\PipeWriterHttp2FrameExtensions.cs
Web Access
Project: src\src\Servers\Kestrel\test\InMemory.FunctionalTests\InMemory.FunctionalTests.csproj (InMemory.FunctionalTests)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
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;
using Http2HeadersEnumerator = Microsoft.AspNetCore.Server.Kestrel.Core.Tests.Http2HeadersEnumerator;
using HPackHeaderWriter = Microsoft.AspNetCore.Server.Kestrel.Core.Tests.HPackHeaderWriter;
using HeaderWriteResult = Microsoft.AspNetCore.Server.Kestrel.Core.Tests.HeaderWriteResult;
 
namespace Microsoft.AspNetCore.InternalTesting;
 
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, DynamicHPackEncoder hpackEncoder, 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(hpackEncoder, headers, buffer, out var length);
        frame.PayloadLength = length;
 
        if (done == HeaderWriteResult.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 != HeaderWriteResult.Done)
        {
            frame.PrepareContinuation(Http2ContinuationFrameFlags.NONE, streamId);
 
            done = HPackHeaderWriter.ContinueEncodeHeaders(hpackEncoder, headers, buffer, out length);
            frame.PayloadLength = length;
 
            if (done == HeaderWriteResult.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);
    }
}