Merge release/2.1
This commit is contained in:
commit
261b5836c1
|
|
@ -16,7 +16,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
|||
{
|
||||
private const int InnerLoopCount = 512;
|
||||
|
||||
public ReadOnlyBuffer _buffer;
|
||||
public ReadOnlyBuffer<byte> _buffer;
|
||||
public Http1Connection _http1Connection;
|
||||
|
||||
[IterationSetup]
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
|||
private static readonly Func<object, Task> _psuedoAsyncTaskFunc = (obj) => _psuedoAsyncTask;
|
||||
|
||||
private readonly TestHttp1Connection _http1Connection;
|
||||
private (IPipeConnection Transport, IPipeConnection Application) _pair;
|
||||
private (IDuplexPipe Transport, IDuplexPipe Application) _pair;
|
||||
|
||||
private readonly byte[] _writeData;
|
||||
|
||||
|
|
@ -128,7 +128,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
|||
var reader = _pair.Application.Input;
|
||||
if (reader.TryRead(out var readResult))
|
||||
{
|
||||
reader.Advance(readResult.Buffer.End);
|
||||
reader.AdvanceTo(readResult.Buffer.End);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
|||
{
|
||||
private readonly HttpParser<Adapter> _parser = new HttpParser<Adapter>();
|
||||
|
||||
private ReadOnlyBuffer _buffer;
|
||||
private ReadOnlyBuffer<byte> _buffer;
|
||||
|
||||
[Benchmark(Baseline = true, OperationsPerInvoke = RequestParsingData.InnerLoopCount)]
|
||||
public void PlaintextTechEmpower()
|
||||
|
|
@ -47,7 +47,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
|||
|
||||
private void InsertData(byte[] data)
|
||||
{
|
||||
_buffer = new ReadOnlyBuffer(data);
|
||||
_buffer = new ReadOnlyBuffer<byte>(data);
|
||||
}
|
||||
|
||||
private void ParseData()
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Collections;
|
||||
using System.Collections.Sequences;
|
||||
using System.IO.Pipelines;
|
||||
using System.Text;
|
||||
|
|
@ -23,7 +24,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
|||
|
||||
public static readonly NullParser<Http1ParsingHandler> Instance = new NullParser<Http1ParsingHandler>();
|
||||
|
||||
public bool ParseHeaders(TRequestHandler handler, ReadOnlyBuffer buffer, out Position consumed, out Position examined, out int consumedBytes)
|
||||
public bool ParseHeaders(TRequestHandler handler, ReadOnlyBuffer<byte> buffer, out SequencePosition consumed, out SequencePosition examined, out int consumedBytes)
|
||||
{
|
||||
handler.OnHeader(new Span<byte>(_hostHeaderName), new Span<byte>(_hostHeaderValue));
|
||||
handler.OnHeader(new Span<byte>(_acceptHeaderName), new Span<byte>(_acceptHeaderValue));
|
||||
|
|
@ -36,7 +37,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
|||
return true;
|
||||
}
|
||||
|
||||
public bool ParseRequestLine(TRequestHandler handler, ReadOnlyBuffer buffer, out Position consumed, out Position examined)
|
||||
public bool ParseRequestLine(TRequestHandler handler, ReadOnlyBuffer<byte> buffer, out SequencePosition consumed, out SequencePosition examined)
|
||||
{
|
||||
handler.OnStartLine(HttpMethod.Get,
|
||||
HttpVersion.Http11,
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
|||
private const int _writeLenght = 57;
|
||||
private const int InnerLoopCount = 512;
|
||||
|
||||
private IPipe _pipe;
|
||||
private Pipe _pipe;
|
||||
private MemoryPool _memoryPool;
|
||||
|
||||
[IterationSetup]
|
||||
|
|
@ -30,9 +30,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
|||
{
|
||||
for (int i = 0; i < InnerLoopCount; i++)
|
||||
{
|
||||
var writableBuffer = _pipe.Writer.Alloc(_writeLenght);
|
||||
writableBuffer.Advance(_writeLenght);
|
||||
await writableBuffer.FlushAsync();
|
||||
_pipe.Writer.GetMemory(_writeLenght);
|
||||
_pipe.Writer.Advance(_writeLenght);
|
||||
await _pipe.Writer.FlushAsync();
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -43,7 +43,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
|||
{
|
||||
var result = await _pipe.Reader.ReadAsync();
|
||||
remaining -= result.Buffer.Length;
|
||||
_pipe.Reader.Advance(result.Buffer.End, result.Buffer.End);
|
||||
_pipe.Reader.AdvanceTo(result.Buffer.End, result.Buffer.End);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -55,11 +55,11 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
|||
{
|
||||
for (int i = 0; i < InnerLoopCount; i++)
|
||||
{
|
||||
var writableBuffer = _pipe.Writer.Alloc(_writeLenght);
|
||||
writableBuffer.Advance(_writeLenght);
|
||||
writableBuffer.FlushAsync().GetAwaiter().GetResult();
|
||||
_pipe.Writer.GetMemory(_writeLenght);
|
||||
_pipe.Writer.Advance(_writeLenght);
|
||||
_pipe.Writer.FlushAsync().GetAwaiter().GetResult();
|
||||
var result = _pipe.Reader.ReadAsync().GetAwaiter().GetResult();
|
||||
_pipe.Reader.Advance(result.Buffer.End, result.Buffer.End);
|
||||
_pipe.Reader.AdvanceTo(result.Buffer.End, result.Buffer.End);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
|||
{
|
||||
public class RequestParsingBenchmark
|
||||
{
|
||||
public IPipe Pipe { get; set; }
|
||||
public Pipe Pipe { get; set; }
|
||||
|
||||
public Http1Connection Http1Connection { get; set; }
|
||||
|
||||
|
|
@ -130,10 +130,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
|||
|
||||
private void InsertData(byte[] bytes)
|
||||
{
|
||||
var buffer = Pipe.Writer.Alloc(2048);
|
||||
buffer.Write(bytes);
|
||||
Pipe.Writer.Write(bytes);
|
||||
// There should not be any backpressure and task completes immediately
|
||||
buffer.FlushAsync().GetAwaiter().GetResult();
|
||||
Pipe.Writer.FlushAsync().GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
private void ParseDataDrainBuffer()
|
||||
|
|
@ -166,7 +165,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
|||
}
|
||||
while (readableBuffer.Length > 0);
|
||||
|
||||
Pipe.Reader.Advance(readableBuffer.End);
|
||||
Pipe.Reader.AdvanceTo(readableBuffer.End);
|
||||
}
|
||||
|
||||
private void ParseData()
|
||||
|
|
@ -189,7 +188,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
|||
{
|
||||
ErrorUtilities.ThrowInvalidRequestLine();
|
||||
}
|
||||
Pipe.Reader.Advance(consumed, examined);
|
||||
Pipe.Reader.AdvanceTo(consumed, examined);
|
||||
|
||||
result = Pipe.Reader.ReadAsync().GetAwaiter().GetResult();
|
||||
readableBuffer = result.Buffer;
|
||||
|
|
@ -198,7 +197,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
|||
{
|
||||
ErrorUtilities.ThrowInvalidRequestHeaders();
|
||||
}
|
||||
Pipe.Reader.Advance(consumed, examined);
|
||||
Pipe.Reader.AdvanceTo(consumed, examined);
|
||||
}
|
||||
while (true);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
<Project>
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
|
||||
</PropertyGroup>
|
||||
|
|
@ -25,24 +25,24 @@
|
|||
<MicrosoftExtensionsLoggingTestingPackageVersion>2.1.0-preview1-27965</MicrosoftExtensionsLoggingTestingPackageVersion>
|
||||
<MicrosoftExtensionsOptionsPackageVersion>2.1.0-preview1-27965</MicrosoftExtensionsOptionsPackageVersion>
|
||||
<MicrosoftNETCoreApp20PackageVersion>2.0.0</MicrosoftNETCoreApp20PackageVersion>
|
||||
<MicrosoftNETCoreApp21PackageVersion>2.1.0-preview1-26102-01</MicrosoftNETCoreApp21PackageVersion>
|
||||
<MicrosoftNETCoreApp21PackageVersion>2.1.0-preview2-26124-07</MicrosoftNETCoreApp21PackageVersion>
|
||||
<MicrosoftNetHttpHeadersPackageVersion>2.1.0-preview1-27965</MicrosoftNetHttpHeadersPackageVersion>
|
||||
<MicrosoftNETTestSdkPackageVersion>15.3.0</MicrosoftNETTestSdkPackageVersion>
|
||||
<MoqPackageVersion>4.7.49</MoqPackageVersion>
|
||||
<NewtonsoftJsonPackageVersion>10.0.1</NewtonsoftJsonPackageVersion>
|
||||
<SystemBuffersPackageVersion>4.5.0-preview1-26102-01</SystemBuffersPackageVersion>
|
||||
<SystemBuffersPrimitivesPackageVersion>0.1.0-e180104-2</SystemBuffersPrimitivesPackageVersion>
|
||||
<SystemIOPipelinesPackageVersion>0.1.0-e180104-2</SystemIOPipelinesPackageVersion>
|
||||
<SystemIOPipelinesTestingPackageVersion>0.1.0-e180104-2</SystemIOPipelinesTestingPackageVersion>
|
||||
<SystemMemoryPackageVersion>4.5.0-preview1-26102-01</SystemMemoryPackageVersion>
|
||||
<SystemNumericsVectorsPackageVersion>4.5.0-preview1-26102-01</SystemNumericsVectorsPackageVersion>
|
||||
<SystemRuntimeCompilerServicesUnsafePackageVersion>4.5.0-preview1-26102-01</SystemRuntimeCompilerServicesUnsafePackageVersion>
|
||||
<SystemSecurityCryptographyCngPackageVersion>4.5.0-preview1-26102-01</SystemSecurityCryptographyCngPackageVersion>
|
||||
<SystemTextEncodingsWebUtf8PackageVersion>0.1.0-e180104-2</SystemTextEncodingsWebUtf8PackageVersion>
|
||||
<SystemBuffersPackageVersion>4.5.0-preview2-26125-06</SystemBuffersPackageVersion>
|
||||
<SystemBuffersPrimitivesPackageVersion>0.1.0-preview2-180130-1</SystemBuffersPrimitivesPackageVersion>
|
||||
<SystemIOPipelinesPackageVersion>0.1.0-preview2-180130-1</SystemIOPipelinesPackageVersion>
|
||||
<SystemIOPipelinesTestingPackageVersion>0.1.0-preview2-180130-1</SystemIOPipelinesTestingPackageVersion>
|
||||
<SystemMemoryPackageVersion>4.5.0-preview2-26125-06</SystemMemoryPackageVersion>
|
||||
<SystemNumericsVectorsPackageVersion>4.5.0-preview2-26125-06</SystemNumericsVectorsPackageVersion>
|
||||
<SystemRuntimeCompilerServicesUnsafePackageVersion>4.5.0-preview2-26125-06</SystemRuntimeCompilerServicesUnsafePackageVersion>
|
||||
<SystemSecurityCryptographyCngPackageVersion>4.5.0-preview2-26125-06</SystemSecurityCryptographyCngPackageVersion>
|
||||
<SystemTextEncodingsWebUtf8PackageVersion>0.1.0-preview2-180130-1</SystemTextEncodingsWebUtf8PackageVersion>
|
||||
<SystemThreadingTasksExtensionsPackageVersion>4.5.0-preview2-25707-02</SystemThreadingTasksExtensionsPackageVersion>
|
||||
<XunitAnalyzersPackageVersion>0.8.0</XunitAnalyzersPackageVersion>
|
||||
<XunitPackageVersion>2.3.1</XunitPackageVersion>
|
||||
<XunitRunnerVisualStudioPackageVersion>2.3.1</XunitRunnerVisualStudioPackageVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(DotNetPackageVersionPropsPath)" Condition=" '$(DotNetPackageVersionPropsPath)' != '' " />
|
||||
</Project>
|
||||
</Project>
|
||||
|
|
@ -10,17 +10,17 @@ using System.Runtime.InteropServices;
|
|||
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Adapter.Internal
|
||||
{
|
||||
public class AdaptedPipeline : IPipeConnection
|
||||
public class AdaptedPipeline : IDuplexPipe
|
||||
{
|
||||
private const int MinAllocBufferSize = 2048;
|
||||
|
||||
private readonly IPipeConnection _transport;
|
||||
private readonly IPipeConnection _application;
|
||||
private readonly IDuplexPipe _transport;
|
||||
private readonly IDuplexPipe _application;
|
||||
|
||||
public AdaptedPipeline(IPipeConnection transport,
|
||||
IPipeConnection application,
|
||||
IPipe inputPipe,
|
||||
IPipe outputPipe)
|
||||
public AdaptedPipeline(IDuplexPipe transport,
|
||||
IDuplexPipe application,
|
||||
Pipe inputPipe,
|
||||
Pipe outputPipe)
|
||||
{
|
||||
_transport = transport;
|
||||
_application = application;
|
||||
|
|
@ -28,13 +28,13 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Adapter.Internal
|
|||
Output = outputPipe;
|
||||
}
|
||||
|
||||
public IPipe Input { get; }
|
||||
public Pipe Input { get; }
|
||||
|
||||
public IPipe Output { get; }
|
||||
public Pipe Output { get; }
|
||||
|
||||
IPipeReader IPipeConnection.Input => Input.Reader;
|
||||
PipeReader IDuplexPipe.Input => Input.Reader;
|
||||
|
||||
IPipeWriter IPipeConnection.Output => Output.Writer;
|
||||
PipeWriter IDuplexPipe.Output => Output.Writer;
|
||||
|
||||
public async Task RunAsync(Stream stream)
|
||||
{
|
||||
|
|
@ -78,7 +78,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Adapter.Internal
|
|||
}
|
||||
await stream.FlushAsync();
|
||||
}
|
||||
else if (buffer.IsSingleSpan)
|
||||
else if (buffer.IsSingleSegment)
|
||||
{
|
||||
var array = buffer.First.GetArray();
|
||||
await stream.WriteAsync(array.Array, array.Offset, array.Count);
|
||||
|
|
@ -94,7 +94,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Adapter.Internal
|
|||
}
|
||||
finally
|
||||
{
|
||||
Output.Reader.Advance(buffer.End);
|
||||
Output.Reader.AdvanceTo(buffer.End);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -124,13 +124,13 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Adapter.Internal
|
|||
while (true)
|
||||
{
|
||||
|
||||
var outputBuffer = Input.Writer.Alloc(MinAllocBufferSize);
|
||||
var outputBuffer = Input.Writer.GetMemory(MinAllocBufferSize);
|
||||
|
||||
var array = outputBuffer.Buffer.GetArray();
|
||||
var array = outputBuffer.GetArray();
|
||||
try
|
||||
{
|
||||
var bytesRead = await stream.ReadAsync(array.Array, array.Offset, array.Count);
|
||||
outputBuffer.Advance(bytesRead);
|
||||
Input.Writer.Advance(bytesRead);
|
||||
|
||||
if (bytesRead == 0)
|
||||
{
|
||||
|
|
@ -140,10 +140,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Adapter.Internal
|
|||
}
|
||||
finally
|
||||
{
|
||||
outputBuffer.Commit();
|
||||
Input.Writer.Commit();
|
||||
}
|
||||
|
||||
var result = await outputBuffer.FlushAsync();
|
||||
var result = await Input.Writer.FlushAsync();
|
||||
|
||||
if (result.IsCompleted)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -6,15 +6,16 @@ using System.IO.Pipelines;
|
|||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Buffers;
|
||||
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Adapter.Internal
|
||||
{
|
||||
public class RawStream : Stream
|
||||
{
|
||||
private readonly IPipeReader _input;
|
||||
private readonly IPipeWriter _output;
|
||||
private readonly PipeReader _input;
|
||||
private readonly PipeWriter _output;
|
||||
|
||||
public RawStream(IPipeReader input, IPipeWriter output)
|
||||
public RawStream(PipeReader input, PipeWriter output)
|
||||
{
|
||||
_input = input;
|
||||
_output = output;
|
||||
|
|
@ -75,14 +76,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Adapter.Internal
|
|||
|
||||
public override async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken token)
|
||||
{
|
||||
var output = _output.Alloc();
|
||||
|
||||
if (buffer != null)
|
||||
{
|
||||
output.Write(new ArraySegment<byte>(buffer, offset, count));
|
||||
_output.Write(new ReadOnlySpan<byte>(buffer, offset, count));
|
||||
}
|
||||
|
||||
await output.FlushAsync(token);
|
||||
await _output.FlushAsync(token);
|
||||
}
|
||||
|
||||
public override void Flush()
|
||||
|
|
@ -118,7 +117,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Adapter.Internal
|
|||
}
|
||||
finally
|
||||
{
|
||||
_input.Advance(readableBuffer.End, readableBuffer.End);
|
||||
_input.AdvanceTo(readableBuffer.End, readableBuffer.End);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -83,22 +83,22 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
|
|||
}
|
||||
|
||||
// Internal for testing
|
||||
internal static PipeOptions GetInputPipeOptions(ServiceContext serviceContext, MemoryPool memoryPool, Scheduler writerScheduler) => new PipeOptions
|
||||
internal static PipeOptions GetInputPipeOptions(ServiceContext serviceContext, MemoryPool memoryPool, PipeScheduler writerScheduler) => new PipeOptions
|
||||
(
|
||||
pool: memoryPool,
|
||||
readerScheduler: serviceContext.ThreadPool,
|
||||
writerScheduler: writerScheduler,
|
||||
maximumSizeHigh: serviceContext.ServerOptions.Limits.MaxRequestBufferSize ?? 0,
|
||||
maximumSizeLow: serviceContext.ServerOptions.Limits.MaxRequestBufferSize ?? 0
|
||||
pauseWriterThreshold: serviceContext.ServerOptions.Limits.MaxRequestBufferSize ?? 0,
|
||||
resumeWriterThreshold: serviceContext.ServerOptions.Limits.MaxRequestBufferSize ?? 0
|
||||
);
|
||||
|
||||
internal static PipeOptions GetOutputPipeOptions(ServiceContext serviceContext, MemoryPool memoryPool, Scheduler readerScheduler) => new PipeOptions
|
||||
internal static PipeOptions GetOutputPipeOptions(ServiceContext serviceContext, MemoryPool memoryPool, PipeScheduler readerScheduler) => new PipeOptions
|
||||
(
|
||||
pool: memoryPool,
|
||||
readerScheduler: readerScheduler,
|
||||
writerScheduler: serviceContext.ThreadPool,
|
||||
maximumSizeHigh: GetOutputResponseBufferSize(serviceContext),
|
||||
maximumSizeLow: GetOutputResponseBufferSize(serviceContext)
|
||||
pauseWriterThreshold: GetOutputResponseBufferSize(serviceContext),
|
||||
resumeWriterThreshold: GetOutputResponseBufferSize(serviceContext)
|
||||
);
|
||||
|
||||
private static long GetOutputResponseBufferSize(ServiceContext serviceContext)
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
// 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.IO.Pipelines;
|
||||
using System.Text;
|
||||
|
||||
|
|
@ -47,16 +48,16 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
return new ArraySegment<byte>(bytes, offset, 10 - offset);
|
||||
}
|
||||
|
||||
public static int WriteBeginChunkBytes(ref WritableBufferWriter start, int dataCount)
|
||||
public static int WriteBeginChunkBytes(ref OutputWriter<PipeWriter> start, int dataCount)
|
||||
{
|
||||
var chunkSegment = BeginChunkBytes(dataCount);
|
||||
start.Write(chunkSegment.Array, chunkSegment.Offset, chunkSegment.Count);
|
||||
start.Write(new ReadOnlySpan<byte>(chunkSegment.Array, chunkSegment.Offset, chunkSegment.Count));
|
||||
return chunkSegment.Count;
|
||||
}
|
||||
|
||||
public static void WriteEndChunkBytes(ref WritableBufferWriter start)
|
||||
public static void WriteEndChunkBytes(ref OutputWriter<PipeWriter> start)
|
||||
{
|
||||
start.Write(_endChunkBytes.Array, _endChunkBytes.Offset, _endChunkBytes.Count);
|
||||
start.Write(new ReadOnlySpan<byte>(_endChunkBytes.Array, _endChunkBytes.Offset, _endChunkBytes.Count));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Collections;
|
||||
using System.Collections.Sequences;
|
||||
using System.Diagnostics;
|
||||
using System.IO.Pipelines;
|
||||
|
|
@ -45,7 +46,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
Output = new Http1OutputProducer(_context.Application.Input, _context.Transport.Output, _context.ConnectionId, _context.ServiceContext.Log, _context.TimeoutControl);
|
||||
}
|
||||
|
||||
public IPipeReader Input => _context.Transport.Input;
|
||||
public PipeReader Input => _context.Transport.Input;
|
||||
|
||||
public ITimeoutControl TimeoutControl => _context.TimeoutControl;
|
||||
public bool RequestTimedOut => _requestTimedOut;
|
||||
|
|
@ -69,7 +70,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
Input.CancelPendingRead();
|
||||
}
|
||||
|
||||
public void ParseRequest(ReadOnlyBuffer buffer, out Position consumed, out Position examined)
|
||||
public void ParseRequest(ReadOnlyBuffer<byte> buffer, out SequencePosition consumed, out SequencePosition examined)
|
||||
{
|
||||
consumed = buffer.Start;
|
||||
examined = buffer.End;
|
||||
|
|
@ -107,7 +108,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
}
|
||||
}
|
||||
|
||||
public bool TakeStartLine(ReadOnlyBuffer buffer, out Position consumed, out Position examined)
|
||||
public bool TakeStartLine(ReadOnlyBuffer<byte> buffer, out SequencePosition consumed, out SequencePosition examined)
|
||||
{
|
||||
var overLength = false;
|
||||
if (buffer.Length >= ServerOptions.Limits.MaxRequestLineSize)
|
||||
|
|
@ -125,7 +126,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
return result;
|
||||
}
|
||||
|
||||
public bool TakeMessageHeaders(ReadOnlyBuffer buffer, out Position consumed, out Position examined)
|
||||
public bool TakeMessageHeaders(ReadOnlyBuffer<byte> buffer, out SequencePosition consumed, out SequencePosition examined)
|
||||
{
|
||||
// Make sure the buffer is limited
|
||||
bool overLength = false;
|
||||
|
|
@ -453,7 +454,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
}
|
||||
finally
|
||||
{
|
||||
Input.Advance(consumed, examined);
|
||||
Input.AdvanceTo(consumed, examined);
|
||||
}
|
||||
|
||||
if (result.IsCompleted)
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
public IPEndPoint RemoteEndPoint { get; set; }
|
||||
public IPEndPoint LocalEndPoint { get; set; }
|
||||
public ITimeoutControl TimeoutControl { get; set; }
|
||||
public IPipeConnection Transport { get; set; }
|
||||
public IPipeConnection Application { get; set; }
|
||||
public IDuplexPipe Transport { get; set; }
|
||||
public IDuplexPipe Application { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Collections;
|
||||
using System.Collections.Sequences;
|
||||
using System.IO;
|
||||
using System.IO.Pipelines;
|
||||
|
|
@ -62,19 +63,18 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
|
||||
if (!readableBuffer.IsEmpty)
|
||||
{
|
||||
var writableBuffer = _context.RequestBodyPipe.Writer.Alloc(1);
|
||||
bool done;
|
||||
|
||||
try
|
||||
{
|
||||
done = Read(readableBuffer, writableBuffer, out consumed, out examined);
|
||||
done = Read(readableBuffer, _context.RequestBodyPipe.Writer, out consumed, out examined);
|
||||
}
|
||||
finally
|
||||
{
|
||||
writableBuffer.Commit();
|
||||
_context.RequestBodyPipe.Writer.Commit();
|
||||
}
|
||||
|
||||
var writeAwaitable = writableBuffer.FlushAsync();
|
||||
var writeAwaitable = _context.RequestBodyPipe.Writer.FlushAsync();
|
||||
var backpressure = false;
|
||||
|
||||
if (!writeAwaitable.IsCompleted)
|
||||
|
|
@ -105,7 +105,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
}
|
||||
finally
|
||||
{
|
||||
_context.Input.Advance(consumed, examined);
|
||||
_context.Input.AdvanceTo(consumed, examined);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -142,7 +142,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
do
|
||||
{
|
||||
result = await _context.RequestBodyPipe.Reader.ReadAsync();
|
||||
_context.RequestBodyPipe.Reader.Advance(result.Buffer.End);
|
||||
_context.RequestBodyPipe.Reader.AdvanceTo(result.Buffer.End);
|
||||
} while (!result.IsCompleted);
|
||||
}
|
||||
finally
|
||||
|
|
@ -151,11 +151,11 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
}
|
||||
}
|
||||
|
||||
protected void Copy(ReadOnlyBuffer readableBuffer, WritableBuffer writableBuffer)
|
||||
protected void Copy(ReadOnlyBuffer<byte> readableBuffer, PipeWriter writableBuffer)
|
||||
{
|
||||
_context.TimeoutControl.BytesRead(readableBuffer.Length);
|
||||
|
||||
if (readableBuffer.IsSingleSpan)
|
||||
if (readableBuffer.IsSingleSegment)
|
||||
{
|
||||
writableBuffer.Write(readableBuffer.First.Span);
|
||||
}
|
||||
|
|
@ -173,7 +173,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
_pumpTask = PumpAsync();
|
||||
}
|
||||
|
||||
protected virtual bool Read(ReadOnlyBuffer readableBuffer, WritableBuffer writableBuffer, out Position consumed, out Position examined)
|
||||
protected virtual bool Read(ReadOnlyBuffer<byte> readableBuffer, PipeWriter writableBuffer, out SequencePosition consumed, out SequencePosition examined)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
|
@ -294,7 +294,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
RequestUpgrade = true;
|
||||
}
|
||||
|
||||
protected override bool Read(ReadOnlyBuffer readableBuffer, WritableBuffer writableBuffer, out Position consumed, out Position examined)
|
||||
protected override bool Read(ReadOnlyBuffer<byte> readableBuffer, PipeWriter writableBuffer, out SequencePosition consumed, out SequencePosition examined)
|
||||
{
|
||||
Copy(readableBuffer, writableBuffer);
|
||||
consumed = readableBuffer.End;
|
||||
|
|
@ -316,7 +316,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
_inputLength = _contentLength;
|
||||
}
|
||||
|
||||
protected override bool Read(ReadOnlyBuffer readableBuffer, WritableBuffer writableBuffer, out Position consumed, out Position examined)
|
||||
protected override bool Read(ReadOnlyBuffer<byte> readableBuffer, PipeWriter writableBuffer, out SequencePosition consumed, out SequencePosition examined)
|
||||
{
|
||||
if (_inputLength == 0)
|
||||
{
|
||||
|
|
@ -326,7 +326,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var actual = (int)Math.Min(readableBuffer.Length, _inputLength);
|
||||
_inputLength -= actual;
|
||||
|
||||
consumed = readableBuffer.Move(readableBuffer.Start, actual);
|
||||
consumed = readableBuffer.GetPosition(readableBuffer.Start, actual);
|
||||
examined = consumed;
|
||||
|
||||
Copy(readableBuffer.Slice(0, actual), writableBuffer);
|
||||
|
|
@ -364,10 +364,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
RequestKeepAlive = keepAlive;
|
||||
}
|
||||
|
||||
protected override bool Read(ReadOnlyBuffer readableBuffer, WritableBuffer writableBuffer, out Position consumed, out Position examined)
|
||||
protected override bool Read(ReadOnlyBuffer<byte> readableBuffer, PipeWriter writableBuffer, out SequencePosition consumed, out SequencePosition examined)
|
||||
{
|
||||
consumed = default(Position);
|
||||
examined = default(Position);
|
||||
consumed = default(SequencePosition);
|
||||
examined = default(SequencePosition);
|
||||
|
||||
while (_mode < Mode.Trailer)
|
||||
{
|
||||
|
|
@ -455,13 +455,13 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
}
|
||||
}
|
||||
|
||||
private void ParseChunkedPrefix(ReadOnlyBuffer buffer, out Position consumed, out Position examined)
|
||||
private void ParseChunkedPrefix(ReadOnlyBuffer<byte> buffer, out SequencePosition consumed, out SequencePosition examined)
|
||||
{
|
||||
consumed = buffer.Start;
|
||||
examined = buffer.Start;
|
||||
var reader = BufferReader.Create(buffer);
|
||||
var ch1 = reader.Take();
|
||||
var ch2 = reader.Take();
|
||||
var ch1 = reader.Read();
|
||||
var ch2 = reader.Read();
|
||||
|
||||
if (ch1 == -1 || ch2 == -1)
|
||||
{
|
||||
|
|
@ -485,7 +485,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
return;
|
||||
}
|
||||
|
||||
ch2 = reader.Take();
|
||||
ch2 = reader.Read();
|
||||
if (ch2 == -1)
|
||||
{
|
||||
examined = reader.Position;
|
||||
|
|
@ -511,7 +511,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
_context.ThrowRequestRejected(RequestRejectionReason.BadChunkSizeData);
|
||||
}
|
||||
|
||||
private void ParseExtension(ReadOnlyBuffer buffer, out Position consumed, out Position examined)
|
||||
private void ParseExtension(ReadOnlyBuffer<byte> buffer, out SequencePosition consumed, out SequencePosition examined)
|
||||
{
|
||||
// Chunk-extensions not currently parsed
|
||||
// Just drain the data
|
||||
|
|
@ -520,8 +520,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
|
||||
do
|
||||
{
|
||||
Position extensionCursor;
|
||||
if (ReadOnlyBuffer.Seek(buffer.Start, buffer.End, out extensionCursor, ByteCR) == -1)
|
||||
SequencePosition? extensionCursorPosition = buffer.PositionOf(ByteCR);
|
||||
if (extensionCursorPosition == null)
|
||||
{
|
||||
// End marker not found yet
|
||||
consumed = buffer.End;
|
||||
|
|
@ -530,6 +530,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
return;
|
||||
};
|
||||
|
||||
var extensionCursor = extensionCursorPosition.Value;
|
||||
var charsToByteCRExclusive = buffer.Slice(0, extensionCursor).Length;
|
||||
|
||||
var sufixBuffer = buffer.Slice(extensionCursor);
|
||||
|
|
@ -563,10 +564,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
} while (_mode == Mode.Extension);
|
||||
}
|
||||
|
||||
private void ReadChunkedData(ReadOnlyBuffer buffer, WritableBuffer writableBuffer, out Position consumed, out Position examined)
|
||||
private void ReadChunkedData(ReadOnlyBuffer<byte> buffer, PipeWriter writableBuffer, out SequencePosition consumed, out SequencePosition examined)
|
||||
{
|
||||
var actual = Math.Min(buffer.Length, _inputLength);
|
||||
consumed = buffer.Move(buffer.Start, actual);
|
||||
consumed = buffer.GetPosition(buffer.Start, actual);
|
||||
examined = consumed;
|
||||
|
||||
Copy(buffer.Slice(0, actual), writableBuffer);
|
||||
|
|
@ -580,7 +581,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
}
|
||||
}
|
||||
|
||||
private void ParseChunkedSuffix(ReadOnlyBuffer buffer, out Position consumed, out Position examined)
|
||||
private void ParseChunkedSuffix(ReadOnlyBuffer<byte> buffer, out SequencePosition consumed, out SequencePosition examined)
|
||||
{
|
||||
consumed = buffer.Start;
|
||||
examined = buffer.Start;
|
||||
|
|
@ -606,7 +607,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
}
|
||||
}
|
||||
|
||||
private void ParseChunkedTrailer(ReadOnlyBuffer buffer, out Position consumed, out Position examined)
|
||||
private void ParseChunkedTrailer(ReadOnlyBuffer<byte> buffer, out SequencePosition consumed, out SequencePosition examined)
|
||||
{
|
||||
consumed = buffer.Start;
|
||||
examined = buffer.Start;
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
// 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.Diagnostics;
|
||||
using System.IO.Pipelines;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
|
@ -28,8 +29,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
|
||||
private bool _completed = false;
|
||||
|
||||
private readonly IPipeWriter _pipeWriter;
|
||||
private readonly IPipeReader _outputPipeReader;
|
||||
private readonly PipeWriter _pipeWriter;
|
||||
private readonly PipeReader _outputPipeReader;
|
||||
|
||||
// https://github.com/dotnet/corefxlab/issues/1334
|
||||
// Pipelines don't support multiple awaiters on flush
|
||||
|
|
@ -39,8 +40,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
private Action _flushCompleted;
|
||||
|
||||
public Http1OutputProducer(
|
||||
IPipeReader outputPipeReader,
|
||||
IPipeWriter pipeWriter,
|
||||
PipeReader outputPipeReader,
|
||||
PipeWriter pipeWriter,
|
||||
string connectionId,
|
||||
IKestrelTrace log,
|
||||
ITimeoutControl timeoutControl)
|
||||
|
|
@ -73,7 +74,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
return WriteAsync(Constants.EmptyData, cancellationToken);
|
||||
}
|
||||
|
||||
public void Write<T>(Action<WritableBuffer, T> callback, T state)
|
||||
public void Write<T>(Action<PipeWriter, T> callback, T state)
|
||||
{
|
||||
lock (_contextLock)
|
||||
{
|
||||
|
|
@ -82,13 +83,13 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
return;
|
||||
}
|
||||
|
||||
var buffer = _pipeWriter.Alloc(1);
|
||||
var buffer = _pipeWriter;
|
||||
callback(buffer, state);
|
||||
buffer.Commit();
|
||||
}
|
||||
}
|
||||
|
||||
public Task WriteAsync<T>(Action<WritableBuffer, T> callback, T state)
|
||||
public Task WriteAsync<T>(Action<PipeWriter, T> callback, T state)
|
||||
{
|
||||
lock (_contextLock)
|
||||
{
|
||||
|
|
@ -97,7 +98,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
var buffer = _pipeWriter.Alloc(1);
|
||||
var buffer = _pipeWriter;
|
||||
callback(buffer, state);
|
||||
buffer.Commit();
|
||||
}
|
||||
|
|
@ -114,8 +115,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
return;
|
||||
}
|
||||
|
||||
var buffer = _pipeWriter.Alloc(1);
|
||||
var writer = new WritableBufferWriter(buffer);
|
||||
var buffer = _pipeWriter;
|
||||
var writer = OutputWriter.Create(buffer);
|
||||
|
||||
writer.Write(_bytesHttpVersion11);
|
||||
var statusBytes = ReasonPhrases.ToStatusBytes(statusCode, reasonPhrase);
|
||||
|
|
@ -167,7 +168,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
ArraySegment<byte> buffer,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var writableBuffer = default(WritableBuffer);
|
||||
var writableBuffer = default(PipeWriter);
|
||||
long bytesWritten = 0;
|
||||
lock (_contextLock)
|
||||
{
|
||||
|
|
@ -176,11 +177,11 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
writableBuffer = _pipeWriter.Alloc(1);
|
||||
var writer = new WritableBufferWriter(writableBuffer);
|
||||
writableBuffer = _pipeWriter;
|
||||
var writer = OutputWriter.Create(writableBuffer);
|
||||
if (buffer.Count > 0)
|
||||
{
|
||||
writer.Write(buffer.Array, buffer.Offset, buffer.Count);
|
||||
writer.Write(new ReadOnlySpan<byte>(buffer.Array, buffer.Offset, buffer.Count));
|
||||
bytesWritten += buffer.Count;
|
||||
}
|
||||
|
||||
|
|
@ -192,7 +193,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
|
||||
// Single caller, at end of method - so inline
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private Task FlushAsync(WritableBuffer writableBuffer, long bytesWritten, CancellationToken cancellationToken)
|
||||
private Task FlushAsync(PipeWriter writableBuffer, long bytesWritten, CancellationToken cancellationToken)
|
||||
{
|
||||
var awaitable = writableBuffer.FlushAsync(cancellationToken);
|
||||
if (awaitable.IsCompleted)
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
|
||||
using System.Buffers;
|
||||
using System.IO.Pipelines;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
|
|
@ -7753,7 +7754,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
return true;
|
||||
}
|
||||
|
||||
protected void CopyToFast(ref WritableBufferWriter output)
|
||||
protected void CopyToFast(ref OutputWriter<PipeWriter> output)
|
||||
{
|
||||
var tempBits = _bits | (_contentLength.HasValue ? -9223372036854775808L : 0);
|
||||
|
||||
|
|
@ -7771,7 +7772,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._Connection[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.Write(_headerBytes, 17, 14);
|
||||
output.Write(new ReadOnlySpan<byte>(_headerBytes, 17, 14));
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
|
|
@ -7797,7 +7798,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._Date[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.Write(_headerBytes, 31, 8);
|
||||
output.Write(new ReadOnlySpan<byte>(_headerBytes, 31, 8));
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
|
|
@ -7818,7 +7819,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._ContentType[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.Write(_headerBytes, 133, 16);
|
||||
output.Write(new ReadOnlySpan<byte>(_headerBytes, 133, 16));
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
|
|
@ -7844,7 +7845,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._Server[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.Write(_headerBytes, 350, 10);
|
||||
output.Write(new ReadOnlySpan<byte>(_headerBytes, 350, 10));
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
|
|
@ -7858,7 +7859,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
}
|
||||
if ((tempBits & -9223372036854775808L) != 0)
|
||||
{
|
||||
output.Write(_headerBytes, 592, 18);
|
||||
output.Write(new ReadOnlySpan<byte>(_headerBytes, 592, 18));
|
||||
PipelineExtensions.WriteNumeric(ref output, (ulong)ContentLength.Value);
|
||||
|
||||
if((tempBits & ~-9223372036854775808L) == 0)
|
||||
|
|
@ -7876,7 +7877,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._CacheControl[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.Write(_headerBytes, 0, 17);
|
||||
output.Write(new ReadOnlySpan<byte>(_headerBytes, 0, 17));
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
|
|
@ -7897,7 +7898,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._KeepAlive[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.Write(_headerBytes, 39, 14);
|
||||
output.Write(new ReadOnlySpan<byte>(_headerBytes, 39, 14));
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
|
|
@ -7918,7 +7919,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._Pragma[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.Write(_headerBytes, 53, 10);
|
||||
output.Write(new ReadOnlySpan<byte>(_headerBytes, 53, 10));
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
|
|
@ -7939,7 +7940,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._Trailer[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.Write(_headerBytes, 63, 11);
|
||||
output.Write(new ReadOnlySpan<byte>(_headerBytes, 63, 11));
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
|
|
@ -7965,7 +7966,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._TransferEncoding[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.Write(_headerBytes, 74, 21);
|
||||
output.Write(new ReadOnlySpan<byte>(_headerBytes, 74, 21));
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
|
|
@ -7986,7 +7987,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._Upgrade[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.Write(_headerBytes, 95, 11);
|
||||
output.Write(new ReadOnlySpan<byte>(_headerBytes, 95, 11));
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
|
|
@ -8007,7 +8008,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._Via[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.Write(_headerBytes, 106, 7);
|
||||
output.Write(new ReadOnlySpan<byte>(_headerBytes, 106, 7));
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
|
|
@ -8028,7 +8029,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._Warning[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.Write(_headerBytes, 113, 11);
|
||||
output.Write(new ReadOnlySpan<byte>(_headerBytes, 113, 11));
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
|
|
@ -8049,7 +8050,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._Allow[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.Write(_headerBytes, 124, 9);
|
||||
output.Write(new ReadOnlySpan<byte>(_headerBytes, 124, 9));
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
|
|
@ -8070,7 +8071,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._ContentEncoding[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.Write(_headerBytes, 149, 20);
|
||||
output.Write(new ReadOnlySpan<byte>(_headerBytes, 149, 20));
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
|
|
@ -8091,7 +8092,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._ContentLanguage[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.Write(_headerBytes, 169, 20);
|
||||
output.Write(new ReadOnlySpan<byte>(_headerBytes, 169, 20));
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
|
|
@ -8112,7 +8113,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._ContentLocation[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.Write(_headerBytes, 189, 20);
|
||||
output.Write(new ReadOnlySpan<byte>(_headerBytes, 189, 20));
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
|
|
@ -8133,7 +8134,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._ContentMD5[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.Write(_headerBytes, 209, 15);
|
||||
output.Write(new ReadOnlySpan<byte>(_headerBytes, 209, 15));
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
|
|
@ -8154,7 +8155,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._ContentRange[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.Write(_headerBytes, 224, 17);
|
||||
output.Write(new ReadOnlySpan<byte>(_headerBytes, 224, 17));
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
|
|
@ -8175,7 +8176,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._Expires[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.Write(_headerBytes, 241, 11);
|
||||
output.Write(new ReadOnlySpan<byte>(_headerBytes, 241, 11));
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
|
|
@ -8196,7 +8197,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._LastModified[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.Write(_headerBytes, 252, 17);
|
||||
output.Write(new ReadOnlySpan<byte>(_headerBytes, 252, 17));
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
|
|
@ -8217,7 +8218,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._AcceptRanges[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.Write(_headerBytes, 269, 17);
|
||||
output.Write(new ReadOnlySpan<byte>(_headerBytes, 269, 17));
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
|
|
@ -8238,7 +8239,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._Age[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.Write(_headerBytes, 286, 7);
|
||||
output.Write(new ReadOnlySpan<byte>(_headerBytes, 286, 7));
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
|
|
@ -8259,7 +8260,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._ETag[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.Write(_headerBytes, 293, 8);
|
||||
output.Write(new ReadOnlySpan<byte>(_headerBytes, 293, 8));
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
|
|
@ -8280,7 +8281,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._Location[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.Write(_headerBytes, 301, 12);
|
||||
output.Write(new ReadOnlySpan<byte>(_headerBytes, 301, 12));
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
|
|
@ -8301,7 +8302,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._ProxyAuthenticate[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.Write(_headerBytes, 313, 22);
|
||||
output.Write(new ReadOnlySpan<byte>(_headerBytes, 313, 22));
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
|
|
@ -8322,7 +8323,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._RetryAfter[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.Write(_headerBytes, 335, 15);
|
||||
output.Write(new ReadOnlySpan<byte>(_headerBytes, 335, 15));
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
|
|
@ -8343,7 +8344,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._SetCookie[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.Write(_headerBytes, 360, 14);
|
||||
output.Write(new ReadOnlySpan<byte>(_headerBytes, 360, 14));
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
|
|
@ -8364,7 +8365,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._Vary[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.Write(_headerBytes, 374, 8);
|
||||
output.Write(new ReadOnlySpan<byte>(_headerBytes, 374, 8));
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
|
|
@ -8385,7 +8386,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._WWWAuthenticate[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.Write(_headerBytes, 382, 20);
|
||||
output.Write(new ReadOnlySpan<byte>(_headerBytes, 382, 20));
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
|
|
@ -8406,7 +8407,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._AccessControlAllowCredentials[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.Write(_headerBytes, 402, 36);
|
||||
output.Write(new ReadOnlySpan<byte>(_headerBytes, 402, 36));
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
|
|
@ -8427,7 +8428,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._AccessControlAllowHeaders[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.Write(_headerBytes, 438, 32);
|
||||
output.Write(new ReadOnlySpan<byte>(_headerBytes, 438, 32));
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
|
|
@ -8448,7 +8449,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._AccessControlAllowMethods[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.Write(_headerBytes, 470, 32);
|
||||
output.Write(new ReadOnlySpan<byte>(_headerBytes, 470, 32));
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
|
|
@ -8469,7 +8470,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._AccessControlAllowOrigin[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.Write(_headerBytes, 502, 31);
|
||||
output.Write(new ReadOnlySpan<byte>(_headerBytes, 502, 31));
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
|
|
@ -8490,7 +8491,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._AccessControlExposeHeaders[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.Write(_headerBytes, 533, 33);
|
||||
output.Write(new ReadOnlySpan<byte>(_headerBytes, 533, 33));
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
|
|
@ -8511,7 +8512,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._AccessControlMaxAge[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.Write(_headerBytes, 566, 26);
|
||||
output.Write(new ReadOnlySpan<byte>(_headerBytes, 566, 26));
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Collections;
|
||||
using System.Collections.Sequences;
|
||||
using System.IO.Pipelines;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
|
@ -33,7 +34,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
private const byte ByteQuestionMark = (byte)'?';
|
||||
private const byte BytePercentage = (byte)'%';
|
||||
|
||||
public unsafe bool ParseRequestLine(TRequestHandler handler, ReadOnlyBuffer buffer, out Position consumed, out Position examined)
|
||||
public unsafe bool ParseRequestLine(TRequestHandler handler, ReadOnlyBuffer<byte> buffer, out SequencePosition consumed, out SequencePosition examined)
|
||||
{
|
||||
consumed = buffer.Start;
|
||||
examined = buffer.End;
|
||||
|
|
@ -43,10 +44,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var lineIndex = span.IndexOf(ByteLF);
|
||||
if (lineIndex >= 0)
|
||||
{
|
||||
consumed = buffer.Move(consumed, lineIndex + 1);
|
||||
consumed = buffer.GetPosition(consumed, lineIndex + 1);
|
||||
span = span.Slice(0, lineIndex + 1);
|
||||
}
|
||||
else if (buffer.IsSingleSpan)
|
||||
else if (buffer.IsSingleSegment)
|
||||
{
|
||||
// No request line end
|
||||
return false;
|
||||
|
|
@ -188,7 +189,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
handler.OnStartLine(method, httpVersion, targetBuffer, pathBuffer, query, customMethod, pathEncoded);
|
||||
}
|
||||
|
||||
public unsafe bool ParseHeaders(TRequestHandler handler, ReadOnlyBuffer buffer, out Position consumed, out Position examined, out int consumedBytes)
|
||||
public unsafe bool ParseHeaders(TRequestHandler handler, ReadOnlyBuffer<byte> buffer, out SequencePosition consumed, out SequencePosition examined, out int consumedBytes)
|
||||
{
|
||||
consumed = buffer.Start;
|
||||
examined = buffer.End;
|
||||
|
|
@ -197,21 +198,21 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var bufferEnd = buffer.End;
|
||||
|
||||
var reader = BufferReader.Create(buffer);
|
||||
var start = default(BufferReader<ReadOnlyBuffer>);
|
||||
var start = default(BufferReader<ReadOnlyBuffer<byte>>);
|
||||
var done = false;
|
||||
|
||||
try
|
||||
{
|
||||
while (!reader.End)
|
||||
{
|
||||
var span = reader.Span;
|
||||
var remaining = span.Length - reader.Index;
|
||||
var span = reader.CurrentSegment;
|
||||
var remaining = span.Length - reader.CurrentSegmentIndex;
|
||||
|
||||
fixed (byte* pBuffer = &MemoryMarshal.GetReference(span))
|
||||
{
|
||||
while (remaining > 0)
|
||||
{
|
||||
var index = reader.Index;
|
||||
var index = reader.CurrentSegmentIndex;
|
||||
int ch1;
|
||||
int ch2;
|
||||
|
||||
|
|
@ -228,8 +229,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
start = reader;
|
||||
|
||||
// Possibly split across spans
|
||||
ch1 = reader.Take();
|
||||
ch2 = reader.Take();
|
||||
ch1 = reader.Read();
|
||||
ch2 = reader.Read();
|
||||
}
|
||||
|
||||
if (ch1 == ByteCR)
|
||||
|
|
@ -245,9 +246,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
{
|
||||
// If we got 2 bytes from the span directly so skip ahead 2 so that
|
||||
// the reader's state matches what we expect
|
||||
if (index == reader.Index)
|
||||
if (index == reader.CurrentSegmentIndex)
|
||||
{
|
||||
reader.Skip(2);
|
||||
reader.Advance(2);
|
||||
}
|
||||
|
||||
done = true;
|
||||
|
|
@ -260,10 +261,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
|
||||
// We moved the reader so look ahead 2 bytes so reset both the reader
|
||||
// and the index
|
||||
if (index != reader.Index)
|
||||
if (index != reader.CurrentSegmentIndex)
|
||||
{
|
||||
reader = start;
|
||||
index = reader.Index;
|
||||
index = reader.CurrentSegmentIndex;
|
||||
}
|
||||
|
||||
var endIndex = new Span<byte>(pBuffer + index, remaining).IndexOf(ByteLF);
|
||||
|
|
@ -279,16 +280,20 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
else
|
||||
{
|
||||
var current = reader.Position;
|
||||
var currentSlice = buffer.Slice(current, bufferEnd);
|
||||
|
||||
var lineEndPosition = currentSlice.PositionOf(ByteLF);
|
||||
// Split buffers
|
||||
if (ReadOnlyBuffer.Seek(current, bufferEnd, out var lineEnd, ByteLF) == -1)
|
||||
if (lineEndPosition == null)
|
||||
{
|
||||
// Not there
|
||||
return false;
|
||||
}
|
||||
|
||||
var lineEnd = lineEndPosition.Value;
|
||||
|
||||
// Make sure LF is included in lineEnd
|
||||
lineEnd = buffer.Move(lineEnd, 1);
|
||||
lineEnd = buffer.GetPosition(lineEnd, 1);
|
||||
var headerSpan = buffer.Slice(current, lineEnd).ToSpan();
|
||||
length = headerSpan.Length;
|
||||
|
||||
|
|
@ -304,7 +309,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
}
|
||||
|
||||
// Skip the reader forward past the header line
|
||||
reader.Skip(length);
|
||||
reader.Advance(length);
|
||||
remaining -= length;
|
||||
}
|
||||
}
|
||||
|
|
@ -414,15 +419,17 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
private static bool TryGetNewLine(ref ReadOnlyBuffer buffer, out Position found)
|
||||
private static bool TryGetNewLine(ref ReadOnlyBuffer<byte> buffer, out SequencePosition found)
|
||||
{
|
||||
var start = buffer.Start;
|
||||
if (ReadOnlyBuffer.Seek(start, buffer.End, out found, ByteLF) != -1)
|
||||
var byteLfPosition = buffer.PositionOf(ByteLF);
|
||||
if (byteLfPosition != null)
|
||||
{
|
||||
// Move 1 byte past the \n
|
||||
found = buffer.Move(found, 1);
|
||||
found = buffer.GetPosition(byteLfPosition.Value, 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
found = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,31 +4,35 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
using Microsoft.AspNetCore.Http.Features.Authentication;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Features;
|
||||
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
||||
{
|
||||
public partial class HttpProtocol
|
||||
{
|
||||
private static readonly Type IHttpRequestFeatureType = typeof(global::Microsoft.AspNetCore.Http.Features.IHttpRequestFeature);
|
||||
private static readonly Type IHttpResponseFeatureType = typeof(global::Microsoft.AspNetCore.Http.Features.IHttpResponseFeature);
|
||||
private static readonly Type IHttpRequestIdentifierFeatureType = typeof(global::Microsoft.AspNetCore.Http.Features.IHttpRequestIdentifierFeature);
|
||||
private static readonly Type IServiceProvidersFeatureType = typeof(global::Microsoft.AspNetCore.Http.Features.IServiceProvidersFeature);
|
||||
private static readonly Type IHttpRequestLifetimeFeatureType = typeof(global::Microsoft.AspNetCore.Http.Features.IHttpRequestLifetimeFeature);
|
||||
private static readonly Type IHttpConnectionFeatureType = typeof(global::Microsoft.AspNetCore.Http.Features.IHttpConnectionFeature);
|
||||
private static readonly Type IHttpAuthenticationFeatureType = typeof(global::Microsoft.AspNetCore.Http.Features.Authentication.IHttpAuthenticationFeature);
|
||||
private static readonly Type IQueryFeatureType = typeof(global::Microsoft.AspNetCore.Http.Features.IQueryFeature);
|
||||
private static readonly Type IFormFeatureType = typeof(global::Microsoft.AspNetCore.Http.Features.IFormFeature);
|
||||
private static readonly Type IHttpUpgradeFeatureType = typeof(global::Microsoft.AspNetCore.Http.Features.IHttpUpgradeFeature);
|
||||
private static readonly Type IHttp2StreamIdFeatureType = typeof(global::Microsoft.AspNetCore.Server.Kestrel.Core.Features.IHttp2StreamIdFeature);
|
||||
private static readonly Type IResponseCookiesFeatureType = typeof(global::Microsoft.AspNetCore.Http.Features.IResponseCookiesFeature);
|
||||
private static readonly Type IItemsFeatureType = typeof(global::Microsoft.AspNetCore.Http.Features.IItemsFeature);
|
||||
private static readonly Type ITlsConnectionFeatureType = typeof(global::Microsoft.AspNetCore.Http.Features.ITlsConnectionFeature);
|
||||
private static readonly Type IHttpWebSocketFeatureType = typeof(global::Microsoft.AspNetCore.Http.Features.IHttpWebSocketFeature);
|
||||
private static readonly Type ISessionFeatureType = typeof(global::Microsoft.AspNetCore.Http.Features.ISessionFeature);
|
||||
private static readonly Type IHttpMaxRequestBodySizeFeatureType = typeof(global::Microsoft.AspNetCore.Http.Features.IHttpMaxRequestBodySizeFeature);
|
||||
private static readonly Type IHttpMinRequestBodyDataRateFeatureType = typeof(global::Microsoft.AspNetCore.Server.Kestrel.Core.Features.IHttpMinRequestBodyDataRateFeature);
|
||||
private static readonly Type IHttpMinResponseDataRateFeatureType = typeof(global::Microsoft.AspNetCore.Server.Kestrel.Core.Features.IHttpMinResponseDataRateFeature);
|
||||
private static readonly Type IHttpBodyControlFeatureType = typeof(global::Microsoft.AspNetCore.Http.Features.IHttpBodyControlFeature);
|
||||
private static readonly Type IHttpSendFileFeatureType = typeof(global::Microsoft.AspNetCore.Http.Features.IHttpSendFileFeature);
|
||||
private static readonly Type IHttpRequestFeatureType = typeof(IHttpRequestFeature);
|
||||
private static readonly Type IHttpResponseFeatureType = typeof(IHttpResponseFeature);
|
||||
private static readonly Type IHttpRequestIdentifierFeatureType = typeof(IHttpRequestIdentifierFeature);
|
||||
private static readonly Type IServiceProvidersFeatureType = typeof(IServiceProvidersFeature);
|
||||
private static readonly Type IHttpRequestLifetimeFeatureType = typeof(IHttpRequestLifetimeFeature);
|
||||
private static readonly Type IHttpConnectionFeatureType = typeof(IHttpConnectionFeature);
|
||||
private static readonly Type IHttpAuthenticationFeatureType = typeof(IHttpAuthenticationFeature);
|
||||
private static readonly Type IQueryFeatureType = typeof(IQueryFeature);
|
||||
private static readonly Type IFormFeatureType = typeof(IFormFeature);
|
||||
private static readonly Type IHttpUpgradeFeatureType = typeof(IHttpUpgradeFeature);
|
||||
private static readonly Type IHttp2StreamIdFeatureType = typeof(IHttp2StreamIdFeature);
|
||||
private static readonly Type IResponseCookiesFeatureType = typeof(IResponseCookiesFeature);
|
||||
private static readonly Type IItemsFeatureType = typeof(IItemsFeature);
|
||||
private static readonly Type ITlsConnectionFeatureType = typeof(ITlsConnectionFeature);
|
||||
private static readonly Type IHttpWebSocketFeatureType = typeof(IHttpWebSocketFeature);
|
||||
private static readonly Type ISessionFeatureType = typeof(ISessionFeature);
|
||||
private static readonly Type IHttpMaxRequestBodySizeFeatureType = typeof(IHttpMaxRequestBodySizeFeature);
|
||||
private static readonly Type IHttpMinRequestBodyDataRateFeatureType = typeof(IHttpMinRequestBodyDataRateFeature);
|
||||
private static readonly Type IHttpMinResponseDataRateFeatureType = typeof(IHttpMinResponseDataRateFeature);
|
||||
private static readonly Type IHttpBodyControlFeatureType = typeof(IHttpBodyControlFeature);
|
||||
private static readonly Type IHttpSendFileFeatureType = typeof(IHttpSendFileFeature);
|
||||
|
||||
private object _currentIHttpRequestFeature;
|
||||
private object _currentIHttpResponseFeature;
|
||||
|
|
@ -283,87 +287,87 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
{
|
||||
if (_currentIHttpRequestFeature != null)
|
||||
{
|
||||
yield return new KeyValuePair<Type, object>(IHttpRequestFeatureType, _currentIHttpRequestFeature as global::Microsoft.AspNetCore.Http.Features.IHttpRequestFeature);
|
||||
yield return new KeyValuePair<Type, object>(IHttpRequestFeatureType, _currentIHttpRequestFeature as IHttpRequestFeature);
|
||||
}
|
||||
if (_currentIHttpResponseFeature != null)
|
||||
{
|
||||
yield return new KeyValuePair<Type, object>(IHttpResponseFeatureType, _currentIHttpResponseFeature as global::Microsoft.AspNetCore.Http.Features.IHttpResponseFeature);
|
||||
yield return new KeyValuePair<Type, object>(IHttpResponseFeatureType, _currentIHttpResponseFeature as IHttpResponseFeature);
|
||||
}
|
||||
if (_currentIHttpRequestIdentifierFeature != null)
|
||||
{
|
||||
yield return new KeyValuePair<Type, object>(IHttpRequestIdentifierFeatureType, _currentIHttpRequestIdentifierFeature as global::Microsoft.AspNetCore.Http.Features.IHttpRequestIdentifierFeature);
|
||||
yield return new KeyValuePair<Type, object>(IHttpRequestIdentifierFeatureType, _currentIHttpRequestIdentifierFeature as IHttpRequestIdentifierFeature);
|
||||
}
|
||||
if (_currentIServiceProvidersFeature != null)
|
||||
{
|
||||
yield return new KeyValuePair<Type, object>(IServiceProvidersFeatureType, _currentIServiceProvidersFeature as global::Microsoft.AspNetCore.Http.Features.IServiceProvidersFeature);
|
||||
yield return new KeyValuePair<Type, object>(IServiceProvidersFeatureType, _currentIServiceProvidersFeature as IServiceProvidersFeature);
|
||||
}
|
||||
if (_currentIHttpRequestLifetimeFeature != null)
|
||||
{
|
||||
yield return new KeyValuePair<Type, object>(IHttpRequestLifetimeFeatureType, _currentIHttpRequestLifetimeFeature as global::Microsoft.AspNetCore.Http.Features.IHttpRequestLifetimeFeature);
|
||||
yield return new KeyValuePair<Type, object>(IHttpRequestLifetimeFeatureType, _currentIHttpRequestLifetimeFeature as IHttpRequestLifetimeFeature);
|
||||
}
|
||||
if (_currentIHttpConnectionFeature != null)
|
||||
{
|
||||
yield return new KeyValuePair<Type, object>(IHttpConnectionFeatureType, _currentIHttpConnectionFeature as global::Microsoft.AspNetCore.Http.Features.IHttpConnectionFeature);
|
||||
yield return new KeyValuePair<Type, object>(IHttpConnectionFeatureType, _currentIHttpConnectionFeature as IHttpConnectionFeature);
|
||||
}
|
||||
if (_currentIHttpAuthenticationFeature != null)
|
||||
{
|
||||
yield return new KeyValuePair<Type, object>(IHttpAuthenticationFeatureType, _currentIHttpAuthenticationFeature as global::Microsoft.AspNetCore.Http.Features.Authentication.IHttpAuthenticationFeature);
|
||||
yield return new KeyValuePair<Type, object>(IHttpAuthenticationFeatureType, _currentIHttpAuthenticationFeature as IHttpAuthenticationFeature);
|
||||
}
|
||||
if (_currentIQueryFeature != null)
|
||||
{
|
||||
yield return new KeyValuePair<Type, object>(IQueryFeatureType, _currentIQueryFeature as global::Microsoft.AspNetCore.Http.Features.IQueryFeature);
|
||||
yield return new KeyValuePair<Type, object>(IQueryFeatureType, _currentIQueryFeature as IQueryFeature);
|
||||
}
|
||||
if (_currentIFormFeature != null)
|
||||
{
|
||||
yield return new KeyValuePair<Type, object>(IFormFeatureType, _currentIFormFeature as global::Microsoft.AspNetCore.Http.Features.IFormFeature);
|
||||
yield return new KeyValuePair<Type, object>(IFormFeatureType, _currentIFormFeature as IFormFeature);
|
||||
}
|
||||
if (_currentIHttpUpgradeFeature != null)
|
||||
{
|
||||
yield return new KeyValuePair<Type, object>(IHttpUpgradeFeatureType, _currentIHttpUpgradeFeature as global::Microsoft.AspNetCore.Http.Features.IHttpUpgradeFeature);
|
||||
yield return new KeyValuePair<Type, object>(IHttpUpgradeFeatureType, _currentIHttpUpgradeFeature as IHttpUpgradeFeature);
|
||||
}
|
||||
if (_currentIHttp2StreamIdFeature != null)
|
||||
{
|
||||
yield return new KeyValuePair<Type, object>(IHttp2StreamIdFeatureType, _currentIHttp2StreamIdFeature as global::Microsoft.AspNetCore.Server.Kestrel.Core.Features.IHttp2StreamIdFeature);
|
||||
yield return new KeyValuePair<Type, object>(IHttp2StreamIdFeatureType, _currentIHttp2StreamIdFeature as IHttp2StreamIdFeature);
|
||||
}
|
||||
if (_currentIResponseCookiesFeature != null)
|
||||
{
|
||||
yield return new KeyValuePair<Type, object>(IResponseCookiesFeatureType, _currentIResponseCookiesFeature as global::Microsoft.AspNetCore.Http.Features.IResponseCookiesFeature);
|
||||
yield return new KeyValuePair<Type, object>(IResponseCookiesFeatureType, _currentIResponseCookiesFeature as IResponseCookiesFeature);
|
||||
}
|
||||
if (_currentIItemsFeature != null)
|
||||
{
|
||||
yield return new KeyValuePair<Type, object>(IItemsFeatureType, _currentIItemsFeature as global::Microsoft.AspNetCore.Http.Features.IItemsFeature);
|
||||
yield return new KeyValuePair<Type, object>(IItemsFeatureType, _currentIItemsFeature as IItemsFeature);
|
||||
}
|
||||
if (_currentITlsConnectionFeature != null)
|
||||
{
|
||||
yield return new KeyValuePair<Type, object>(ITlsConnectionFeatureType, _currentITlsConnectionFeature as global::Microsoft.AspNetCore.Http.Features.ITlsConnectionFeature);
|
||||
yield return new KeyValuePair<Type, object>(ITlsConnectionFeatureType, _currentITlsConnectionFeature as ITlsConnectionFeature);
|
||||
}
|
||||
if (_currentIHttpWebSocketFeature != null)
|
||||
{
|
||||
yield return new KeyValuePair<Type, object>(IHttpWebSocketFeatureType, _currentIHttpWebSocketFeature as global::Microsoft.AspNetCore.Http.Features.IHttpWebSocketFeature);
|
||||
yield return new KeyValuePair<Type, object>(IHttpWebSocketFeatureType, _currentIHttpWebSocketFeature as IHttpWebSocketFeature);
|
||||
}
|
||||
if (_currentISessionFeature != null)
|
||||
{
|
||||
yield return new KeyValuePair<Type, object>(ISessionFeatureType, _currentISessionFeature as global::Microsoft.AspNetCore.Http.Features.ISessionFeature);
|
||||
yield return new KeyValuePair<Type, object>(ISessionFeatureType, _currentISessionFeature as ISessionFeature);
|
||||
}
|
||||
if (_currentIHttpMaxRequestBodySizeFeature != null)
|
||||
{
|
||||
yield return new KeyValuePair<Type, object>(IHttpMaxRequestBodySizeFeatureType, _currentIHttpMaxRequestBodySizeFeature as global::Microsoft.AspNetCore.Http.Features.IHttpMaxRequestBodySizeFeature);
|
||||
yield return new KeyValuePair<Type, object>(IHttpMaxRequestBodySizeFeatureType, _currentIHttpMaxRequestBodySizeFeature as IHttpMaxRequestBodySizeFeature);
|
||||
}
|
||||
if (_currentIHttpMinRequestBodyDataRateFeature != null)
|
||||
{
|
||||
yield return new KeyValuePair<Type, object>(IHttpMinRequestBodyDataRateFeatureType, _currentIHttpMinRequestBodyDataRateFeature as global::Microsoft.AspNetCore.Server.Kestrel.Core.Features.IHttpMinRequestBodyDataRateFeature);
|
||||
yield return new KeyValuePair<Type, object>(IHttpMinRequestBodyDataRateFeatureType, _currentIHttpMinRequestBodyDataRateFeature as IHttpMinRequestBodyDataRateFeature);
|
||||
}
|
||||
if (_currentIHttpMinResponseDataRateFeature != null)
|
||||
{
|
||||
yield return new KeyValuePair<Type, object>(IHttpMinResponseDataRateFeatureType, _currentIHttpMinResponseDataRateFeature as global::Microsoft.AspNetCore.Server.Kestrel.Core.Features.IHttpMinResponseDataRateFeature);
|
||||
yield return new KeyValuePair<Type, object>(IHttpMinResponseDataRateFeatureType, _currentIHttpMinResponseDataRateFeature as IHttpMinResponseDataRateFeature);
|
||||
}
|
||||
if (_currentIHttpBodyControlFeature != null)
|
||||
{
|
||||
yield return new KeyValuePair<Type, object>(IHttpBodyControlFeatureType, _currentIHttpBodyControlFeature as global::Microsoft.AspNetCore.Http.Features.IHttpBodyControlFeature);
|
||||
yield return new KeyValuePair<Type, object>(IHttpBodyControlFeatureType, _currentIHttpBodyControlFeature as IHttpBodyControlFeature);
|
||||
}
|
||||
if (_currentIHttpSendFileFeature != null)
|
||||
{
|
||||
yield return new KeyValuePair<Type, object>(IHttpSendFileFeatureType, _currentIHttpSendFileFeature as global::Microsoft.AspNetCore.Http.Features.IHttpSendFileFeature);
|
||||
yield return new KeyValuePair<Type, object>(IHttpSendFileFeatureType, _currentIHttpSendFileFeature as IHttpSendFileFeature);
|
||||
}
|
||||
|
||||
if (MaybeExtra != null)
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
// 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.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
|
|
@ -30,7 +31,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
private static readonly byte[] _bytesConnectionKeepAlive = Encoding.ASCII.GetBytes("\r\nConnection: keep-alive");
|
||||
private static readonly byte[] _bytesTransferEncodingChunked = Encoding.ASCII.GetBytes("\r\nTransfer-Encoding: chunked");
|
||||
private static readonly byte[] _bytesServer = Encoding.ASCII.GetBytes("\r\nServer: " + Constants.ServerName);
|
||||
private static readonly Action<WritableBuffer, ArraySegment<byte>> _writeChunk = WriteChunk;
|
||||
private static readonly Action<PipeWriter, ArraySegment<byte>> _writeChunk = WriteChunk;
|
||||
|
||||
private readonly object _onStartingSync = new Object();
|
||||
private readonly object _onCompletedSync = new Object();
|
||||
|
|
@ -895,13 +896,13 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
return Output.WriteAsync(_writeChunk, data);
|
||||
}
|
||||
|
||||
private static void WriteChunk(WritableBuffer writableBuffer, ArraySegment<byte> buffer)
|
||||
private static void WriteChunk(PipeWriter writableBuffer, ArraySegment<byte> buffer)
|
||||
{
|
||||
var writer = new WritableBufferWriter(writableBuffer);
|
||||
var writer = OutputWriter.Create(writableBuffer);
|
||||
if (buffer.Count > 0)
|
||||
{
|
||||
ChunkWriter.WriteBeginChunkBytes(ref writer, buffer.Count);
|
||||
writer.Write(buffer.Array, buffer.Offset, buffer.Count);
|
||||
writer.Write(new ReadOnlySpan<byte>(buffer.Array, buffer.Offset, buffer.Count));
|
||||
ChunkWriter.WriteEndChunkBytes(ref writer);
|
||||
}
|
||||
}
|
||||
|
|
@ -1297,9 +1298,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
(
|
||||
pool: _context.MemoryPool,
|
||||
readerScheduler: ServiceContext.ThreadPool,
|
||||
writerScheduler: Scheduler.Inline,
|
||||
maximumSizeHigh: 1,
|
||||
maximumSizeLow: 1
|
||||
writerScheduler: PipeScheduler.Inline,
|
||||
pauseWriterThreshold: 1,
|
||||
resumeWriterThreshold: 1
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
// 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.IO.Pipelines;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
|
@ -34,7 +35,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
return GetEnumerator();
|
||||
}
|
||||
|
||||
public void CopyTo(ref WritableBufferWriter output)
|
||||
public void CopyTo(ref OutputWriter<PipeWriter> output)
|
||||
{
|
||||
CopyToFast(ref output);
|
||||
if (MaybeUnknown != null)
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
public interface IHttpOutputProducer : IDisposable
|
||||
{
|
||||
void Abort(Exception error);
|
||||
Task WriteAsync<T>(Action<WritableBuffer, T> callback, T state);
|
||||
Task WriteAsync<T>(Action<PipeWriter, T> callback, T state);
|
||||
Task FlushAsync(CancellationToken cancellationToken);
|
||||
Task Write100ContinueAsync(CancellationToken cancellationToken);
|
||||
void WriteResponseHeaders(int statusCode, string ReasonPhrase, HttpResponseHeaders responseHeaders);
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Buffers;
|
||||
using System.Collections;
|
||||
using System.Collections.Sequences;
|
||||
using System.IO.Pipelines;
|
||||
|
||||
|
|
@ -9,8 +10,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
{
|
||||
public interface IHttpParser<TRequestHandler> where TRequestHandler : IHttpHeadersHandler, IHttpRequestLineHandler
|
||||
{
|
||||
bool ParseRequestLine(TRequestHandler handler, ReadOnlyBuffer buffer, out Position consumed, out Position examined);
|
||||
bool ParseRequestLine(TRequestHandler handler, ReadOnlyBuffer<byte> buffer, out SequencePosition consumed, out SequencePosition examined);
|
||||
|
||||
bool ParseHeaders(TRequestHandler handler, ReadOnlyBuffer buffer, out Position consumed, out Position examined, out int consumedBytes);
|
||||
bool ParseHeaders(TRequestHandler handler, ReadOnlyBuffer<byte> buffer, out SequencePosition consumed, out SequencePosition examined, out int consumedBytes);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
// buffer.Count is int
|
||||
var actual = (int) Math.Min(readableBuffer.Length, buffer.Count);
|
||||
var slice = readableBuffer.Slice(0, actual);
|
||||
consumed = readableBuffer.Move(readableBuffer.Start, actual);
|
||||
consumed = readableBuffer.GetPosition(readableBuffer.Start, actual);
|
||||
slice.CopyTo(buffer);
|
||||
return actual;
|
||||
}
|
||||
|
|
@ -64,7 +64,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
}
|
||||
finally
|
||||
{
|
||||
_context.RequestBodyPipe.Reader.Advance(consumed);
|
||||
_context.RequestBodyPipe.Reader.AdvanceTo(consumed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -96,7 +96,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
}
|
||||
finally
|
||||
{
|
||||
_context.RequestBodyPipe.Reader.Advance(consumed);
|
||||
_context.RequestBodyPipe.Reader.AdvanceTo(consumed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,9 +17,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
private static byte[] _numericBytesScratch;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static ReadOnlySpan<byte> ToSpan(this ReadOnlyBuffer buffer)
|
||||
public static ReadOnlySpan<byte> ToSpan(this ReadOnlyBuffer<byte> buffer)
|
||||
{
|
||||
if (buffer.IsSingleSpan)
|
||||
if (buffer.IsSingleSegment)
|
||||
{
|
||||
return buffer.First.Span;
|
||||
}
|
||||
|
|
@ -45,7 +45,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
return result;
|
||||
}
|
||||
|
||||
public unsafe static void WriteAsciiNoValidation(ref this WritableBufferWriter buffer, string data)
|
||||
public unsafe static void WriteAsciiNoValidation(ref this OutputWriter<PipeWriter> buffer, string data)
|
||||
{
|
||||
if (string.IsNullOrEmpty(data))
|
||||
{
|
||||
|
|
@ -74,7 +74,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public unsafe static void WriteNumeric(ref this WritableBufferWriter buffer, ulong number)
|
||||
public unsafe static void WriteNumeric(ref this OutputWriter<PipeWriter> buffer, ulong number)
|
||||
{
|
||||
const byte AsciiDigitStart = (byte)'0';
|
||||
|
||||
|
|
@ -124,7 +124,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
private static void WriteNumericMultiWrite(ref this WritableBufferWriter buffer, ulong number)
|
||||
private static void WriteNumericMultiWrite(ref this OutputWriter<PipeWriter> buffer, ulong number)
|
||||
{
|
||||
const byte AsciiDigitStart = (byte)'0';
|
||||
|
||||
|
|
@ -141,11 +141,11 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
while (value != 0);
|
||||
|
||||
var length = _maxULongByteLength - position;
|
||||
buffer.Write(byteBuffer, position, length);
|
||||
buffer.Write(new ReadOnlySpan<byte>(byteBuffer, position, length));
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
private unsafe static void WriteAsciiMultiWrite(ref this WritableBufferWriter buffer, string data)
|
||||
private unsafe static void WriteAsciiMultiWrite(ref this OutputWriter<PipeWriter> buffer, string data)
|
||||
{
|
||||
var remaining = data.Length;
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Collections;
|
||||
using System.Collections.Sequences;
|
||||
using System.Collections.Concurrent;
|
||||
using System.IO.Pipelines;
|
||||
|
|
@ -84,7 +85,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
|
|||
|
||||
public string ConnectionId => _context.ConnectionId;
|
||||
|
||||
public IPipeReader Input => _context.Transport.Input;
|
||||
public PipeReader Input => _context.Transport.Input;
|
||||
|
||||
public IKestrelTrace Log => _context.ServiceContext.Log;
|
||||
|
||||
|
|
@ -132,7 +133,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
|
|||
}
|
||||
finally
|
||||
{
|
||||
Input.Advance(consumed, examined);
|
||||
Input.AdvanceTo(consumed, examined);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -165,7 +166,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
|
|||
}
|
||||
finally
|
||||
{
|
||||
Input.Advance(consumed, examined);
|
||||
Input.AdvanceTo(consumed, examined);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -216,7 +217,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
|
|||
}
|
||||
}
|
||||
|
||||
private bool ParsePreface(ReadOnlyBuffer readableBuffer, out Position consumed, out Position examined)
|
||||
private bool ParsePreface(ReadOnlyBuffer<byte> readableBuffer, out SequencePosition consumed, out SequencePosition examined)
|
||||
{
|
||||
consumed = readableBuffer.Start;
|
||||
examined = readableBuffer.End;
|
||||
|
|
@ -226,7 +227,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
|
|||
return false;
|
||||
}
|
||||
|
||||
var span = readableBuffer.IsSingleSpan
|
||||
var span = readableBuffer.IsSingleSegment
|
||||
? readableBuffer.First.Span
|
||||
: readableBuffer.ToSpan();
|
||||
|
||||
|
|
@ -238,7 +239,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
|
|||
}
|
||||
}
|
||||
|
||||
consumed = examined = readableBuffer.Move(readableBuffer.Start, ClientPreface.Length);
|
||||
consumed = examined = readableBuffer.GetPosition(readableBuffer.Start, ClientPreface.Length);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
|
|||
public IPEndPoint LocalEndPoint { get; set; }
|
||||
public IPEndPoint RemoteEndPoint { get; set; }
|
||||
|
||||
public IPipeConnection Transport { get; set; }
|
||||
public IPipeConnection Application { get; set; }
|
||||
public IDuplexPipe Transport { get; set; }
|
||||
public IDuplexPipe Application { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Buffers;
|
||||
using System.Collections;
|
||||
using System.Collections.Sequences;
|
||||
using System.IO.Pipelines;
|
||||
|
||||
|
|
@ -9,7 +10,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
|
|||
{
|
||||
public static class Http2FrameReader
|
||||
{
|
||||
public static bool ReadFrame(ReadOnlyBuffer readableBuffer, Http2Frame frame, out Position consumed, out Position examined)
|
||||
public static bool ReadFrame(ReadOnlyBuffer<byte> readableBuffer, Http2Frame frame, out SequencePosition consumed, out SequencePosition examined)
|
||||
{
|
||||
consumed = readableBuffer.Start;
|
||||
examined = readableBuffer.End;
|
||||
|
|
@ -28,7 +29,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
|
|||
}
|
||||
|
||||
readableBuffer.Slice(Http2Frame.HeaderLength, frame.Length).CopyTo(frame.Payload);
|
||||
consumed = examined = readableBuffer.Move(readableBuffer.Start, Http2Frame.HeaderLength + frame.Length);
|
||||
consumed = examined = readableBuffer.GetPosition(readableBuffer.Start, Http2Frame.HeaderLength + frame.Length);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
// 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.Collections.Generic;
|
||||
using System.IO.Pipelines;
|
||||
using System.Threading;
|
||||
|
|
@ -20,12 +21,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
|
|||
private readonly Http2Frame _outgoingFrame = new Http2Frame();
|
||||
private readonly object _writeLock = new object();
|
||||
private readonly HPackEncoder _hpackEncoder = new HPackEncoder();
|
||||
private readonly IPipeWriter _outputWriter;
|
||||
private readonly IPipeReader _outputReader;
|
||||
private readonly PipeWriter _outputWriter;
|
||||
private readonly PipeReader _outputReader;
|
||||
|
||||
private bool _completed;
|
||||
|
||||
public Http2FrameWriter(IPipeWriter outputPipeWriter, IPipeReader outputPipeReader)
|
||||
public Http2FrameWriter(PipeWriter outputPipeWriter, PipeReader outputPipeReader)
|
||||
{
|
||||
_outputWriter = outputPipeWriter;
|
||||
_outputReader = outputPipeReader;
|
||||
|
|
@ -48,7 +49,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
|
|||
|
||||
public Task FlushAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
return WriteAsync(Constants.EmptyData);
|
||||
lock (_writeLock)
|
||||
{
|
||||
return WriteAsync(Constants.EmptyData);
|
||||
}
|
||||
}
|
||||
|
||||
public Task Write100ContinueAsync(int streamId)
|
||||
|
|
@ -185,9 +189,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
|
|||
return;
|
||||
}
|
||||
|
||||
var writeableBuffer = _outputWriter.Alloc(1);
|
||||
writeableBuffer.Write(data);
|
||||
writeableBuffer.Commit();
|
||||
_outputWriter.Write(data);
|
||||
_outputWriter.Commit();
|
||||
}
|
||||
|
||||
// Must be called with _writeLock
|
||||
|
|
@ -198,9 +201,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
|
|||
return;
|
||||
}
|
||||
|
||||
var writeableBuffer = _outputWriter.Alloc(1);
|
||||
writeableBuffer.Write(data);
|
||||
await writeableBuffer.FlushAsync(cancellationToken);
|
||||
_outputWriter.Write(data);
|
||||
await _outputWriter.FlushAsync(cancellationToken);
|
||||
}
|
||||
|
||||
private static IEnumerable<KeyValuePair<string, string>> EnumerateHeaders(IHeaderDictionary headers)
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
|
|||
// TODO: RST_STREAM?
|
||||
}
|
||||
|
||||
public Task WriteAsync<T>(Action<WritableBuffer, T> callback, T state)
|
||||
public Task WriteAsync<T>(Action<PipeWriter, T> callback, T state)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
// 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.IO.Pipelines;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Features;
|
||||
|
|
@ -78,19 +79,17 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
|
|||
{
|
||||
if (data.Count > 0)
|
||||
{
|
||||
var writableBuffer = RequestBodyPipe.Writer.Alloc(1);
|
||||
|
||||
try
|
||||
{
|
||||
writableBuffer.Write(data);
|
||||
RequestBodyPipe.Writer.Write(data);
|
||||
}
|
||||
finally
|
||||
{
|
||||
writableBuffer.Commit();
|
||||
RequestBodyPipe.Writer.Commit();
|
||||
}
|
||||
|
||||
RequestBodyStarted = true;
|
||||
await writableBuffer.FlushAsync();
|
||||
await RequestBodyPipe.Writer.FlushAsync();
|
||||
}
|
||||
|
||||
if (endStream)
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
|
|||
private readonly TaskCompletionSource<object> _socketClosedTcs = new TaskCompletionSource<object>(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||
|
||||
private IList<IAdaptedConnection> _adaptedConnections;
|
||||
private IPipeConnection _adaptedTransport;
|
||||
private IDuplexPipe _adaptedTransport;
|
||||
|
||||
private readonly object _protocolSelectionLock = new object();
|
||||
private ProtocolSelectionState _protocolSelectionState = ProtocolSelectionState.Initializing;
|
||||
|
|
@ -75,18 +75,18 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
|
|||
(
|
||||
pool: MemoryPool,
|
||||
readerScheduler: _context.ServiceContext.ThreadPool,
|
||||
writerScheduler: Scheduler.Inline,
|
||||
maximumSizeHigh: _context.ServiceContext.ServerOptions.Limits.MaxRequestBufferSize ?? 0,
|
||||
maximumSizeLow: _context.ServiceContext.ServerOptions.Limits.MaxRequestBufferSize ?? 0
|
||||
writerScheduler: PipeScheduler.Inline,
|
||||
pauseWriterThreshold: _context.ServiceContext.ServerOptions.Limits.MaxRequestBufferSize ?? 0,
|
||||
resumeWriterThreshold: _context.ServiceContext.ServerOptions.Limits.MaxRequestBufferSize ?? 0
|
||||
);
|
||||
|
||||
internal PipeOptions AdaptedOutputPipeOptions => new PipeOptions
|
||||
(
|
||||
pool: MemoryPool,
|
||||
readerScheduler: Scheduler.Inline,
|
||||
writerScheduler: Scheduler.Inline,
|
||||
maximumSizeHigh: _context.ServiceContext.ServerOptions.Limits.MaxResponseBufferSize ?? 0,
|
||||
maximumSizeLow: _context.ServiceContext.ServerOptions.Limits.MaxResponseBufferSize ?? 0
|
||||
readerScheduler: PipeScheduler.Inline,
|
||||
writerScheduler: PipeScheduler.Inline,
|
||||
pauseWriterThreshold: _context.ServiceContext.ServerOptions.Limits.MaxResponseBufferSize ?? 0,
|
||||
resumeWriterThreshold: _context.ServiceContext.ServerOptions.Limits.MaxResponseBufferSize ?? 0
|
||||
);
|
||||
|
||||
private IKestrelTrace Log => _context.ServiceContext.Log;
|
||||
|
|
@ -196,13 +196,13 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
|
|||
}
|
||||
|
||||
// For testing only
|
||||
internal void Initialize(IPipeConnection transport, IPipeConnection application)
|
||||
internal void Initialize(IDuplexPipe transport, IDuplexPipe application)
|
||||
{
|
||||
_requestProcessor = _http1Connection = CreateHttp1Connection(transport, application);
|
||||
_protocolSelectionState = ProtocolSelectionState.Selected;
|
||||
}
|
||||
|
||||
private Http1Connection CreateHttp1Connection(IPipeConnection transport, IPipeConnection application)
|
||||
private Http1Connection CreateHttp1Connection(IDuplexPipe transport, IDuplexPipe application)
|
||||
{
|
||||
return new Http1Connection(new Http1ConnectionContext
|
||||
{
|
||||
|
|
@ -218,7 +218,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
|
|||
});
|
||||
}
|
||||
|
||||
private Http2Connection CreateHttp2Connection(IPipeConnection transport, IPipeConnection application)
|
||||
private Http2Connection CreateHttp2Connection(IDuplexPipe transport, IDuplexPipe application)
|
||||
{
|
||||
return new Http2Connection(new Http2ConnectionContext
|
||||
{
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
|
|||
public MemoryPool MemoryPool { get; set; }
|
||||
public IPEndPoint LocalEndPoint { get; set; }
|
||||
public IPEndPoint RemoteEndPoint { get; set; }
|
||||
public IPipeConnection Transport { get; set; }
|
||||
public IPipeConnection Application { get; set; }
|
||||
public IDuplexPipe Transport { get; set; }
|
||||
public IDuplexPipe Application { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,12 +2,11 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.IO.Pipelines;
|
||||
using System.Threading;
|
||||
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
|
||||
{
|
||||
public abstract class KestrelThreadPool: Scheduler
|
||||
public abstract class KestrelThreadPool : PipeScheduler
|
||||
{
|
||||
public abstract void Run(Action action);
|
||||
public abstract void UnsafeRun(WaitCallback action, object state);
|
||||
|
|
|
|||
|
|
@ -42,12 +42,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
|
|||
|
||||
public override void Run(Action action)
|
||||
{
|
||||
ThreadPool.QueueUserWorkItem(_runAction, action);
|
||||
System.Threading.ThreadPool.QueueUserWorkItem(_runAction, action);
|
||||
}
|
||||
|
||||
public override void UnsafeRun(WaitCallback action, object state)
|
||||
{
|
||||
ThreadPool.QueueUserWorkItem(action, state);
|
||||
System.Threading.ThreadPool.QueueUserWorkItem(action, state);
|
||||
}
|
||||
|
||||
public override void Schedule(Action action)
|
||||
|
|
|
|||
|
|
@ -98,13 +98,13 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal
|
|||
|
||||
MemoryPool IConnectionTransportFeature.MemoryPool => MemoryPool;
|
||||
|
||||
IPipeConnection IConnectionTransportFeature.Transport
|
||||
IDuplexPipe IConnectionTransportFeature.Transport
|
||||
{
|
||||
get => Transport;
|
||||
set => Transport = value;
|
||||
}
|
||||
|
||||
IPipeConnection IConnectionTransportFeature.Application
|
||||
IDuplexPipe IConnectionTransportFeature.Application
|
||||
{
|
||||
get => Application;
|
||||
set => Application = value;
|
||||
|
|
|
|||
|
|
@ -23,13 +23,13 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal
|
|||
public string ConnectionId { get; set; }
|
||||
|
||||
public virtual MemoryPool MemoryPool { get; }
|
||||
public virtual Scheduler InputWriterScheduler { get; }
|
||||
public virtual Scheduler OutputReaderScheduler { get; }
|
||||
public virtual PipeScheduler InputWriterScheduler { get; }
|
||||
public virtual PipeScheduler OutputReaderScheduler { get; }
|
||||
|
||||
public IPipeConnection Transport { get; set; }
|
||||
public IPipeConnection Application { get; set; }
|
||||
public IDuplexPipe Transport { get; set; }
|
||||
public IDuplexPipe Application { get; set; }
|
||||
|
||||
public IPipeWriter Input => Application.Output;
|
||||
public IPipeReader Output => Application.Input;
|
||||
public PipeWriter Input => Application.Output;
|
||||
public PipeReader Output => Application.Input;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
|||
|
||||
private readonly UvStreamHandle _socket;
|
||||
|
||||
private WritableBuffer? _currentWritableBuffer;
|
||||
private MemoryHandle _bufferHandle;
|
||||
|
||||
public LibuvConnection(ListenerContext context, UvStreamHandle socket) : base(context)
|
||||
|
|
@ -107,13 +106,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
|||
|
||||
private unsafe LibuvFunctions.uv_buf_t OnAlloc(UvStreamHandle handle, int suggestedSize)
|
||||
{
|
||||
Debug.Assert(_currentWritableBuffer == null);
|
||||
var currentWritableBuffer = Input.Alloc(MinAllocBufferSize);
|
||||
_currentWritableBuffer = currentWritableBuffer;
|
||||
var currentWritableBuffer = Input.GetMemory(MinAllocBufferSize);
|
||||
_bufferHandle = currentWritableBuffer.Retain(true);
|
||||
|
||||
_bufferHandle = currentWritableBuffer.Buffer.Retain(true);
|
||||
|
||||
return handle.Libuv.buf_init((IntPtr)_bufferHandle.Pointer, currentWritableBuffer.Buffer.Length);
|
||||
return handle.Libuv.buf_init((IntPtr)_bufferHandle.Pointer, currentWritableBuffer.Length);
|
||||
}
|
||||
|
||||
private static void ReadCallback(UvStreamHandle handle, int status, object state)
|
||||
|
|
@ -127,17 +123,14 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
|||
{
|
||||
// EAGAIN/EWOULDBLOCK so just return the buffer.
|
||||
// http://docs.libuv.org/en/v1.x/stream.html#c.uv_read_cb
|
||||
Debug.Assert(_currentWritableBuffer != null);
|
||||
_currentWritableBuffer.Value.Commit();
|
||||
Input.Commit();
|
||||
}
|
||||
else if (status > 0)
|
||||
{
|
||||
Log.ConnectionRead(ConnectionId, status);
|
||||
|
||||
Debug.Assert(_currentWritableBuffer != null);
|
||||
var currentWritableBuffer = _currentWritableBuffer.Value;
|
||||
currentWritableBuffer.Advance(status);
|
||||
var flushTask = currentWritableBuffer.FlushAsync();
|
||||
Input.Advance(status);
|
||||
var flushTask = Input.FlushAsync();
|
||||
|
||||
if (!flushTask.IsCompleted)
|
||||
{
|
||||
|
|
@ -149,7 +142,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
|||
else
|
||||
{
|
||||
// Given a negative status, it's possible that OnAlloc wasn't called.
|
||||
_currentWritableBuffer?.Commit();
|
||||
Input.Commit();
|
||||
_socket.ReadStop();
|
||||
|
||||
IOException error = null;
|
||||
|
|
@ -180,7 +173,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
|||
}
|
||||
|
||||
// Cleanup state from last OnAlloc. This is safe even if OnAlloc wasn't called.
|
||||
_currentWritableBuffer = null;
|
||||
_bufferHandle.Dispose();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
|||
public ListenerContext ListenerContext { get; set; }
|
||||
|
||||
public override MemoryPool MemoryPool => ListenerContext.Thread.MemoryPool;
|
||||
public override Scheduler InputWriterScheduler => ListenerContext.Thread;
|
||||
public override Scheduler OutputReaderScheduler => ListenerContext.Thread;
|
||||
public override PipeScheduler InputWriterScheduler => ListenerContext.Thread;
|
||||
public override PipeScheduler OutputReaderScheduler => ListenerContext.Thread;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,10 +14,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
|||
private readonly UvStreamHandle _socket;
|
||||
private readonly string _connectionId;
|
||||
private readonly ILibuvTrace _log;
|
||||
private readonly IPipeReader _pipe;
|
||||
private readonly PipeReader _pipe;
|
||||
|
||||
public LibuvOutputConsumer(
|
||||
IPipeReader pipe,
|
||||
PipeReader pipe,
|
||||
LibuvThread thread,
|
||||
UvStreamHandle socket,
|
||||
string connectionId,
|
||||
|
|
@ -94,7 +94,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
|||
}
|
||||
finally
|
||||
{
|
||||
_pipe.Advance(consumed);
|
||||
_pipe.AdvanceTo(consumed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ using Microsoft.Extensions.Logging;
|
|||
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
||||
{
|
||||
public class LibuvThread : Scheduler
|
||||
public class LibuvThread : PipeScheduler
|
||||
{
|
||||
// maximum times the work queues swapped and are processed in a single pass
|
||||
// as completing a task may immediately have write data to put on the network
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networkin
|
|||
_bufs = handle + requestSize;
|
||||
}
|
||||
|
||||
public LibuvAwaitable<UvWriteReq> WriteAsync(UvStreamHandle handle, ReadOnlyBuffer buffer)
|
||||
public LibuvAwaitable<UvWriteReq> WriteAsync(UvStreamHandle handle, ReadOnlyBuffer<byte> buffer)
|
||||
{
|
||||
Write(handle, buffer, LibuvAwaitable<UvWriteReq>.Callback, _awaitable);
|
||||
return _awaitable;
|
||||
|
|
@ -63,14 +63,14 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networkin
|
|||
|
||||
private unsafe void Write(
|
||||
UvStreamHandle handle,
|
||||
ReadOnlyBuffer buffer,
|
||||
ReadOnlyBuffer<byte> buffer,
|
||||
Action<UvWriteReq, int, UvException, object> callback,
|
||||
object state)
|
||||
{
|
||||
try
|
||||
{
|
||||
var nBuffers = 0;
|
||||
if (buffer.IsSingleSpan)
|
||||
if (buffer.IsSingleSegment)
|
||||
{
|
||||
nBuffers = 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,8 +52,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal
|
|||
}
|
||||
|
||||
public override MemoryPool MemoryPool { get; }
|
||||
public override Scheduler InputWriterScheduler => Scheduler.Inline;
|
||||
public override Scheduler OutputReaderScheduler => Scheduler.TaskRun;
|
||||
public override PipeScheduler InputWriterScheduler => PipeScheduler.Inline;
|
||||
public override PipeScheduler OutputReaderScheduler => PipeScheduler.ThreadPool;
|
||||
|
||||
public async Task StartAsync(IConnectionHandler connectionHandler)
|
||||
{
|
||||
|
|
@ -102,11 +102,11 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal
|
|||
while (true)
|
||||
{
|
||||
// Ensure we have some reasonable amount of buffer space
|
||||
var buffer = Input.Alloc(MinAllocBufferSize);
|
||||
var buffer = Input.GetMemory(MinAllocBufferSize);
|
||||
|
||||
try
|
||||
{
|
||||
var bytesReceived = await _receiver.ReceiveAsync(buffer.Buffer);
|
||||
var bytesReceived = await _receiver.ReceiveAsync(buffer);
|
||||
|
||||
if (bytesReceived == 0)
|
||||
{
|
||||
|
|
@ -115,14 +115,14 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal
|
|||
break;
|
||||
}
|
||||
|
||||
buffer.Advance(bytesReceived);
|
||||
Input.Advance(bytesReceived);
|
||||
}
|
||||
finally
|
||||
{
|
||||
buffer.Commit();
|
||||
Input.Commit();
|
||||
}
|
||||
|
||||
var flushTask = buffer.FlushAsync();
|
||||
var flushTask = Input.FlushAsync();
|
||||
|
||||
if (!flushTask.IsCompleted)
|
||||
{
|
||||
|
|
@ -217,7 +217,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal
|
|||
}
|
||||
finally
|
||||
{
|
||||
Output.Advance(buffer.End);
|
||||
Output.AdvanceTo(buffer.End);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,9 +26,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal
|
|||
_eventArgs.Completed += (_, e) => ((SocketAwaitable)e.UserToken).Complete(e.BytesTransferred, e.SocketError);
|
||||
}
|
||||
|
||||
public SocketAwaitable SendAsync(ReadOnlyBuffer buffers)
|
||||
public SocketAwaitable SendAsync(ReadOnlyBuffer<byte> buffers)
|
||||
{
|
||||
if (buffers.IsSingleSpan)
|
||||
if (buffers.IsSingleSegment)
|
||||
{
|
||||
return SendAsync(buffers.First);
|
||||
}
|
||||
|
|
@ -75,10 +75,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal
|
|||
return _awaitable;
|
||||
}
|
||||
|
||||
private List<ArraySegment<byte>> GetBufferList(ReadOnlyBuffer buffer)
|
||||
private List<ArraySegment<byte>> GetBufferList(ReadOnlyBuffer<byte> buffer)
|
||||
{
|
||||
Debug.Assert(!buffer.IsEmpty);
|
||||
Debug.Assert(!buffer.IsSingleSpan);
|
||||
Debug.Assert(!buffer.IsSingleSegment);
|
||||
|
||||
if (_bufferList == null)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ namespace Microsoft.AspNetCore.Protocols
|
|||
|
||||
public abstract IFeatureCollection Features { get; }
|
||||
|
||||
public abstract IPipeConnection Transport { get; set; }
|
||||
public abstract IDuplexPipe Transport { get; set; }
|
||||
|
||||
public abstract MemoryPool MemoryPool { get; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ namespace Microsoft.AspNetCore.Protocols
|
|||
|
||||
public override MemoryPool MemoryPool => ConnectionTransportFeature.MemoryPool;
|
||||
|
||||
public override IPipeConnection Transport
|
||||
public override IDuplexPipe Transport
|
||||
{
|
||||
get => ConnectionTransportFeature.Transport;
|
||||
set => ConnectionTransportFeature.Transport = value;
|
||||
|
|
|
|||
|
|
@ -8,12 +8,12 @@ namespace Microsoft.AspNetCore.Protocols.Features
|
|||
{
|
||||
MemoryPool MemoryPool { get; }
|
||||
|
||||
IPipeConnection Transport { get; set; }
|
||||
IDuplexPipe Transport { get; set; }
|
||||
|
||||
IPipeConnection Application { get; set; }
|
||||
IDuplexPipe Application { get; set; }
|
||||
|
||||
Scheduler InputWriterScheduler { get; }
|
||||
PipeScheduler InputWriterScheduler { get; }
|
||||
|
||||
Scheduler OutputReaderScheduler { get; }
|
||||
PipeScheduler OutputReaderScheduler { get; }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,17 +4,17 @@ using System.Text;
|
|||
|
||||
namespace System.IO.Pipelines
|
||||
{
|
||||
public class PipeConnection : IPipeConnection
|
||||
public class PipeConnection : IDuplexPipe
|
||||
{
|
||||
public PipeConnection(IPipeReader reader, IPipeWriter writer)
|
||||
public PipeConnection(PipeReader reader, PipeWriter writer)
|
||||
{
|
||||
Input = reader;
|
||||
Output = writer;
|
||||
}
|
||||
|
||||
public IPipeReader Input { get; }
|
||||
public PipeReader Input { get; }
|
||||
|
||||
public IPipeWriter Output { get; }
|
||||
public PipeWriter Output { get; }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -4,12 +4,12 @@ namespace System.IO.Pipelines
|
|||
{
|
||||
public static class PipeFactory
|
||||
{
|
||||
public static (IPipeConnection Transport, IPipeConnection Application) CreateConnectionPair(MemoryPool memoryPool)
|
||||
public static (IDuplexPipe Transport, IDuplexPipe Application) CreateConnectionPair(MemoryPool memoryPool)
|
||||
{
|
||||
return CreateConnectionPair(new PipeOptions(memoryPool), new PipeOptions(memoryPool));
|
||||
}
|
||||
|
||||
public static (IPipeConnection Transport, IPipeConnection Application) CreateConnectionPair(PipeOptions inputOptions, PipeOptions outputOptions)
|
||||
public static (IDuplexPipe Transport, IDuplexPipe Application) CreateConnectionPair(PipeOptions inputOptions, PipeOptions outputOptions)
|
||||
{
|
||||
var input = new Pipe(inputOptions);
|
||||
var output = new Pipe(outputOptions);
|
||||
|
|
|
|||
|
|
@ -1,9 +1,7 @@
|
|||
using System;
|
||||
using System.Buffers;
|
||||
using System.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using System.IO.Pipelines;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
|
|
@ -55,12 +53,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
|
||||
public MemoryPool MemoryPool { get; } = new MemoryPool();
|
||||
|
||||
public IPipeConnection Transport { get; set; }
|
||||
public IPipeConnection Application { get; set; }
|
||||
public IDuplexPipe Transport { get; set; }
|
||||
public IDuplexPipe Application { get; set; }
|
||||
|
||||
public Scheduler InputWriterScheduler => Scheduler.TaskRun;
|
||||
public PipeScheduler InputWriterScheduler => PipeScheduler.ThreadPool;
|
||||
|
||||
public Scheduler OutputReaderScheduler => Scheduler.TaskRun;
|
||||
public PipeScheduler OutputReaderScheduler => PipeScheduler.ThreadPool;
|
||||
|
||||
public string ConnectionId { get; set; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,14 +28,14 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
{
|
||||
public class Http1ConnectionTests : IDisposable
|
||||
{
|
||||
private readonly IPipeConnection _transport;
|
||||
private readonly IPipeConnection _application;
|
||||
private readonly IDuplexPipe _transport;
|
||||
private readonly IDuplexPipe _application;
|
||||
private readonly TestHttp1Connection _http1Connection;
|
||||
private readonly ServiceContext _serviceContext;
|
||||
private readonly Http1ConnectionContext _http1ConnectionContext;
|
||||
private readonly MemoryPool _pipelineFactory;
|
||||
private Position _consumed;
|
||||
private Position _examined;
|
||||
private SequencePosition _consumed;
|
||||
private SequencePosition _examined;
|
||||
private Mock<ITimeoutControl> _timeoutControl;
|
||||
|
||||
public Http1ConnectionTests()
|
||||
|
|
@ -84,7 +84,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
var readableBuffer = (await _transport.Input.ReadAsync()).Buffer;
|
||||
|
||||
var exception = Assert.Throws<BadHttpRequestException>(() => _http1Connection.TakeMessageHeaders(readableBuffer, out _consumed, out _examined));
|
||||
_transport.Input.Advance(_consumed, _examined);
|
||||
_transport.Input.AdvanceTo(_consumed, _examined);
|
||||
|
||||
Assert.Equal(CoreStrings.BadRequest_HeadersExceedMaxTotalSize, exception.Message);
|
||||
Assert.Equal(StatusCodes.Status431RequestHeaderFieldsTooLarge, exception.StatusCode);
|
||||
|
|
@ -100,7 +100,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
var readableBuffer = (await _transport.Input.ReadAsync()).Buffer;
|
||||
|
||||
var exception = Assert.Throws<BadHttpRequestException>(() => _http1Connection.TakeMessageHeaders(readableBuffer, out _consumed, out _examined));
|
||||
_transport.Input.Advance(_consumed, _examined);
|
||||
_transport.Input.AdvanceTo(_consumed, _examined);
|
||||
|
||||
Assert.Equal(CoreStrings.BadRequest_TooManyHeaders, exception.Message);
|
||||
Assert.Equal(StatusCodes.Status431RequestHeaderFieldsTooLarge, exception.StatusCode);
|
||||
|
|
@ -205,7 +205,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
var readableBuffer = (await _transport.Input.ReadAsync()).Buffer;
|
||||
|
||||
var takeMessageHeaders = _http1Connection.TakeMessageHeaders(readableBuffer, out _consumed, out _examined);
|
||||
_transport.Input.Advance(_consumed, _examined);
|
||||
_transport.Input.AdvanceTo(_consumed, _examined);
|
||||
|
||||
Assert.True(takeMessageHeaders);
|
||||
Assert.Equal(1, _http1Connection.RequestHeaders.Count);
|
||||
|
|
@ -217,7 +217,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
readableBuffer = (await _transport.Input.ReadAsync()).Buffer;
|
||||
|
||||
takeMessageHeaders = _http1Connection.TakeMessageHeaders(readableBuffer, out _consumed, out _examined);
|
||||
_transport.Input.Advance(_consumed, _examined);
|
||||
_transport.Input.AdvanceTo(_consumed, _examined);
|
||||
|
||||
Assert.True(takeMessageHeaders);
|
||||
Assert.Equal(1, _http1Connection.RequestHeaders.Count);
|
||||
|
|
@ -342,7 +342,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
var readableBuffer = (await _transport.Input.ReadAsync()).Buffer;
|
||||
|
||||
var returnValue = _http1Connection.TakeStartLine(readableBuffer, out _consumed, out _examined);
|
||||
_transport.Input.Advance(_consumed, _examined);
|
||||
_transport.Input.AdvanceTo(_consumed, _examined);
|
||||
|
||||
Assert.True(returnValue);
|
||||
Assert.Equal(expectedMethod, _http1Connection.Method);
|
||||
|
|
@ -365,7 +365,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
var readableBuffer = (await _transport.Input.ReadAsync()).Buffer;
|
||||
|
||||
var returnValue = _http1Connection.TakeStartLine(readableBuffer, out _consumed, out _examined);
|
||||
_transport.Input.Advance(_consumed, _examined);
|
||||
_transport.Input.AdvanceTo(_consumed, _examined);
|
||||
|
||||
Assert.True(returnValue);
|
||||
Assert.Equal(expectedRawTarget, _http1Connection.RawTarget);
|
||||
|
|
@ -379,7 +379,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
await _application.Output.WriteAsync(Encoding.ASCII.GetBytes("G"));
|
||||
|
||||
_http1Connection.ParseRequest((await _transport.Input.ReadAsync()).Buffer, out _consumed, out _examined);
|
||||
_transport.Input.Advance(_consumed, _examined);
|
||||
_transport.Input.AdvanceTo(_consumed, _examined);
|
||||
|
||||
var expectedRequestHeadersTimeout = _serviceContext.ServerOptions.Limits.RequestHeadersTimeout.Ticks;
|
||||
_timeoutControl.Verify(cc => cc.ResetTimeout(expectedRequestHeadersTimeout, TimeoutAction.SendTimeoutResponse));
|
||||
|
|
@ -395,7 +395,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
|
||||
var readableBuffer = (await _transport.Input.ReadAsync()).Buffer;
|
||||
var exception = Assert.Throws<BadHttpRequestException>(() => _http1Connection.TakeStartLine(readableBuffer, out _consumed, out _examined));
|
||||
_transport.Input.Advance(_consumed, _examined);
|
||||
_transport.Input.AdvanceTo(_consumed, _examined);
|
||||
|
||||
Assert.Equal(CoreStrings.BadRequest_RequestLineTooLong, exception.Message);
|
||||
Assert.Equal(StatusCodes.Status414UriTooLong, exception.StatusCode);
|
||||
|
|
@ -410,7 +410,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
|
||||
var exception = Assert.Throws<BadHttpRequestException>(() =>
|
||||
_http1Connection.TakeStartLine(readableBuffer, out _consumed, out _examined));
|
||||
_transport.Input.Advance(_consumed, _examined);
|
||||
_transport.Input.AdvanceTo(_consumed, _examined);
|
||||
|
||||
Assert.Equal(CoreStrings.FormatBadRequest_InvalidRequestTarget_Detail(target), exception.Message);
|
||||
}
|
||||
|
|
@ -424,7 +424,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
|
||||
var exception = Assert.Throws<BadHttpRequestException>(() =>
|
||||
_http1Connection.TakeStartLine(readableBuffer, out _consumed, out _examined));
|
||||
_transport.Input.Advance(_consumed, _examined);
|
||||
_transport.Input.AdvanceTo(_consumed, _examined);
|
||||
|
||||
Assert.Equal(CoreStrings.FormatBadRequest_InvalidRequestTarget_Detail(target.EscapeNonPrintable()), exception.Message);
|
||||
}
|
||||
|
|
@ -440,7 +440,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
|
||||
var exception = Assert.Throws<BadHttpRequestException>(() =>
|
||||
_http1Connection.TakeStartLine(readableBuffer, out _consumed, out _examined));
|
||||
_transport.Input.Advance(_consumed, _examined);
|
||||
_transport.Input.AdvanceTo(_consumed, _examined);
|
||||
|
||||
Assert.Equal(CoreStrings.FormatBadRequest_InvalidRequestLine_Detail(requestLine.EscapeNonPrintable()), exception.Message);
|
||||
}
|
||||
|
|
@ -456,7 +456,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
|
||||
var exception = Assert.Throws<BadHttpRequestException>(() =>
|
||||
_http1Connection.TakeStartLine(readableBuffer, out _consumed, out _examined));
|
||||
_transport.Input.Advance(_consumed, _examined);
|
||||
_transport.Input.AdvanceTo(_consumed, _examined);
|
||||
|
||||
Assert.Equal(CoreStrings.FormatBadRequest_InvalidRequestTarget_Detail(target.EscapeNonPrintable()), exception.Message);
|
||||
}
|
||||
|
|
@ -472,7 +472,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
|
||||
var exception = Assert.Throws<BadHttpRequestException>(() =>
|
||||
_http1Connection.TakeStartLine(readableBuffer, out _consumed, out _examined));
|
||||
_transport.Input.Advance(_consumed, _examined);
|
||||
_transport.Input.AdvanceTo(_consumed, _examined);
|
||||
|
||||
Assert.Equal(CoreStrings.FormatBadRequest_InvalidRequestTarget_Detail(target.EscapeNonPrintable()), exception.Message);
|
||||
}
|
||||
|
|
@ -486,7 +486,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
|
||||
var exception = Assert.Throws<BadHttpRequestException>(() =>
|
||||
_http1Connection.TakeStartLine(readableBuffer, out _consumed, out _examined));
|
||||
_transport.Input.Advance(_consumed, _examined);
|
||||
_transport.Input.AdvanceTo(_consumed, _examined);
|
||||
|
||||
Assert.Equal(405, exception.StatusCode);
|
||||
Assert.Equal(CoreStrings.BadRequest_MethodNotAllowed, exception.Message);
|
||||
|
|
@ -685,7 +685,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
|
||||
var exception = Assert.Throws<BadHttpRequestException>(() =>
|
||||
_http1Connection.TakeStartLine(readableBuffer, out _consumed, out _examined));
|
||||
_transport.Input.Advance(_consumed, _examined);
|
||||
_transport.Input.AdvanceTo(_consumed, _examined);
|
||||
|
||||
Assert.Equal(CoreStrings.FormatBadRequest_InvalidRequestTarget_Detail(string.Empty), exception.Message);
|
||||
Assert.Equal(StatusCodes.Status400BadRequest, exception.StatusCode);
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
private static readonly byte[] _maxData = Encoding.ASCII.GetBytes(new string('a', Http2Frame.MinAllowedMaxFrameSize));
|
||||
|
||||
private readonly MemoryPool _memoryPool = new MemoryPool();
|
||||
private readonly (IPipeConnection Transport, IPipeConnection Application) _pair;
|
||||
private readonly (IDuplexPipe Transport, IDuplexPipe Application) _pair;
|
||||
private readonly TestApplicationErrorLogger _logger;
|
||||
private readonly Http2ConnectionContext _connectionContext;
|
||||
private readonly Http2Connection _connection;
|
||||
|
|
@ -2138,7 +2138,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
|
||||
private async Task SendAsync(ArraySegment<byte> span)
|
||||
{
|
||||
var writableBuffer = _pair.Application.Output.Alloc(1);
|
||||
var writableBuffer = _pair.Application.Output;
|
||||
writableBuffer.Write(span);
|
||||
await writableBuffer.FlushAsync();
|
||||
}
|
||||
|
|
@ -2466,7 +2466,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
}
|
||||
finally
|
||||
{
|
||||
_pair.Application.Input.Advance(consumed, examined);
|
||||
_pair.Application.Input.AdvanceTo(consumed, examined);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
string expectedVersion)
|
||||
{
|
||||
var parser = CreateParser(Mock.Of<IKestrelTrace>());
|
||||
var buffer = new ReadOnlyBuffer(Encoding.ASCII.GetBytes(requestLine));
|
||||
var buffer = new ReadOnlyBuffer<byte>(Encoding.ASCII.GetBytes(requestLine));
|
||||
var requestHandler = new RequestHandler();
|
||||
|
||||
Assert.True(parser.ParseRequestLine(requestHandler, buffer, out var consumed, out var examined));
|
||||
|
|
@ -45,8 +45,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
Assert.Equal(requestHandler.RawTarget, expectedRawTarget);
|
||||
Assert.Equal(requestHandler.RawPath, expectedRawPath);
|
||||
Assert.Equal(requestHandler.Version, expectedVersion);
|
||||
Assert.Equal(buffer.End, consumed);
|
||||
Assert.Equal(buffer.End, examined);
|
||||
Assert.True(buffer.Slice(consumed).IsEmpty);
|
||||
Assert.True(buffer.Slice(examined).IsEmpty);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
@ -54,7 +54,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
public void ParseRequestLineReturnsFalseWhenGivenIncompleteRequestLines(string requestLine)
|
||||
{
|
||||
var parser = CreateParser(Mock.Of<IKestrelTrace>());
|
||||
var buffer = new ReadOnlyBuffer(Encoding.ASCII.GetBytes(requestLine));
|
||||
var buffer = new ReadOnlyBuffer<byte>(Encoding.ASCII.GetBytes(requestLine));
|
||||
var requestHandler = new RequestHandler();
|
||||
|
||||
Assert.False(parser.ParseRequestLine(requestHandler, buffer, out var consumed, out var examined));
|
||||
|
|
@ -65,13 +65,13 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
public void ParseRequestLineDoesNotConsumeIncompleteRequestLine(string requestLine)
|
||||
{
|
||||
var parser = CreateParser(Mock.Of<IKestrelTrace>());
|
||||
var buffer = new ReadOnlyBuffer(Encoding.ASCII.GetBytes(requestLine));
|
||||
var buffer = new ReadOnlyBuffer<byte>(Encoding.ASCII.GetBytes(requestLine));
|
||||
var requestHandler = new RequestHandler();
|
||||
|
||||
Assert.False(parser.ParseRequestLine(requestHandler, buffer, out var consumed, out var examined));
|
||||
|
||||
Assert.Equal(buffer.Start, consumed);
|
||||
Assert.Equal(buffer.End, examined);
|
||||
Assert.True(buffer.Slice(examined).IsEmpty);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
@ -84,7 +84,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
.Returns(true);
|
||||
|
||||
var parser = CreateParser(mockTrace.Object);
|
||||
var buffer = new ReadOnlyBuffer(Encoding.ASCII.GetBytes(requestLine));
|
||||
var buffer = new ReadOnlyBuffer<byte>(Encoding.ASCII.GetBytes(requestLine));
|
||||
var requestHandler = new RequestHandler();
|
||||
|
||||
var exception = Assert.Throws<BadHttpRequestException>(() =>
|
||||
|
|
@ -106,7 +106,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
.Returns(true);
|
||||
|
||||
var parser = CreateParser(mockTrace.Object);
|
||||
var buffer = new ReadOnlyBuffer(Encoding.ASCII.GetBytes(requestLine));
|
||||
var buffer = new ReadOnlyBuffer<byte>(Encoding.ASCII.GetBytes(requestLine));
|
||||
var requestHandler = new RequestHandler();
|
||||
|
||||
var exception = Assert.Throws<BadHttpRequestException>(() =>
|
||||
|
|
@ -128,7 +128,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
.Returns(true);
|
||||
|
||||
var parser = CreateParser(mockTrace.Object);
|
||||
var buffer = new ReadOnlyBuffer(Encoding.ASCII.GetBytes(requestLine));
|
||||
var buffer = new ReadOnlyBuffer<byte>(Encoding.ASCII.GetBytes(requestLine));
|
||||
var requestHandler = new RequestHandler();
|
||||
|
||||
var exception = Assert.Throws<BadHttpRequestException>(() =>
|
||||
|
|
@ -179,7 +179,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
{
|
||||
var parser = CreateParser(Mock.Of<IKestrelTrace>());
|
||||
|
||||
var buffer = new ReadOnlyBuffer(Encoding.ASCII.GetBytes(rawHeaders));
|
||||
var buffer = new ReadOnlyBuffer<byte>(Encoding.ASCII.GetBytes(rawHeaders));
|
||||
var requestHandler = new RequestHandler();
|
||||
Assert.False(parser.ParseHeaders(requestHandler, buffer, out var consumed, out var examined, out var consumedBytes));
|
||||
}
|
||||
|
|
@ -204,12 +204,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
{
|
||||
var parser = CreateParser(Mock.Of<IKestrelTrace>());
|
||||
|
||||
var buffer = new ReadOnlyBuffer(Encoding.ASCII.GetBytes(rawHeaders));
|
||||
var buffer = new ReadOnlyBuffer<byte>(Encoding.ASCII.GetBytes(rawHeaders));
|
||||
var requestHandler = new RequestHandler();
|
||||
parser.ParseHeaders(requestHandler, buffer, out var consumed, out var examined, out var consumedBytes);
|
||||
|
||||
Assert.Equal(buffer.Start, consumed);
|
||||
Assert.Equal(buffer.End, examined);
|
||||
Assert.Equal(buffer.Length, buffer.Slice(consumed).Length);
|
||||
Assert.True(buffer.Slice(examined).IsEmpty);
|
||||
Assert.Equal(0, consumedBytes);
|
||||
}
|
||||
|
||||
|
|
@ -294,19 +294,19 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
var parser = CreateParser(Mock.Of<IKestrelTrace>());
|
||||
|
||||
const string headerLine = "Header: value\r\n\r";
|
||||
var buffer1 = new ReadOnlyBuffer(Encoding.ASCII.GetBytes(headerLine));
|
||||
var buffer1 = new ReadOnlyBuffer<byte>(Encoding.ASCII.GetBytes(headerLine));
|
||||
var requestHandler = new RequestHandler();
|
||||
Assert.False(parser.ParseHeaders(requestHandler, buffer1, out var consumed, out var examined, out var consumedBytes));
|
||||
|
||||
Assert.Equal(buffer1.Move(buffer1.Start, headerLine.Length - 1), consumed);
|
||||
Assert.Equal(buffer1.GetPosition(buffer1.Start, headerLine.Length - 1), consumed);
|
||||
Assert.Equal(buffer1.End, examined);
|
||||
Assert.Equal(headerLine.Length - 1, consumedBytes);
|
||||
|
||||
var buffer2 = new ReadOnlyBuffer(Encoding.ASCII.GetBytes("\r\n"));
|
||||
var buffer2 = new ReadOnlyBuffer<byte>(Encoding.ASCII.GetBytes("\r\n"));
|
||||
Assert.True(parser.ParseHeaders(requestHandler, buffer2, out consumed, out examined, out consumedBytes));
|
||||
|
||||
Assert.Equal(buffer2.End, consumed);
|
||||
Assert.Equal(buffer2.End, examined);
|
||||
Assert.True(buffer2.Slice(consumed).IsEmpty);
|
||||
Assert.True(buffer2.Slice(examined).IsEmpty);
|
||||
Assert.Equal(2, consumedBytes);
|
||||
}
|
||||
|
||||
|
|
@ -320,7 +320,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
.Returns(true);
|
||||
|
||||
var parser = CreateParser(mockTrace.Object);
|
||||
var buffer = new ReadOnlyBuffer(Encoding.ASCII.GetBytes(rawHeaders));
|
||||
var buffer = new ReadOnlyBuffer<byte>(Encoding.ASCII.GetBytes(rawHeaders));
|
||||
var requestHandler = new RequestHandler();
|
||||
|
||||
var exception = Assert.Throws<BadHttpRequestException>(() =>
|
||||
|
|
@ -341,7 +341,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
var parser = CreateParser(mockTrace.Object);
|
||||
|
||||
// Invalid request line
|
||||
var buffer = new ReadOnlyBuffer(Encoding.ASCII.GetBytes("GET % HTTP/1.1\r\n"));
|
||||
var buffer = new ReadOnlyBuffer<byte>(Encoding.ASCII.GetBytes("GET % HTTP/1.1\r\n"));
|
||||
var requestHandler = new RequestHandler();
|
||||
|
||||
var exception = Assert.Throws<BadHttpRequestException>(() =>
|
||||
|
|
@ -351,7 +351,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
Assert.Equal(StatusCodes.Status400BadRequest, (exception as BadHttpRequestException).StatusCode);
|
||||
|
||||
// Unrecognized HTTP version
|
||||
buffer = new ReadOnlyBuffer(Encoding.ASCII.GetBytes("GET / HTTP/1.2\r\n"));
|
||||
buffer = new ReadOnlyBuffer<byte>(Encoding.ASCII.GetBytes("GET / HTTP/1.2\r\n"));
|
||||
|
||||
exception = Assert.Throws<BadHttpRequestException>(() =>
|
||||
parser.ParseRequestLine(requestHandler, buffer, out var consumed, out var examined));
|
||||
|
|
@ -360,7 +360,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
Assert.Equal(StatusCodes.Status505HttpVersionNotsupported, (exception as BadHttpRequestException).StatusCode);
|
||||
|
||||
// Invalid request header
|
||||
buffer = new ReadOnlyBuffer(Encoding.ASCII.GetBytes("Header: value\n\r\n"));
|
||||
buffer = new ReadOnlyBuffer<byte>(Encoding.ASCII.GetBytes("Header: value\n\r\n"));
|
||||
|
||||
exception = Assert.Throws<BadHttpRequestException>(() =>
|
||||
parser.ParseHeaders(requestHandler, buffer, out var consumed, out var examined, out var consumedBytes));
|
||||
|
|
@ -375,7 +375,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
string expectedHeaderValue)
|
||||
{
|
||||
var parser = CreateParser(Mock.Of<IKestrelTrace>());
|
||||
var buffer = new ReadOnlyBuffer(Encoding.ASCII.GetBytes($"{headerName}:{rawHeaderValue}\r\n"));
|
||||
var buffer = new ReadOnlyBuffer<byte>(Encoding.ASCII.GetBytes($"{headerName}:{rawHeaderValue}\r\n"));
|
||||
|
||||
var requestHandler = new RequestHandler();
|
||||
parser.ParseHeaders(requestHandler, buffer, out var consumed, out var examined, out var consumedBytes);
|
||||
|
|
@ -384,8 +384,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
Assert.Single(pairs);
|
||||
Assert.Equal(headerName, pairs[0].Key);
|
||||
Assert.Equal(expectedHeaderValue, pairs[0].Value);
|
||||
Assert.Equal(buffer.End, consumed);
|
||||
Assert.Equal(buffer.End, examined);
|
||||
Assert.True(buffer.Slice(consumed).IsEmpty);
|
||||
Assert.True(buffer.Slice(examined).IsEmpty);
|
||||
}
|
||||
|
||||
private void VerifyRawHeaders(string rawHeaders, IEnumerable<string> expectedHeaderNames, IEnumerable<string> expectedHeaderValues)
|
||||
|
|
@ -393,7 +393,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
Assert.True(expectedHeaderNames.Count() == expectedHeaderValues.Count(), $"{nameof(expectedHeaderNames)} and {nameof(expectedHeaderValues)} sizes must match");
|
||||
|
||||
var parser = CreateParser(Mock.Of<IKestrelTrace>());
|
||||
var buffer = new ReadOnlyBuffer(Encoding.ASCII.GetBytes(rawHeaders));
|
||||
var buffer = new ReadOnlyBuffer<byte>(Encoding.ASCII.GetBytes(rawHeaders));
|
||||
|
||||
var requestHandler = new RequestHandler();
|
||||
parser.ParseHeaders(requestHandler, buffer, out var consumed, out var examined, out var consumedBytes);
|
||||
|
|
@ -403,8 +403,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
Assert.Equal(expectedHeaderNames.Count(), parsedHeaders.Length);
|
||||
Assert.Equal(expectedHeaderNames, parsedHeaders.Select(t => t.Key));
|
||||
Assert.Equal(expectedHeaderValues, parsedHeaders.Select(t => t.Value));
|
||||
Assert.Equal(buffer.End, consumed);
|
||||
Assert.Equal(buffer.End, examined);
|
||||
Assert.True(buffer.Slice(consumed).IsEmpty);
|
||||
Assert.True(buffer.Slice(examined).IsEmpty);
|
||||
}
|
||||
|
||||
private IHttpParser<RequestHandler> CreateParser(IKestrelTrace log) => new HttpParser<RequestHandler>(log.IsEnabled(LogLevel.Information));
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
|
@ -445,23 +446,23 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
// The block returned by IncomingStart always has at least 2048 available bytes,
|
||||
// so no need to bounds check in this test.
|
||||
var bytes = Encoding.ASCII.GetBytes(data[0]);
|
||||
var buffer = input.Application.Output.Alloc(2048);
|
||||
var buffer = input.Application.Output.GetMemory(2028);
|
||||
ArraySegment<byte> block;
|
||||
Assert.True(buffer.Buffer.TryGetArray(out block));
|
||||
Assert.True(MemoryMarshal.TryGetArray(buffer, out block));
|
||||
Buffer.BlockCopy(bytes, 0, block.Array, block.Offset, bytes.Length);
|
||||
buffer.Advance(bytes.Length);
|
||||
await buffer.FlushAsync();
|
||||
input.Application.Output.Advance(bytes.Length);
|
||||
await input.Application.Output.FlushAsync();
|
||||
|
||||
// Verify the block passed to WriteAsync is the same one incoming data was written into.
|
||||
Assert.Same(block.Array, await writeTcs.Task);
|
||||
|
||||
writeTcs = new TaskCompletionSource<byte[]>();
|
||||
bytes = Encoding.ASCII.GetBytes(data[1]);
|
||||
buffer = input.Application.Output.Alloc(2048);
|
||||
Assert.True(buffer.Buffer.TryGetArray(out block));
|
||||
buffer = input.Application.Output.GetMemory(2048);
|
||||
Assert.True(MemoryMarshal.TryGetArray(buffer, out block));
|
||||
Buffer.BlockCopy(bytes, 0, block.Array, block.Offset, bytes.Length);
|
||||
buffer.Advance(bytes.Length);
|
||||
await buffer.FlushAsync();
|
||||
input.Application.Output.Advance(bytes.Length);
|
||||
await input.Application.Output.FlushAsync();
|
||||
|
||||
Assert.Same(block.Array, await writeTcs.Task);
|
||||
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
var pipeOptions = new PipeOptions
|
||||
(
|
||||
pool: _memoryPool,
|
||||
readerScheduler: Mock.Of<Scheduler>()
|
||||
readerScheduler: Mock.Of<PipeScheduler>()
|
||||
);
|
||||
|
||||
using (var socketOutput = CreateOutputProducer(pipeOptions))
|
||||
|
|
|
|||
|
|
@ -26,11 +26,11 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
serviceContext.ServerOptions.Limits.MaxResponseBufferSize = maxResponseBufferSize;
|
||||
serviceContext.ThreadPool = new LoggingThreadPool(null);
|
||||
|
||||
var mockScheduler = Mock.Of<Scheduler>();
|
||||
var mockScheduler = Mock.Of<PipeScheduler>();
|
||||
var outputPipeOptions = ConnectionHandler.GetOutputPipeOptions(serviceContext, new MemoryPool(), readerScheduler: mockScheduler);
|
||||
|
||||
Assert.Equal(expectedMaximumSizeLow, outputPipeOptions.MaximumSizeLow);
|
||||
Assert.Equal(expectedMaximumSizeHigh, outputPipeOptions.MaximumSizeHigh);
|
||||
Assert.Equal(expectedMaximumSizeLow, outputPipeOptions.ResumeWriterThreshold);
|
||||
Assert.Equal(expectedMaximumSizeHigh, outputPipeOptions.PauseWriterThreshold);
|
||||
Assert.Same(mockScheduler, outputPipeOptions.ReaderScheduler);
|
||||
Assert.Same(serviceContext.ThreadPool, outputPipeOptions.WriterScheduler);
|
||||
}
|
||||
|
|
@ -44,11 +44,11 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
serviceContext.ServerOptions.Limits.MaxRequestBufferSize = maxRequestBufferSize;
|
||||
serviceContext.ThreadPool = new LoggingThreadPool(null);
|
||||
|
||||
var mockScheduler = Mock.Of<Scheduler>();
|
||||
var mockScheduler = Mock.Of<PipeScheduler>();
|
||||
var inputPipeOptions = ConnectionHandler.GetInputPipeOptions(serviceContext, new MemoryPool(), writerScheduler: mockScheduler);
|
||||
|
||||
Assert.Equal(expectedMaximumSizeLow, inputPipeOptions.MaximumSizeLow);
|
||||
Assert.Equal(expectedMaximumSizeHigh, inputPipeOptions.MaximumSizeHigh);
|
||||
Assert.Equal(expectedMaximumSizeLow, inputPipeOptions.ResumeWriterThreshold);
|
||||
Assert.Equal(expectedMaximumSizeHigh, inputPipeOptions.PauseWriterThreshold);
|
||||
Assert.Same(serviceContext.ThreadPool, inputPipeOptions.ReaderScheduler);
|
||||
Assert.Same(mockScheduler, inputPipeOptions.WriterScheduler);
|
||||
}
|
||||
|
|
@ -66,10 +66,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
ServiceContext = serviceContext
|
||||
});
|
||||
|
||||
Assert.Equal(expectedMaximumSizeLow, connectionLifetime.AdaptedInputPipeOptions.MaximumSizeLow);
|
||||
Assert.Equal(expectedMaximumSizeHigh, connectionLifetime.AdaptedInputPipeOptions.MaximumSizeHigh);
|
||||
Assert.Equal(expectedMaximumSizeLow, connectionLifetime.AdaptedInputPipeOptions.ResumeWriterThreshold);
|
||||
Assert.Equal(expectedMaximumSizeHigh, connectionLifetime.AdaptedInputPipeOptions.PauseWriterThreshold);
|
||||
Assert.Same(serviceContext.ThreadPool, connectionLifetime.AdaptedInputPipeOptions.ReaderScheduler);
|
||||
Assert.Same(Scheduler.Inline, connectionLifetime.AdaptedInputPipeOptions.WriterScheduler);
|
||||
Assert.Same(PipeScheduler.Inline, connectionLifetime.AdaptedInputPipeOptions.WriterScheduler);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
@ -85,10 +85,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
ServiceContext = serviceContext
|
||||
});
|
||||
|
||||
Assert.Equal(expectedMaximumSizeLow, connectionLifetime.AdaptedOutputPipeOptions.MaximumSizeLow);
|
||||
Assert.Equal(expectedMaximumSizeHigh, connectionLifetime.AdaptedOutputPipeOptions.MaximumSizeHigh);
|
||||
Assert.Same(Scheduler.Inline, connectionLifetime.AdaptedOutputPipeOptions.ReaderScheduler);
|
||||
Assert.Same(Scheduler.Inline, connectionLifetime.AdaptedOutputPipeOptions.WriterScheduler);
|
||||
Assert.Equal(expectedMaximumSizeLow, connectionLifetime.AdaptedOutputPipeOptions.ResumeWriterThreshold);
|
||||
Assert.Equal(expectedMaximumSizeHigh, connectionLifetime.AdaptedOutputPipeOptions.PauseWriterThreshold);
|
||||
Assert.Same(PipeScheduler.Inline, connectionLifetime.AdaptedOutputPipeOptions.ReaderScheduler);
|
||||
Assert.Same(PipeScheduler.Inline, connectionLifetime.AdaptedOutputPipeOptions.WriterScheduler);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
// ulong.MaxValue.ToString().Length
|
||||
private const int _ulongMaxValueLength = 20;
|
||||
|
||||
private readonly IPipe _pipe;
|
||||
private readonly Pipe _pipe;
|
||||
private readonly MemoryPool _memoryPool = new MemoryPool();
|
||||
|
||||
public PipelineExtensionTests()
|
||||
|
|
@ -34,8 +34,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
[InlineData(4_8_15_16_23_42)]
|
||||
public void WritesNumericToAscii(ulong number)
|
||||
{
|
||||
var writerBuffer = _pipe.Writer.Alloc();
|
||||
var writer = new WritableBufferWriter(writerBuffer);
|
||||
var writerBuffer = _pipe.Writer;
|
||||
var writer = OutputWriter.Create(writerBuffer);
|
||||
writer.WriteNumeric(number);
|
||||
writerBuffer.FlushAsync().GetAwaiter().GetResult();
|
||||
|
||||
|
|
@ -51,8 +51,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
[InlineData(_ulongMaxValueLength - 1)]
|
||||
public void WritesNumericAcrossSpanBoundaries(int gapSize)
|
||||
{
|
||||
var writerBuffer = _pipe.Writer.Alloc(100);
|
||||
var writer = new WritableBufferWriter(writerBuffer);
|
||||
var writerBuffer = _pipe.Writer;
|
||||
var writer = OutputWriter.Create(writerBuffer);
|
||||
// almost fill up the first block
|
||||
var spacer = new byte[writer.Span.Length - gapSize];
|
||||
writer.Write(spacer);
|
||||
|
|
@ -66,7 +66,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
var reader = _pipe.Reader.ReadAsync().GetAwaiter().GetResult();
|
||||
var numAsString = ulong.MaxValue.ToString();
|
||||
var written = reader.Buffer.Slice(spacer.Length, numAsString.Length);
|
||||
Assert.False(written.IsSingleSpan, "The buffer should cross spans");
|
||||
Assert.False(written.IsSingleSegment, "The buffer should cross spans");
|
||||
AssertExtensions.Equal(Encoding.ASCII.GetBytes(numAsString), written.ToArray());
|
||||
}
|
||||
|
||||
|
|
@ -82,8 +82,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
[InlineData(null, new byte[0])]
|
||||
public void EncodesAsAscii(string input, byte[] expected)
|
||||
{
|
||||
var writerBuffer = _pipe.Writer.Alloc();
|
||||
var writer = new WritableBufferWriter(writerBuffer);
|
||||
var writerBuffer = _pipe.Writer;
|
||||
var writer = OutputWriter.Create(writerBuffer);
|
||||
writer.WriteAsciiNoValidation(input);
|
||||
writerBuffer.FlushAsync().GetAwaiter().GetResult();
|
||||
var reader = _pipe.Reader.ReadAsync().GetAwaiter().GetResult();
|
||||
|
|
@ -109,8 +109,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
{
|
||||
// WriteAscii doesn't validate if characters are in the ASCII range
|
||||
// but it shouldn't produce more than one byte per character
|
||||
var writerBuffer = _pipe.Writer.Alloc();
|
||||
var writer = new WritableBufferWriter(writerBuffer);
|
||||
var writerBuffer = _pipe.Writer;
|
||||
var writer = OutputWriter.Create(writerBuffer);
|
||||
writer.WriteAsciiNoValidation(input);
|
||||
writerBuffer.FlushAsync().GetAwaiter().GetResult();
|
||||
var reader = _pipe.Reader.ReadAsync().GetAwaiter().GetResult();
|
||||
|
|
@ -122,8 +122,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
public void WriteAsciiNoValidation()
|
||||
{
|
||||
const byte maxAscii = 0x7f;
|
||||
var writerBuffer = _pipe.Writer.Alloc();
|
||||
var writer = new WritableBufferWriter(writerBuffer);
|
||||
var writerBuffer = _pipe.Writer;
|
||||
var writer = OutputWriter.Create(writerBuffer);
|
||||
for (var i = 0; i < maxAscii; i++)
|
||||
{
|
||||
writer.WriteAsciiNoValidation(new string((char)i, 1));
|
||||
|
|
@ -151,8 +151,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
public void WritesAsciiAcrossBlockBoundaries(int stringLength, int gapSize)
|
||||
{
|
||||
var testString = new string(' ', stringLength);
|
||||
var writerBuffer = _pipe.Writer.Alloc(100);
|
||||
var writer = new WritableBufferWriter(writerBuffer);
|
||||
var writerBuffer = _pipe.Writer;
|
||||
var writer = OutputWriter.Create(writerBuffer);
|
||||
// almost fill up the first block
|
||||
var spacer = new byte[writer.Span.Length - gapSize];
|
||||
writer.Write(spacer);
|
||||
|
|
@ -166,7 +166,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
|
||||
var reader = _pipe.Reader.ReadAsync().GetAwaiter().GetResult();
|
||||
var written = reader.Buffer.Slice(spacer.Length, stringLength);
|
||||
Assert.False(written.IsSingleSpan, "The buffer should cross spans");
|
||||
Assert.False(written.IsSingleSegment, "The buffer should cross spans");
|
||||
AssertExtensions.Equal(Encoding.ASCII.GetBytes(testString), written.ToArray());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,9 +38,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
Http1Connection.HttpResponseControl = Mock.Of<IHttpResponseControl>();
|
||||
}
|
||||
|
||||
public IPipeConnection Transport { get; }
|
||||
public IDuplexPipe Transport { get; }
|
||||
|
||||
public IPipeConnection Application { get; }
|
||||
public IDuplexPipe Application { get; }
|
||||
|
||||
public Http1ConnectionContext Http1ConnectionContext { get; }
|
||||
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
|||
mockConnectionHandler.InputOptions = pool =>
|
||||
new PipeOptions(
|
||||
pool: pool,
|
||||
maximumSizeHigh: 3);
|
||||
pauseWriterThreshold: 3);
|
||||
|
||||
// We don't set the output writer scheduler here since we want to run the callback inline
|
||||
|
||||
|
|
@ -117,7 +117,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
|||
var transportContext = new TestLibuvTransportContext() { ConnectionHandler = mockConnectionHandler };
|
||||
var transport = new LibuvTransport(mockLibuv, transportContext, null);
|
||||
var thread = new LibuvThread(transport);
|
||||
var mockScheduler = new Mock<Scheduler>();
|
||||
var mockScheduler = new Mock<PipeScheduler>();
|
||||
Action backPressure = null;
|
||||
mockScheduler.Setup(m => m.Schedule(It.IsAny<Action>())).Callback<Action>(a =>
|
||||
{
|
||||
|
|
@ -126,8 +126,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
|||
mockConnectionHandler.InputOptions = pool =>
|
||||
new PipeOptions(
|
||||
pool: pool,
|
||||
maximumSizeHigh: 3,
|
||||
maximumSizeLow: 3,
|
||||
pauseWriterThreshold: 3,
|
||||
resumeWriterThreshold: 3,
|
||||
writerScheduler: mockScheduler.Object);
|
||||
|
||||
mockConnectionHandler.OutputOptions = pool => new PipeOptions(pool: pool, readerScheduler:thread );
|
||||
|
|
@ -161,7 +161,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
|||
var result = await mockConnectionHandler.Input.Reader.ReadAsync();
|
||||
// Calling advance will call into our custom scheduler that captures the back pressure
|
||||
// callback
|
||||
mockConnectionHandler.Input.Reader.Advance(result.Buffer.End);
|
||||
mockConnectionHandler.Input.Reader.AdvanceTo(result.Buffer.End);
|
||||
|
||||
// Cancel the current pending flush
|
||||
mockConnectionHandler.Input.Writer.CancelPendingFlush();
|
||||
|
|
|
|||
|
|
@ -60,14 +60,14 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
|||
// SocketOutput, the write callback would never be invoked for writes larger than
|
||||
// maxResponseBufferSize even after the write actually completed.
|
||||
|
||||
// ConnectionHandler will set MaximumSizeHigh/Low to zero when MaxResponseBufferSize is null.
|
||||
// ConnectionHandler will set Pause/ResumeWriterThreshold to zero when MaxResponseBufferSize is null.
|
||||
// This is verified in PipeOptionsTests.OutputPipeOptionsConfiguredCorrectly.
|
||||
var pipeOptions = new PipeOptions
|
||||
(
|
||||
pool: _memoryPool,
|
||||
readerScheduler: _libuvThread,
|
||||
maximumSizeHigh: maxResponseBufferSize ?? 0,
|
||||
maximumSizeLow: maxResponseBufferSize ?? 0
|
||||
pauseWriterThreshold: maxResponseBufferSize ?? 0,
|
||||
resumeWriterThreshold: maxResponseBufferSize ?? 0
|
||||
);
|
||||
|
||||
using (var outputProducer = CreateOutputProducer(pipeOptions))
|
||||
|
|
@ -96,14 +96,14 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
|||
return 0;
|
||||
};
|
||||
|
||||
// ConnectionHandler will set MaximumSizeHigh/Low to zero when MaxResponseBufferSize is null.
|
||||
// ConnectionHandler will set Pause/ResumeWriterThreshold to zero when MaxResponseBufferSize is null.
|
||||
// This is verified in PipeOptionsTests.OutputPipeOptionsConfiguredCorrectly.
|
||||
var pipeOptions = new PipeOptions
|
||||
(
|
||||
pool: _memoryPool,
|
||||
readerScheduler: _libuvThread,
|
||||
maximumSizeHigh: 0,
|
||||
maximumSizeLow: 0
|
||||
pauseWriterThreshold: 0,
|
||||
resumeWriterThreshold: 0
|
||||
);
|
||||
|
||||
using (var outputProducer = CreateOutputProducer(pipeOptions))
|
||||
|
|
@ -144,14 +144,14 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
|||
return 0;
|
||||
};
|
||||
|
||||
// ConnectionHandler will set MaximumSizeHigh/Low to 1 when MaxResponseBufferSize is zero.
|
||||
// ConnectionHandler will set Pause/ResumeWriterThreshold to 1 when MaxResponseBufferSize is zero.
|
||||
// This is verified in PipeOptionsTests.OutputPipeOptionsConfiguredCorrectly.
|
||||
var pipeOptions = new PipeOptions
|
||||
(
|
||||
pool: _memoryPool,
|
||||
readerScheduler: _libuvThread,
|
||||
maximumSizeHigh: 1,
|
||||
maximumSizeLow: 1
|
||||
pauseWriterThreshold: 1,
|
||||
resumeWriterThreshold: 1
|
||||
);
|
||||
|
||||
using (var outputProducer = CreateOutputProducer(pipeOptions))
|
||||
|
|
@ -206,8 +206,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
|||
(
|
||||
pool: _memoryPool,
|
||||
readerScheduler: _libuvThread,
|
||||
maximumSizeHigh: maxResponseBufferSize,
|
||||
maximumSizeLow: maxResponseBufferSize
|
||||
pauseWriterThreshold: maxResponseBufferSize,
|
||||
resumeWriterThreshold: maxResponseBufferSize
|
||||
);
|
||||
|
||||
using (var outputProducer = CreateOutputProducer(pipeOptions))
|
||||
|
|
@ -270,8 +270,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
|||
(
|
||||
pool: _memoryPool,
|
||||
readerScheduler: _libuvThread,
|
||||
maximumSizeHigh: maxResponseBufferSize,
|
||||
maximumSizeLow: maxResponseBufferSize
|
||||
pauseWriterThreshold: maxResponseBufferSize,
|
||||
resumeWriterThreshold: maxResponseBufferSize
|
||||
);
|
||||
|
||||
using (var outputProducer = CreateOutputProducer(pipeOptions))
|
||||
|
|
@ -340,8 +340,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
|||
(
|
||||
pool: _memoryPool,
|
||||
readerScheduler: _libuvThread,
|
||||
maximumSizeHigh: maxResponseBufferSize,
|
||||
maximumSizeLow: maxResponseBufferSize
|
||||
pauseWriterThreshold: maxResponseBufferSize,
|
||||
resumeWriterThreshold: maxResponseBufferSize
|
||||
);
|
||||
|
||||
using (var outputProducer = CreateOutputProducer(pipeOptions, abortedSource))
|
||||
|
|
@ -433,8 +433,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
|||
(
|
||||
pool: _memoryPool,
|
||||
readerScheduler: _libuvThread,
|
||||
maximumSizeHigh: maxResponseBufferSize,
|
||||
maximumSizeLow: maxResponseBufferSize
|
||||
pauseWriterThreshold: maxResponseBufferSize,
|
||||
resumeWriterThreshold: maxResponseBufferSize
|
||||
);
|
||||
|
||||
using (var outputProducer = CreateOutputProducer(pipeOptions))
|
||||
|
|
@ -517,8 +517,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
|||
(
|
||||
pool: _memoryPool,
|
||||
readerScheduler: _libuvThread,
|
||||
maximumSizeHigh: maxResponseBufferSize,
|
||||
maximumSizeLow: maxResponseBufferSize
|
||||
pauseWriterThreshold: maxResponseBufferSize,
|
||||
resumeWriterThreshold: maxResponseBufferSize
|
||||
);
|
||||
|
||||
using (var outputProducer = CreateOutputProducer(pipeOptions))
|
||||
|
|
@ -599,8 +599,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
|||
(
|
||||
pool: _memoryPool,
|
||||
readerScheduler: _libuvThread,
|
||||
maximumSizeHigh: maxResponseBufferSize,
|
||||
maximumSizeLow: maxResponseBufferSize
|
||||
pauseWriterThreshold: maxResponseBufferSize,
|
||||
resumeWriterThreshold: maxResponseBufferSize
|
||||
);
|
||||
|
||||
using (var outputProducer = CreateOutputProducer(pipeOptions))
|
||||
|
|
@ -654,14 +654,14 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
|||
return 0;
|
||||
};
|
||||
|
||||
// ConnectionHandler will set MaximumSizeHigh/Low to zero when MaxResponseBufferSize is null.
|
||||
// ConnectionHandler will set Pause/ResumeWriterThreshold to zero when MaxResponseBufferSize is null.
|
||||
// This is verified in PipeOptionsTests.OutputPipeOptionsConfiguredCorrectly.
|
||||
var pipeOptions = new PipeOptions
|
||||
(
|
||||
pool: _memoryPool,
|
||||
readerScheduler: _libuvThread,
|
||||
maximumSizeHigh: maxResponseBufferSize ?? 0,
|
||||
maximumSizeLow: maxResponseBufferSize ?? 0
|
||||
pauseWriterThreshold: maxResponseBufferSize ?? 0,
|
||||
resumeWriterThreshold: maxResponseBufferSize ?? 0
|
||||
);
|
||||
|
||||
using (var outputProducer = CreateOutputProducer(pipeOptions))
|
||||
|
|
@ -728,7 +728,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
|||
return (Http1OutputProducer)http1Connection.Output;
|
||||
}
|
||||
|
||||
private async Task WriteOutputAsync(LibuvOutputConsumer consumer, IPipeReader outputReader, Http1Connection http1Connection)
|
||||
private async Task WriteOutputAsync(LibuvOutputConsumer consumer, PipeReader outputReader, Http1Connection http1Connection)
|
||||
{
|
||||
// This WriteOutputAsync() calling code is equivalent to that in LibuvConnection.
|
||||
try
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
|||
|
||||
await writeRequest.WriteAsync(
|
||||
serverConnectionPipe,
|
||||
new ReadOnlyBuffer(new byte[] { 1, 2, 3, 4 }));
|
||||
new ReadOnlyBuffer<byte>(new byte[] { 1, 2, 3, 4 }));
|
||||
|
||||
writeRequest.Dispose();
|
||||
serverConnectionPipe.Dispose();
|
||||
|
|
|
|||
|
|
@ -162,7 +162,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
|||
{
|
||||
var req = new UvWriteReq(_logger);
|
||||
req.DangerousInit(loop);
|
||||
var block = new ReadOnlyBuffer(new byte[] { 65, 66, 67, 68, 69 });
|
||||
var block = new ReadOnlyBuffer<byte>(new byte[] { 65, 66, 67, 68, 69 });
|
||||
|
||||
await req.WriteAsync(
|
||||
tcp2,
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests.TestHelpers
|
|||
feature.Application = new PipeConnection(Output.Reader, Input.Writer);
|
||||
}
|
||||
|
||||
public IPipe Input { get; private set; }
|
||||
public IPipe Output { get; private set; }
|
||||
public Pipe Input { get; private set; }
|
||||
public Pipe Output { get; private set; }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,9 +7,6 @@
|
|||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Kestrel.Core\Kestrel.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Hosting" Version="$(MicrosoftAspNetCoreHostingPackageVersion)" />
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ using System.Collections.Generic;
|
|||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
using Microsoft.AspNetCore.Http.Features.Authentication;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Features;
|
||||
//using Microsoft.AspNetCore.Server.Kestrel.Core.Features;
|
||||
|
||||
namespace CodeGenerator
|
||||
{
|
||||
|
|
@ -23,39 +23,39 @@ namespace CodeGenerator
|
|||
{
|
||||
var alwaysFeatures = new[]
|
||||
{
|
||||
typeof(IHttpRequestFeature),
|
||||
typeof(IHttpResponseFeature),
|
||||
typeof(IHttpRequestIdentifierFeature),
|
||||
typeof(IServiceProvidersFeature),
|
||||
typeof(IHttpRequestLifetimeFeature),
|
||||
typeof(IHttpConnectionFeature),
|
||||
"IHttpRequestFeature",
|
||||
"IHttpResponseFeature",
|
||||
"IHttpRequestIdentifierFeature",
|
||||
"IServiceProvidersFeature",
|
||||
"IHttpRequestLifetimeFeature",
|
||||
"IHttpConnectionFeature",
|
||||
};
|
||||
|
||||
var commonFeatures = new[]
|
||||
{
|
||||
typeof(IHttpAuthenticationFeature),
|
||||
typeof(IQueryFeature),
|
||||
typeof(IFormFeature),
|
||||
"IHttpAuthenticationFeature",
|
||||
"IQueryFeature",
|
||||
"IFormFeature",
|
||||
};
|
||||
|
||||
var sometimesFeatures = new[]
|
||||
{
|
||||
typeof(IHttpUpgradeFeature),
|
||||
typeof(IHttp2StreamIdFeature),
|
||||
typeof(IResponseCookiesFeature),
|
||||
typeof(IItemsFeature),
|
||||
typeof(ITlsConnectionFeature),
|
||||
typeof(IHttpWebSocketFeature),
|
||||
typeof(ISessionFeature),
|
||||
typeof(IHttpMaxRequestBodySizeFeature),
|
||||
typeof(IHttpMinRequestBodyDataRateFeature),
|
||||
typeof(IHttpMinResponseDataRateFeature),
|
||||
typeof(IHttpBodyControlFeature),
|
||||
"IHttpUpgradeFeature",
|
||||
"IHttp2StreamIdFeature",
|
||||
"IResponseCookiesFeature",
|
||||
"IItemsFeature",
|
||||
"ITlsConnectionFeature",
|
||||
"IHttpWebSocketFeature",
|
||||
"ISessionFeature",
|
||||
"IHttpMaxRequestBodySizeFeature",
|
||||
"IHttpMinRequestBodyDataRateFeature",
|
||||
"IHttpMinResponseDataRateFeature",
|
||||
"IHttpBodyControlFeature",
|
||||
};
|
||||
|
||||
var rareFeatures = new[]
|
||||
{
|
||||
typeof(IHttpSendFileFeature),
|
||||
"IHttpSendFileFeature",
|
||||
};
|
||||
|
||||
var allFeatures = alwaysFeatures.Concat(commonFeatures).Concat(sometimesFeatures).Concat(rareFeatures);
|
||||
|
|
@ -64,15 +64,15 @@ namespace CodeGenerator
|
|||
// See also: src/Kestrel/Http/HttpProtocol.FeatureCollection.cs
|
||||
var implementedFeatures = new[]
|
||||
{
|
||||
typeof(IHttpRequestFeature),
|
||||
typeof(IHttpResponseFeature),
|
||||
typeof(IHttpRequestIdentifierFeature),
|
||||
typeof(IHttpRequestLifetimeFeature),
|
||||
typeof(IHttpConnectionFeature),
|
||||
typeof(IHttpMaxRequestBodySizeFeature),
|
||||
typeof(IHttpMinRequestBodyDataRateFeature),
|
||||
typeof(IHttpMinResponseDataRateFeature),
|
||||
typeof(IHttpBodyControlFeature),
|
||||
"IHttpRequestFeature",
|
||||
"IHttpResponseFeature",
|
||||
"IHttpRequestIdentifierFeature",
|
||||
"IHttpRequestLifetimeFeature",
|
||||
"IHttpConnectionFeature",
|
||||
"IHttpMaxRequestBodySizeFeature",
|
||||
"IHttpMinRequestBodyDataRateFeature",
|
||||
"IHttpMinResponseDataRateFeature",
|
||||
"IHttpBodyControlFeature",
|
||||
};
|
||||
|
||||
return $@"// Copyright (c) .NET Foundation. All rights reserved.
|
||||
|
|
@ -81,26 +81,30 @@ namespace CodeGenerator
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
using Microsoft.AspNetCore.Http.Features.Authentication;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Features;
|
||||
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
||||
{{
|
||||
public partial class {className}
|
||||
{{{Each(allFeatures, feature => $@"
|
||||
private static readonly Type {feature.Name}Type = typeof(global::{feature.FullName});")}
|
||||
private static readonly Type {feature}Type = typeof({feature});")}
|
||||
{Each(allFeatures, feature => $@"
|
||||
private object _current{feature.Name};")}
|
||||
private object _current{feature};")}
|
||||
|
||||
private void FastReset()
|
||||
{{{Each(implementedFeatures, feature => $@"
|
||||
_current{feature.Name} = this;")}
|
||||
_current{feature} = this;")}
|
||||
{Each(allFeatures.Where(f => !implementedFeatures.Contains(f)), feature => $@"
|
||||
_current{feature.Name} = null;")}
|
||||
_current{feature} = null;")}
|
||||
}}
|
||||
|
||||
internal object FastFeatureGet(Type key)
|
||||
{{{Each(allFeatures, feature => $@"
|
||||
if (key == {feature.Name}Type)
|
||||
if (key == {feature}Type)
|
||||
{{
|
||||
return _current{feature.Name};
|
||||
return _current{feature};
|
||||
}}")}
|
||||
return ExtraFeatureGet(key);
|
||||
}}
|
||||
|
|
@ -109,9 +113,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
{{
|
||||
_featureRevision++;
|
||||
{Each(allFeatures, feature => $@"
|
||||
if (key == {feature.Name}Type)
|
||||
if (key == {feature}Type)
|
||||
{{
|
||||
_current{feature.Name} = feature;
|
||||
_current{feature} = feature;
|
||||
return;
|
||||
}}")};
|
||||
ExtraFeatureSet(key, feature);
|
||||
|
|
@ -119,9 +123,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
|
||||
private IEnumerable<KeyValuePair<Type, object>> FastEnumerable()
|
||||
{{{Each(allFeatures, feature => $@"
|
||||
if (_current{feature.Name} != null)
|
||||
if (_current{feature} != null)
|
||||
{{
|
||||
yield return new KeyValuePair<Type, object>({feature.Name}Type, _current{feature.Name} as global::{feature.FullName});
|
||||
yield return new KeyValuePair<Type, object>({feature}Type, _current{feature} as {feature});
|
||||
}}")}
|
||||
|
||||
if (MaybeExtra != null)
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ using System.Diagnostics;
|
|||
using System.Linq;
|
||||
using System.Text;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
|
||||
|
||||
namespace CodeGenerator.HttpUtilities
|
||||
{
|
||||
|
|
@ -17,27 +16,27 @@ namespace CodeGenerator.HttpUtilities
|
|||
{
|
||||
var httpMethods = new []
|
||||
{
|
||||
new Tuple<string, HttpMethod>("CONNECT ", HttpMethod.Connect),
|
||||
new Tuple<string, HttpMethod>("DELETE ", HttpMethod.Delete),
|
||||
new Tuple<string, HttpMethod>("HEAD ", HttpMethod.Head),
|
||||
new Tuple<string, HttpMethod>("PATCH ", HttpMethod.Patch),
|
||||
new Tuple<string, HttpMethod>("POST ", HttpMethod.Post),
|
||||
new Tuple<string, HttpMethod>("PUT ", HttpMethod.Put),
|
||||
new Tuple<string, HttpMethod>("OPTIONS ", HttpMethod.Options),
|
||||
new Tuple<string, HttpMethod>("TRACE ", HttpMethod.Trace),
|
||||
new Tuple<string, HttpMethod>("GET ", HttpMethod.Get)
|
||||
new Tuple<string, String>("CONNECT ", "Connect"),
|
||||
new Tuple<string, String>("DELETE ", "Delete"),
|
||||
new Tuple<string, String>("HEAD ", "Head"),
|
||||
new Tuple<string, String>("PATCH ", "Patch"),
|
||||
new Tuple<string, String>("POST ", "Post"),
|
||||
new Tuple<string, String>("PUT ", "Put"),
|
||||
new Tuple<string, String>("OPTIONS ", "Options"),
|
||||
new Tuple<string, String>("TRACE ", "Trace"),
|
||||
new Tuple<string, String>("GET ", "Get")
|
||||
};
|
||||
|
||||
return GenerateFile(httpMethods);
|
||||
}
|
||||
|
||||
private static string GenerateFile(Tuple<string, HttpMethod>[] httpMethods)
|
||||
private static string GenerateFile(Tuple<string, String>[] httpMethods)
|
||||
{
|
||||
var maskLength = (byte)Math.Ceiling(Math.Log(httpMethods.Length, 2));
|
||||
|
||||
var methodsInfo = httpMethods.Select(GetMethodStringAndUlongAndMaskLength).ToList();
|
||||
|
||||
var methodsInfoWithoutGet = methodsInfo.Where(m => m.HttpMethod != HttpMethod.Get.ToString()).ToList();
|
||||
var methodsInfoWithoutGet = methodsInfo.Where(m => m.HttpMethod != "Get".ToString()).ToList();
|
||||
|
||||
var methodsAsciiStringAsLong = methodsInfo.Select(m => m.AsciiStringAsLong).ToArray();
|
||||
|
||||
|
|
@ -158,7 +157,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
|
|||
var maskFieldName = GetMaskFieldName(methodInfo.MaskLength);
|
||||
var httpMethodFieldName = GetHttpMethodFieldName(methodInfo);
|
||||
|
||||
result.AppendFormat(" SetKnownMethod({0}, {1}, {2}.{3}, {4});", maskFieldName, httpMethodFieldName, typeof(HttpMethod).Name, methodInfo.HttpMethod, methodInfo.MaskLength - 1);
|
||||
result.AppendFormat(" SetKnownMethod({0}, {1}, HttpMethod.{3}, {4});", maskFieldName, httpMethodFieldName, typeof(String).Name, methodInfo.HttpMethod, methodInfo.MaskLength - 1);
|
||||
|
||||
if (index < methodsInfo.Count - 1)
|
||||
{
|
||||
|
|
@ -181,7 +180,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
|
|||
{
|
||||
var methodInfo = methodsInfo[index];
|
||||
|
||||
result.AppendFormat(" _methodNames[(byte){0}.{1}] = {2}.{3};", typeof(HttpMethod).Name, methodInfo.HttpMethod, typeof(HttpMethods).Name, methodInfo.HttpMethod);
|
||||
result.AppendFormat(" _methodNames[(byte)HttpMethod.{1}] = {2}.{3};", typeof(String).Name, methodInfo.HttpMethod, typeof(HttpMethods).Name, methodInfo.HttpMethod);
|
||||
|
||||
if (index < methodsInfo.Count - 1)
|
||||
{
|
||||
|
|
@ -281,7 +280,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
|
|||
public int MaskLength;
|
||||
}
|
||||
|
||||
private static MethodInfo GetMethodStringAndUlongAndMaskLength(Tuple<string, HttpMethod> method)
|
||||
private static MethodInfo GetMethodStringAndUlongAndMaskLength(Tuple<string, string> method)
|
||||
{
|
||||
var methodString = GetMethodString(method.Item1);
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ using System.Collections.Generic;
|
|||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
|
||||
|
||||
namespace CodeGenerator
|
||||
{
|
||||
|
|
@ -266,14 +265,14 @@ namespace CodeGenerator
|
|||
{
|
||||
Headers = requestHeaders,
|
||||
HeadersByLength = requestHeaders.GroupBy(x => x.Name.Length),
|
||||
ClassName = nameof(HttpRequestHeaders),
|
||||
ClassName = "HttpRequestHeaders",
|
||||
Bytes = default(byte[])
|
||||
},
|
||||
new
|
||||
{
|
||||
Headers = responseHeaders,
|
||||
HeadersByLength = responseHeaders.GroupBy(x => x.Name.Length),
|
||||
ClassName = nameof(HttpResponseHeaders),
|
||||
ClassName = "HttpResponseHeaders",
|
||||
Bytes = responseHeaders.SelectMany(header => header.Bytes).ToArray()
|
||||
}
|
||||
};
|
||||
|
|
@ -293,6 +292,7 @@ namespace CodeGenerator
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
|
||||
using System.Buffers;
|
||||
using System.IO.Pipelines;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
|
|
@ -384,7 +384,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
}}
|
||||
|
||||
protected override void SetValueFast(string key, StringValues value)
|
||||
{{{(loop.ClassName == nameof(HttpResponseHeaders) ? @"
|
||||
{{{(loop.ClassName == "HttpResponseHeaders" ? @"
|
||||
ValidateHeaderCharacters(value);" : "")}
|
||||
switch (key.Length)
|
||||
{{{Each(loop.HeadersByLength, byLength => $@"
|
||||
|
|
@ -406,7 +406,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
}}
|
||||
|
||||
protected override bool AddValueFast(string key, StringValues value)
|
||||
{{{(loop.ClassName == nameof(HttpResponseHeaders) ? @"
|
||||
{{{(loop.ClassName == "HttpResponseHeaders" ? @"
|
||||
ValidateHeaderCharacters(value);" : "")}
|
||||
switch (key.Length)
|
||||
{{{Each(loop.HeadersByLength, byLength => $@"
|
||||
|
|
@ -432,7 +432,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
}}
|
||||
break;")}
|
||||
}}
|
||||
{(loop.ClassName == nameof(HttpResponseHeaders) ? @"
|
||||
{(loop.ClassName == "HttpResponseHeaders" ? @"
|
||||
ValidateHeaderCharacters(key);" : "")}
|
||||
Unknown.Add(key, value);
|
||||
// Return true, above will throw and exit for false
|
||||
|
|
@ -522,8 +522,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
|
||||
return true;
|
||||
}}
|
||||
{(loop.ClassName == nameof(HttpResponseHeaders) ? $@"
|
||||
protected void CopyToFast(ref WritableBufferWriter output)
|
||||
{(loop.ClassName == "HttpResponseHeaders" ? $@"
|
||||
protected void CopyToFast(ref OutputWriter<PipeWriter> output)
|
||||
{{
|
||||
var tempBits = _bits | (_contentLength.HasValue ? {1L << 63}L : 0);
|
||||
{Each(loop.Headers.Where(header => header.Identifier != "ContentLength").OrderBy(h => !h.PrimaryHeader), header => $@"
|
||||
|
|
@ -541,7 +541,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._{header.Identifier}[i];
|
||||
if (value != null)
|
||||
{{
|
||||
output.Write(_headerBytes, {header.BytesOffset}, {header.BytesCount});
|
||||
output.Write(new ReadOnlySpan<byte>(_headerBytes, {header.BytesOffset}, {header.BytesCount}));
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}}
|
||||
}}
|
||||
|
|
@ -555,7 +555,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
}}{(header.Identifier == "Server" ? $@"
|
||||
if ((tempBits & {1L << 63}L) != 0)
|
||||
{{
|
||||
output.Write(_headerBytes, {loop.Headers.First(x => x.Identifier == "ContentLength").BytesOffset}, {loop.Headers.First(x => x.Identifier == "ContentLength").BytesCount});
|
||||
output.Write(new ReadOnlySpan<byte>(_headerBytes, {loop.Headers.First(x => x.Identifier == "ContentLength").BytesOffset}, {loop.Headers.First(x => x.Identifier == "ContentLength").BytesCount}));
|
||||
PipelineExtensions.WriteNumeric(ref output, (ulong)ContentLength.Value);
|
||||
|
||||
if((tempBits & ~{1L << 63}L) == 0)
|
||||
|
|
@ -565,7 +565,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
tempBits &= ~{1L << 63}L;
|
||||
}}" : "")}")}
|
||||
}}" : "")}
|
||||
{(loop.ClassName == nameof(HttpRequestHeaders) ? $@"
|
||||
{(loop.ClassName == "HttpRequestHeaders" ? $@"
|
||||
public unsafe void Append(byte* pKeyBytes, int keyLength, string value)
|
||||
{{
|
||||
var pUB = pKeyBytes;
|
||||
|
|
|
|||
|
|
@ -3,8 +3,6 @@
|
|||
|
||||
using System;
|
||||
using System.IO;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Features;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
|
||||
|
||||
namespace CodeGenerator
|
||||
{
|
||||
|
|
@ -36,7 +34,7 @@ namespace CodeGenerator
|
|||
public static void Run(string knownHeadersPath, string httpProtocolFeatureCollectionPath, string httpUtilitiesPath)
|
||||
{
|
||||
var knownHeadersContent = KnownHeaders.GeneratedFile();
|
||||
var httpProtocolFeatureCollectionContent = HttpProtocolFeatureCollection.GeneratedFile(nameof(HttpProtocol));
|
||||
var httpProtocolFeatureCollectionContent = HttpProtocolFeatureCollection.GeneratedFile("HttpProtocol");
|
||||
var httpUtilitiesContent = HttpUtilities.HttpUtilities.GeneratedFile();
|
||||
|
||||
var existingKnownHeaders = File.Exists(knownHeadersPath) ? File.ReadAllText(knownHeadersPath) : "";
|
||||
|
|
|
|||
Loading…
Reference in New Issue