React to pipes in corefx (#2337)
This commit is contained in:
parent
a3911269c5
commit
2c108d9ba1
|
|
@ -17,5 +17,7 @@
|
|||
<PublicSign Condition="'$(OS)' != 'Windows_NT'">true</PublicSign>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<!-- https://github.com/aspnet/KestrelHttpServer/issues/2350 -->
|
||||
<EnableApiCheck>false</EnableApiCheck>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ using Microsoft.AspNetCore.Server.Kestrel.Core;
|
|||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Performance.Mocks;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
|
||||
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
||||
{
|
||||
|
|
@ -16,13 +17,13 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
|||
{
|
||||
private const int InnerLoopCount = 512;
|
||||
|
||||
public ReadOnlyBuffer<byte> _buffer;
|
||||
public ReadOnlySequence<byte> _buffer;
|
||||
public Http1Connection _http1Connection;
|
||||
|
||||
[IterationSetup]
|
||||
public void Setup()
|
||||
{
|
||||
var memoryPool = new MemoryPool();
|
||||
var memoryPool = KestrelMemoryPool.Create();
|
||||
var pair = DuplexPipe.CreateConnectionPair(memoryPool);
|
||||
|
||||
var serviceContext = new ServiceContext
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ using Microsoft.AspNetCore.Http.Features;
|
|||
using Microsoft.AspNetCore.Server.Kestrel.Core;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
|
||||
using Microsoft.AspNetCore.Testing;
|
||||
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
||||
|
|
@ -24,15 +25,17 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
|||
private static readonly Task _psuedoAsyncTask = Task.FromResult(27);
|
||||
private static readonly Func<object, Task> _psuedoAsyncTaskFunc = (obj) => _psuedoAsyncTask;
|
||||
|
||||
private readonly TestHttp1Connection _http1Connection;
|
||||
private TestHttp1Connection _http1Connection;
|
||||
private DuplexPipe.DuplexPipePair _pair;
|
||||
private MemoryPool<byte> _memoryPool;
|
||||
|
||||
private readonly byte[] _writeData;
|
||||
private readonly byte[] _writeData = Encoding.ASCII.GetBytes("Hello, World!");
|
||||
|
||||
public Http1WritingBenchmark()
|
||||
[GlobalSetup]
|
||||
public void GlobalSetup()
|
||||
{
|
||||
_memoryPool = KestrelMemoryPool.Create();
|
||||
_http1Connection = MakeHttp1Connection();
|
||||
_writeData = Encoding.ASCII.GetBytes("Hello, World!");
|
||||
}
|
||||
|
||||
[Params(true, false)]
|
||||
|
|
@ -93,33 +96,30 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
|||
|
||||
private TestHttp1Connection MakeHttp1Connection()
|
||||
{
|
||||
using (var memoryPool = new MemoryPool())
|
||||
var pair = DuplexPipe.CreateConnectionPair(_memoryPool);
|
||||
_pair = pair;
|
||||
|
||||
var serviceContext = new ServiceContext
|
||||
{
|
||||
var pair = DuplexPipe.CreateConnectionPair(memoryPool);
|
||||
_pair = pair;
|
||||
DateHeaderValueManager = new DateHeaderValueManager(),
|
||||
ServerOptions = new KestrelServerOptions(),
|
||||
Log = new MockTrace(),
|
||||
HttpParser = new HttpParser<Http1ParsingHandler>()
|
||||
};
|
||||
|
||||
var serviceContext = new ServiceContext
|
||||
{
|
||||
DateHeaderValueManager = new DateHeaderValueManager(),
|
||||
ServerOptions = new KestrelServerOptions(),
|
||||
Log = new MockTrace(),
|
||||
HttpParser = new HttpParser<Http1ParsingHandler>()
|
||||
};
|
||||
var http1Connection = new TestHttp1Connection(new Http1ConnectionContext
|
||||
{
|
||||
ServiceContext = serviceContext,
|
||||
ConnectionFeatures = new FeatureCollection(),
|
||||
MemoryPool = _memoryPool,
|
||||
Application = pair.Application,
|
||||
Transport = pair.Transport
|
||||
});
|
||||
|
||||
var http1Connection = new TestHttp1Connection(new Http1ConnectionContext
|
||||
{
|
||||
ServiceContext = serviceContext,
|
||||
ConnectionFeatures = new FeatureCollection(),
|
||||
MemoryPool = memoryPool,
|
||||
Application = pair.Application,
|
||||
Transport = pair.Transport
|
||||
});
|
||||
http1Connection.Reset();
|
||||
http1Connection.InitializeStreams(MessageBody.ZeroContentLengthKeepAlive);
|
||||
|
||||
http1Connection.Reset();
|
||||
http1Connection.InitializeStreams(MessageBody.ZeroContentLengthKeepAlive);
|
||||
|
||||
return http1Connection;
|
||||
}
|
||||
return http1Connection;
|
||||
}
|
||||
|
||||
[IterationCleanup]
|
||||
|
|
@ -138,5 +138,11 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
|||
Sync,
|
||||
Async
|
||||
}
|
||||
|
||||
[GlobalCleanup]
|
||||
public void Dispose()
|
||||
{
|
||||
_memoryPool?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
|||
{
|
||||
private readonly HttpParser<Adapter> _parser = new HttpParser<Adapter>();
|
||||
|
||||
private ReadOnlyBuffer<byte> _buffer;
|
||||
private ReadOnlySequence<byte> _buffer;
|
||||
|
||||
[Benchmark(Baseline = true, OperationsPerInvoke = RequestParsingData.InnerLoopCount)]
|
||||
public void PlaintextTechEmpower()
|
||||
|
|
@ -46,7 +46,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
|||
|
||||
private void InsertData(byte[] data)
|
||||
{
|
||||
_buffer = new ReadOnlyBuffer<byte>(data);
|
||||
_buffer = new ReadOnlySequence<byte>(data);
|
||||
}
|
||||
|
||||
private void ParseData()
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ using Microsoft.AspNetCore.Http.Features;
|
|||
using Microsoft.AspNetCore.Server.Kestrel.Core;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
|
||||
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
||||
{
|
||||
|
|
@ -78,7 +79,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
|||
|
||||
public HttpProtocolFeatureCollection()
|
||||
{
|
||||
var memoryPool = new MemoryPool();
|
||||
var memoryPool = KestrelMemoryPool.Create();
|
||||
var pair = DuplexPipe.CreateConnectionPair(memoryPool);
|
||||
|
||||
var serviceContext = new ServiceContext
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
|||
|
||||
public static readonly NullParser<Http1ParsingHandler> Instance = new NullParser<Http1ParsingHandler>();
|
||||
|
||||
public bool ParseHeaders(TRequestHandler handler, ReadOnlyBuffer<byte> buffer, out SequencePosition consumed, out SequencePosition examined, out int consumedBytes)
|
||||
public bool ParseHeaders(TRequestHandler handler, ReadOnlySequence<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));
|
||||
|
|
@ -35,7 +35,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
|||
return true;
|
||||
}
|
||||
|
||||
public bool ParseRequestLine(TRequestHandler handler, ReadOnlyBuffer<byte> buffer, out SequencePosition consumed, out SequencePosition examined)
|
||||
public bool ParseRequestLine(TRequestHandler handler, ReadOnlySequence<byte> buffer, out SequencePosition consumed, out SequencePosition examined)
|
||||
{
|
||||
handler.OnStartLine(HttpMethod.Get,
|
||||
HttpVersion.Http11,
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.IO.Pipelines;
|
||||
using System.Threading.Tasks;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
|
||||
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
||||
{
|
||||
|
|
@ -14,12 +16,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
|||
private const int InnerLoopCount = 512;
|
||||
|
||||
private Pipe _pipe;
|
||||
private MemoryPool _memoryPool;
|
||||
private MemoryPool<byte> _memoryPool;
|
||||
|
||||
[IterationSetup]
|
||||
public void Setup()
|
||||
{
|
||||
_memoryPool = new MemoryPool();
|
||||
_memoryPool = KestrelMemoryPool.Create();
|
||||
_pipe = new Pipe(new PipeOptions(_memoryPool));
|
||||
}
|
||||
|
||||
|
|
@ -62,5 +64,11 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
|||
_pipe.Reader.AdvanceTo(result.Buffer.End, result.Buffer.End);
|
||||
}
|
||||
}
|
||||
|
||||
[IterationCleanup]
|
||||
public void Cleanup()
|
||||
{
|
||||
_memoryPool.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,11 +9,14 @@ using Microsoft.AspNetCore.Server.Kestrel.Core;
|
|||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Performance.Mocks;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
|
||||
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
||||
{
|
||||
public class RequestParsingBenchmark
|
||||
{
|
||||
private MemoryPool<byte> _memoryPool;
|
||||
|
||||
public Pipe Pipe { get; set; }
|
||||
|
||||
public Http1Connection Http1Connection { get; set; }
|
||||
|
|
@ -21,8 +24,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
|||
[IterationSetup]
|
||||
public void Setup()
|
||||
{
|
||||
var memoryPool = new MemoryPool();
|
||||
var pair = DuplexPipe.CreateConnectionPair(memoryPool);
|
||||
_memoryPool = KestrelMemoryPool.Create();
|
||||
var pair = DuplexPipe.CreateConnectionPair(_memoryPool);
|
||||
|
||||
var serviceContext = new ServiceContext
|
||||
{
|
||||
|
|
@ -36,7 +39,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
|||
{
|
||||
ServiceContext = serviceContext,
|
||||
ConnectionFeatures = new FeatureCollection(),
|
||||
MemoryPool = memoryPool,
|
||||
MemoryPool = _memoryPool,
|
||||
Application = pair.Application,
|
||||
Transport = pair.Transport,
|
||||
TimeoutControl = new MockTimeoutControl()
|
||||
|
|
@ -45,7 +48,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
|||
http1Connection.Reset();
|
||||
|
||||
Http1Connection = http1Connection;
|
||||
Pipe = new Pipe(new PipeOptions(memoryPool));
|
||||
Pipe = new Pipe(new PipeOptions(_memoryPool));
|
||||
}
|
||||
|
||||
[Benchmark(Baseline = true, OperationsPerInvoke = RequestParsingData.InnerLoopCount)]
|
||||
|
|
@ -201,5 +204,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
|||
}
|
||||
while (true);
|
||||
}
|
||||
|
||||
|
||||
[IterationCleanup]
|
||||
public void Cleanup()
|
||||
{
|
||||
_memoryPool.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ using Microsoft.AspNetCore.Http.Internal;
|
|||
using Microsoft.AspNetCore.Server.Kestrel.Core;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
|
||||
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
||||
{
|
||||
|
|
@ -170,7 +171,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
|||
[IterationSetup]
|
||||
public void Setup()
|
||||
{
|
||||
var memoryPool = new MemoryPool();
|
||||
var memoryPool = KestrelMemoryPool.Create();
|
||||
var pair = DuplexPipe.CreateConnectionPair(memoryPool);
|
||||
|
||||
var serviceContext = new ServiceContext
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ using Microsoft.AspNetCore.Server.Kestrel.Core;
|
|||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Performance.Mocks;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
|
||||
using Microsoft.AspNetCore.Testing;
|
||||
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
||||
|
|
@ -23,6 +24,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
|||
|
||||
private TestHttp1Connection _http1Connection;
|
||||
|
||||
private MemoryPool<byte> _memoryPool;
|
||||
|
||||
[Params(
|
||||
BenchmarkTypes.TechEmpowerPlaintext,
|
||||
BenchmarkTypes.PlaintextChunked,
|
||||
|
|
@ -110,8 +113,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
|||
[IterationSetup]
|
||||
public void Setup()
|
||||
{
|
||||
var memoryPool = new MemoryPool();
|
||||
var pair = DuplexPipe.CreateConnectionPair(memoryPool);
|
||||
_memoryPool = KestrelMemoryPool.Create();
|
||||
var pair = DuplexPipe.CreateConnectionPair(_memoryPool);
|
||||
|
||||
var serviceContext = new ServiceContext
|
||||
{
|
||||
|
|
@ -125,7 +128,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
|||
{
|
||||
ServiceContext = serviceContext,
|
||||
ConnectionFeatures = new FeatureCollection(),
|
||||
MemoryPool = memoryPool,
|
||||
MemoryPool = _memoryPool,
|
||||
TimeoutControl = new MockTimeoutControl(),
|
||||
Application = pair.Application,
|
||||
Transport = pair.Transport
|
||||
|
|
@ -136,6 +139,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
|||
_http1Connection = http1Connection;
|
||||
}
|
||||
|
||||
[IterationCleanup]
|
||||
public void Cleanup()
|
||||
{
|
||||
_memoryPool.Dispose();
|
||||
}
|
||||
|
||||
public enum BenchmarkTypes
|
||||
{
|
||||
TechEmpowerPlaintext,
|
||||
|
|
|
|||
|
|
@ -5,40 +5,39 @@
|
|||
<!-- This files is typically managed by automation. Execute 'run.ps1 upgrade deps' to update these variables to the last-known-good versions. -->
|
||||
<PropertyGroup Label="Package Versions">
|
||||
<BenchmarkDotNetPackageVersion>0.10.11</BenchmarkDotNetPackageVersion>
|
||||
<InternalAspNetCoreSdkPackageVersion>2.1.0-preview2-15721</InternalAspNetCoreSdkPackageVersion>
|
||||
<InternalAspNetCoreSdkPackageVersion>2.1.0-preview2-15707</InternalAspNetCoreSdkPackageVersion>
|
||||
<LibuvPackageVersion>1.10.0</LibuvPackageVersion>
|
||||
<MicrosoftAspNetCoreBenchmarkRunnerSourcesPackageVersion>2.1.0-preview2-30187</MicrosoftAspNetCoreBenchmarkRunnerSourcesPackageVersion>
|
||||
<MicrosoftAspNetCoreCertificatesGenerationSourcesPackageVersion>2.1.0-preview2-30187</MicrosoftAspNetCoreCertificatesGenerationSourcesPackageVersion>
|
||||
<MicrosoftAspNetCoreHostingAbstractionsPackageVersion>2.1.0-preview2-30187</MicrosoftAspNetCoreHostingAbstractionsPackageVersion>
|
||||
<MicrosoftAspNetCoreHostingPackageVersion>2.1.0-preview2-30187</MicrosoftAspNetCoreHostingPackageVersion>
|
||||
<MicrosoftAspNetCoreHttpAbstractionsPackageVersion>2.1.0-preview2-30187</MicrosoftAspNetCoreHttpAbstractionsPackageVersion>
|
||||
<MicrosoftAspNetCoreHttpFeaturesPackageVersion>2.1.0-preview2-30187</MicrosoftAspNetCoreHttpFeaturesPackageVersion>
|
||||
<MicrosoftAspNetCoreHttpPackageVersion>2.1.0-preview2-30187</MicrosoftAspNetCoreHttpPackageVersion>
|
||||
<MicrosoftAspNetCoreTestingPackageVersion>2.1.0-preview2-30187</MicrosoftAspNetCoreTestingPackageVersion>
|
||||
<MicrosoftAspNetCoreWebUtilitiesPackageVersion>2.1.0-preview2-30187</MicrosoftAspNetCoreWebUtilitiesPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationBinderPackageVersion>2.1.0-preview2-30187</MicrosoftExtensionsConfigurationBinderPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationJsonPackageVersion>2.1.0-preview2-30187</MicrosoftExtensionsConfigurationJsonPackageVersion>
|
||||
<MicrosoftExtensionsDependencyInjectionPackageVersion>2.1.0-preview2-30187</MicrosoftExtensionsDependencyInjectionPackageVersion>
|
||||
<MicrosoftExtensionsLoggingAbstractionsPackageVersion>2.1.0-preview2-30187</MicrosoftExtensionsLoggingAbstractionsPackageVersion>
|
||||
<MicrosoftExtensionsLoggingConsolePackageVersion>2.1.0-preview2-30187</MicrosoftExtensionsLoggingConsolePackageVersion>
|
||||
<MicrosoftExtensionsLoggingPackageVersion>2.1.0-preview2-30187</MicrosoftExtensionsLoggingPackageVersion>
|
||||
<MicrosoftExtensionsLoggingTestingPackageVersion>2.1.0-preview2-30187</MicrosoftExtensionsLoggingTestingPackageVersion>
|
||||
<MicrosoftExtensionsOptionsPackageVersion>2.1.0-preview2-30187</MicrosoftExtensionsOptionsPackageVersion>
|
||||
<MicrosoftAspNetCoreBenchmarkRunnerSourcesPackageVersion>2.1.0-preview2-30131</MicrosoftAspNetCoreBenchmarkRunnerSourcesPackageVersion>
|
||||
<MicrosoftAspNetCoreCertificatesGenerationSourcesPackageVersion>2.1.0-preview2-30131</MicrosoftAspNetCoreCertificatesGenerationSourcesPackageVersion>
|
||||
<MicrosoftAspNetCoreHostingAbstractionsPackageVersion>2.1.0-preview2-30131</MicrosoftAspNetCoreHostingAbstractionsPackageVersion>
|
||||
<MicrosoftAspNetCoreHostingPackageVersion>2.1.0-preview2-30131</MicrosoftAspNetCoreHostingPackageVersion>
|
||||
<MicrosoftAspNetCoreHttpAbstractionsPackageVersion>2.1.0-preview2-30131</MicrosoftAspNetCoreHttpAbstractionsPackageVersion>
|
||||
<MicrosoftAspNetCoreHttpFeaturesPackageVersion>2.1.0-preview2-30131</MicrosoftAspNetCoreHttpFeaturesPackageVersion>
|
||||
<MicrosoftAspNetCoreHttpPackageVersion>2.1.0-preview2-30131</MicrosoftAspNetCoreHttpPackageVersion>
|
||||
<MicrosoftAspNetCoreTestingPackageVersion>2.1.0-preview2-30131</MicrosoftAspNetCoreTestingPackageVersion>
|
||||
<MicrosoftAspNetCoreWebUtilitiesPackageVersion>2.1.0-preview2-30131</MicrosoftAspNetCoreWebUtilitiesPackageVersion>
|
||||
<MicrosoftExtensionsBuffersSourcesPackageVersion>2.1.0-preview2-t000</MicrosoftExtensionsBuffersSourcesPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationBinderPackageVersion>2.1.0-preview2-30131</MicrosoftExtensionsConfigurationBinderPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationJsonPackageVersion>2.1.0-preview2-30131</MicrosoftExtensionsConfigurationJsonPackageVersion>
|
||||
<MicrosoftExtensionsDependencyInjectionPackageVersion>2.1.0-preview2-30131</MicrosoftExtensionsDependencyInjectionPackageVersion>
|
||||
<MicrosoftExtensionsLoggingAbstractionsPackageVersion>2.1.0-preview2-30131</MicrosoftExtensionsLoggingAbstractionsPackageVersion>
|
||||
<MicrosoftExtensionsLoggingConsolePackageVersion>2.1.0-preview2-30131</MicrosoftExtensionsLoggingConsolePackageVersion>
|
||||
<MicrosoftExtensionsLoggingPackageVersion>2.1.0-preview2-30131</MicrosoftExtensionsLoggingPackageVersion>
|
||||
<MicrosoftExtensionsLoggingTestingPackageVersion>2.1.0-preview2-30131</MicrosoftExtensionsLoggingTestingPackageVersion>
|
||||
<MicrosoftExtensionsOptionsPackageVersion>2.1.0-preview2-30131</MicrosoftExtensionsOptionsPackageVersion>
|
||||
<MicrosoftNETCoreApp20PackageVersion>2.0.0</MicrosoftNETCoreApp20PackageVersion>
|
||||
<MicrosoftNETCoreApp21PackageVersion>2.1.0-preview2-26130-04</MicrosoftNETCoreApp21PackageVersion>
|
||||
<MicrosoftNetHttpHeadersPackageVersion>2.1.0-preview2-30187</MicrosoftNetHttpHeadersPackageVersion>
|
||||
<MicrosoftNETTestSdkPackageVersion>15.6.0</MicrosoftNETTestSdkPackageVersion>
|
||||
<MicrosoftNETCoreApp21PackageVersion>2.1.0-preview2-26225-03</MicrosoftNETCoreApp21PackageVersion>
|
||||
<MicrosoftNetHttpHeadersPackageVersion>2.1.0-preview2-30131</MicrosoftNetHttpHeadersPackageVersion>
|
||||
<MicrosoftNETTestSdkPackageVersion>15.3.0</MicrosoftNETTestSdkPackageVersion>
|
||||
<MoqPackageVersion>4.7.49</MoqPackageVersion>
|
||||
<NewtonsoftJsonPackageVersion>10.0.1</NewtonsoftJsonPackageVersion>
|
||||
<SystemBuffersPackageVersion>4.5.0-preview2-26130-01</SystemBuffersPackageVersion>
|
||||
<SystemBuffersPrimitivesPackageVersion>0.1.0-preview2-180130-1</SystemBuffersPrimitivesPackageVersion>
|
||||
<SystemIOPipelinesPackageVersion>0.1.0-preview2-180130-1</SystemIOPipelinesPackageVersion>
|
||||
<SystemMemoryPackageVersion>4.5.0-preview2-26130-01</SystemMemoryPackageVersion>
|
||||
<SystemNumericsVectorsPackageVersion>4.5.0-preview2-26130-01</SystemNumericsVectorsPackageVersion>
|
||||
<SystemRuntimeCompilerServicesUnsafePackageVersion>4.5.0-preview2-26130-01</SystemRuntimeCompilerServicesUnsafePackageVersion>
|
||||
<SystemSecurityCryptographyCngPackageVersion>4.5.0-preview2-26130-01</SystemSecurityCryptographyCngPackageVersion>
|
||||
<SystemTextEncodingsWebUtf8PackageVersion>0.1.0-preview2-180130-1</SystemTextEncodingsWebUtf8PackageVersion>
|
||||
<SystemThreadingTasksExtensionsPackageVersion>4.5.0-preview2-26130-01</SystemThreadingTasksExtensionsPackageVersion>
|
||||
<SystemBuffersPackageVersion>4.5.0-preview2-26224-02</SystemBuffersPackageVersion>
|
||||
<SystemIOPipelinesPackageVersion>4.5.0-preview2-26224-02</SystemIOPipelinesPackageVersion>
|
||||
<SystemMemoryPackageVersion>4.5.0-preview2-26224-02</SystemMemoryPackageVersion>
|
||||
<SystemNumericsVectorsPackageVersion>4.5.0-preview2-26224-02</SystemNumericsVectorsPackageVersion>
|
||||
<SystemRuntimeCompilerServicesUnsafePackageVersion>4.5.0-preview2-26224-02</SystemRuntimeCompilerServicesUnsafePackageVersion>
|
||||
<SystemSecurityCryptographyCngPackageVersion>4.5.0-preview2-26224-02</SystemSecurityCryptographyCngPackageVersion>
|
||||
<SystemThreadingTasksExtensionsPackageVersion>4.5.0-preview2-26224-02</SystemThreadingTasksExtensionsPackageVersion>
|
||||
<XunitAnalyzersPackageVersion>0.8.0</XunitAnalyzersPackageVersion>
|
||||
<XunitPackageVersion>2.3.1</XunitPackageVersion>
|
||||
<XunitRunnerVisualStudioPackageVersion>2.4.0-beta.1.build3945</XunitRunnerVisualStudioPackageVersion>
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Adapter.Internal
|
|||
|
||||
try
|
||||
{
|
||||
if (result.IsCancelled)
|
||||
if (result.IsCanceled)
|
||||
{
|
||||
// Forward the cancellation to the transport pipe
|
||||
_application.Input.CancelPendingRead();
|
||||
|
|
@ -132,26 +132,18 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Adapter.Internal
|
|||
{
|
||||
|
||||
var outputBuffer = Input.Writer.GetMemory(MinAllocBufferSize);
|
||||
|
||||
try
|
||||
{
|
||||
#if NETCOREAPP2_1
|
||||
var bytesRead = await stream.ReadAsync(outputBuffer);
|
||||
var bytesRead = await stream.ReadAsync(outputBuffer);
|
||||
#else
|
||||
var array = outputBuffer.GetArray();
|
||||
var bytesRead = await stream.ReadAsync(array.Array, array.Offset, array.Count);
|
||||
var array = outputBuffer.GetArray();
|
||||
var bytesRead = await stream.ReadAsync(array.Array, array.Offset, array.Count);
|
||||
#endif
|
||||
Input.Writer.Advance(bytesRead);
|
||||
Input.Writer.Advance(bytesRead);
|
||||
|
||||
if (bytesRead == 0)
|
||||
{
|
||||
// FIN
|
||||
break;
|
||||
}
|
||||
}
|
||||
finally
|
||||
if (bytesRead == 0)
|
||||
{
|
||||
Input.Writer.Commit();
|
||||
// FIN
|
||||
break;
|
||||
}
|
||||
|
||||
var result = await Input.Writer.FlushAsync();
|
||||
|
|
@ -160,7 +152,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Adapter.Internal
|
|||
{
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
|
|||
}
|
||||
|
||||
// Internal for testing
|
||||
internal static PipeOptions GetInputPipeOptions(ServiceContext serviceContext, MemoryPool memoryPool, PipeScheduler writerScheduler) => new PipeOptions
|
||||
internal static PipeOptions GetInputPipeOptions(ServiceContext serviceContext, MemoryPool<byte> memoryPool, PipeScheduler writerScheduler) => new PipeOptions
|
||||
(
|
||||
pool: memoryPool,
|
||||
readerScheduler: serviceContext.ThreadPool,
|
||||
|
|
@ -92,7 +92,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
|
|||
resumeWriterThreshold: serviceContext.ServerOptions.Limits.MaxRequestBufferSize ?? 0
|
||||
);
|
||||
|
||||
internal static PipeOptions GetOutputPipeOptions(ServiceContext serviceContext, MemoryPool memoryPool, PipeScheduler readerScheduler) => new PipeOptions
|
||||
internal static PipeOptions GetOutputPipeOptions(ServiceContext serviceContext, MemoryPool<byte> memoryPool, PipeScheduler readerScheduler) => new PipeOptions
|
||||
(
|
||||
pool: memoryPool,
|
||||
readerScheduler: readerScheduler,
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ using System.Text;
|
|||
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
||||
{
|
||||
public static class ChunkWriter
|
||||
internal static class ChunkWriter
|
||||
{
|
||||
private static readonly ArraySegment<byte> _endChunkBytes = CreateAsciiByteArraySegment("\r\n");
|
||||
private static readonly byte[] _hex = Encoding.ASCII.GetBytes("0123456789abcdef");
|
||||
|
|
@ -48,14 +48,14 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
return new ArraySegment<byte>(bytes, offset, 10 - offset);
|
||||
}
|
||||
|
||||
public static int WriteBeginChunkBytes(ref OutputWriter<PipeWriter> start, int dataCount)
|
||||
internal static int WriteBeginChunkBytes(ref BufferWriter<PipeWriter> start, int dataCount)
|
||||
{
|
||||
var chunkSegment = BeginChunkBytes(dataCount);
|
||||
start.Write(new ReadOnlySpan<byte>(chunkSegment.Array, chunkSegment.Offset, chunkSegment.Count));
|
||||
return chunkSegment.Count;
|
||||
}
|
||||
|
||||
public static void WriteEndChunkBytes(ref OutputWriter<PipeWriter> start)
|
||||
internal static void WriteEndChunkBytes(ref BufferWriter<PipeWriter> start)
|
||||
{
|
||||
start.Write(new ReadOnlySpan<byte>(_endChunkBytes.Array, _endChunkBytes.Offset, _endChunkBytes.Count));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,9 +8,10 @@ using System.Diagnostics;
|
|||
using System.IO.Pipelines;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Text.Encodings.Web.Utf8;
|
||||
using System.Text.Encodings.Web;
|
||||
using System.Threading;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
using Microsoft.AspNetCore.Protocols.Abstractions;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
|
||||
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
||||
|
|
@ -69,7 +70,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
Input.CancelPendingRead();
|
||||
}
|
||||
|
||||
public void ParseRequest(ReadOnlyBuffer<byte> buffer, out SequencePosition consumed, out SequencePosition examined)
|
||||
public void ParseRequest(ReadOnlySequence<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<byte> buffer, out SequencePosition consumed, out SequencePosition examined)
|
||||
public bool TakeStartLine(ReadOnlySequence<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<byte> buffer, out SequencePosition consumed, out SequencePosition examined)
|
||||
public bool TakeMessageHeaders(ReadOnlySequence<byte> buffer, out SequencePosition consumed, out SequencePosition examined)
|
||||
{
|
||||
// Make sure the buffer is limited
|
||||
bool overLength = false;
|
||||
|
|
@ -217,9 +218,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
{
|
||||
// URI was encoded, unescape and then parse as UTF-8
|
||||
// Disabling warning temporary
|
||||
#pragma warning disable 618
|
||||
var pathLength = UrlEncoder.Decode(path, path);
|
||||
#pragma warning restore 618
|
||||
var pathLength = UrlDecoder.Decode(path, path);
|
||||
|
||||
// Removing dot segments must be done after unescaping. From RFC 3986:
|
||||
//
|
||||
|
|
@ -430,7 +429,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
TimeoutControl.SetTimeout(_keepAliveTicks, TimeoutAction.StopProcessingNextRequest);
|
||||
}
|
||||
|
||||
protected override bool BeginRead(out ValueAwaiter<ReadResult> awaitable)
|
||||
protected override bool BeginRead(out PipeAwaiter<ReadResult> awaitable)
|
||||
{
|
||||
awaitable = Input.ReadAsync();
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
public string ConnectionId { get; set; }
|
||||
public ServiceContext ServiceContext { get; set; }
|
||||
public IFeatureCollection ConnectionFeatures { get; set; }
|
||||
public MemoryPool MemoryPool { get; set; }
|
||||
public MemoryPool<byte> MemoryPool { get; set; }
|
||||
public IPEndPoint RemoteEndPoint { get; set; }
|
||||
public IPEndPoint LocalEndPoint { get; set; }
|
||||
public ITimeoutControl TimeoutControl { get; set; }
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ using System.IO;
|
|||
using System.IO.Pipelines;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Protocols.Abstractions;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
|
||||
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
||||
|
|
@ -63,15 +64,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
if (!readableBuffer.IsEmpty)
|
||||
{
|
||||
bool done;
|
||||
|
||||
try
|
||||
{
|
||||
done = Read(readableBuffer, _context.RequestBodyPipe.Writer, out consumed, out examined);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_context.RequestBodyPipe.Writer.Commit();
|
||||
}
|
||||
done = Read(readableBuffer, _context.RequestBodyPipe.Writer, out consumed, out examined);
|
||||
|
||||
var writeAwaitable = _context.RequestBodyPipe.Writer.FlushAsync();
|
||||
var backpressure = false;
|
||||
|
|
@ -150,7 +143,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
}
|
||||
}
|
||||
|
||||
protected void Copy(ReadOnlyBuffer<byte> readableBuffer, PipeWriter writableBuffer)
|
||||
protected void Copy(ReadOnlySequence<byte> readableBuffer, PipeWriter writableBuffer)
|
||||
{
|
||||
_context.TimeoutControl.BytesRead(readableBuffer.Length);
|
||||
|
||||
|
|
@ -172,7 +165,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
_pumpTask = PumpAsync();
|
||||
}
|
||||
|
||||
protected virtual bool Read(ReadOnlyBuffer<byte> readableBuffer, PipeWriter writableBuffer, out SequencePosition consumed, out SequencePosition examined)
|
||||
protected virtual bool Read(ReadOnlySequence<byte> readableBuffer, PipeWriter writableBuffer, out SequencePosition consumed, out SequencePosition examined)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
|
@ -295,7 +288,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
|
||||
public override bool IsEmpty => true;
|
||||
|
||||
protected override bool Read(ReadOnlyBuffer<byte> readableBuffer, PipeWriter writableBuffer, out SequencePosition consumed, out SequencePosition examined)
|
||||
protected override bool Read(ReadOnlySequence<byte> readableBuffer, PipeWriter writableBuffer, out SequencePosition consumed, out SequencePosition examined)
|
||||
{
|
||||
Copy(readableBuffer, writableBuffer);
|
||||
consumed = readableBuffer.End;
|
||||
|
|
@ -317,7 +310,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
_inputLength = _contentLength;
|
||||
}
|
||||
|
||||
protected override bool Read(ReadOnlyBuffer<byte> readableBuffer, PipeWriter writableBuffer, out SequencePosition consumed, out SequencePosition examined)
|
||||
protected override bool Read(ReadOnlySequence<byte> readableBuffer, PipeWriter writableBuffer, out SequencePosition consumed, out SequencePosition examined)
|
||||
{
|
||||
if (_inputLength == 0)
|
||||
{
|
||||
|
|
@ -365,7 +358,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
RequestKeepAlive = keepAlive;
|
||||
}
|
||||
|
||||
protected override bool Read(ReadOnlyBuffer<byte> readableBuffer, PipeWriter writableBuffer, out SequencePosition consumed, out SequencePosition examined)
|
||||
protected override bool Read(ReadOnlySequence<byte> readableBuffer, PipeWriter writableBuffer, out SequencePosition consumed, out SequencePosition examined)
|
||||
{
|
||||
consumed = default(SequencePosition);
|
||||
examined = default(SequencePosition);
|
||||
|
|
@ -456,11 +449,11 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
}
|
||||
}
|
||||
|
||||
private void ParseChunkedPrefix(ReadOnlyBuffer<byte> buffer, out SequencePosition consumed, out SequencePosition examined)
|
||||
private void ParseChunkedPrefix(ReadOnlySequence<byte> buffer, out SequencePosition consumed, out SequencePosition examined)
|
||||
{
|
||||
consumed = buffer.Start;
|
||||
examined = buffer.Start;
|
||||
var reader = BufferReader.Create(buffer);
|
||||
var reader = new BufferReader(buffer);
|
||||
var ch1 = reader.Read();
|
||||
var ch2 = reader.Read();
|
||||
|
||||
|
|
@ -512,7 +505,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
BadHttpRequestException.Throw(RequestRejectionReason.BadChunkSizeData);
|
||||
}
|
||||
|
||||
private void ParseExtension(ReadOnlyBuffer<byte> buffer, out SequencePosition consumed, out SequencePosition examined)
|
||||
private void ParseExtension(ReadOnlySequence<byte> buffer, out SequencePosition consumed, out SequencePosition examined)
|
||||
{
|
||||
// Chunk-extensions not currently parsed
|
||||
// Just drain the data
|
||||
|
|
@ -565,7 +558,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
} while (_mode == Mode.Extension);
|
||||
}
|
||||
|
||||
private void ReadChunkedData(ReadOnlyBuffer<byte> buffer, PipeWriter writableBuffer, out SequencePosition consumed, out SequencePosition examined)
|
||||
private void ReadChunkedData(ReadOnlySequence<byte> buffer, PipeWriter writableBuffer, out SequencePosition consumed, out SequencePosition examined)
|
||||
{
|
||||
var actual = Math.Min(buffer.Length, _inputLength);
|
||||
consumed = buffer.GetPosition(buffer.Start, actual);
|
||||
|
|
@ -582,7 +575,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
}
|
||||
}
|
||||
|
||||
private void ParseChunkedSuffix(ReadOnlyBuffer<byte> buffer, out SequencePosition consumed, out SequencePosition examined)
|
||||
private void ParseChunkedSuffix(ReadOnlySequence<byte> buffer, out SequencePosition consumed, out SequencePosition examined)
|
||||
{
|
||||
consumed = buffer.Start;
|
||||
examined = buffer.Start;
|
||||
|
|
@ -608,7 +601,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
}
|
||||
}
|
||||
|
||||
private void ParseChunkedTrailer(ReadOnlyBuffer<byte> buffer, out SequencePosition consumed, out SequencePosition examined)
|
||||
private void ParseChunkedTrailer(ReadOnlySequence<byte> buffer, out SequencePosition consumed, out SequencePosition examined)
|
||||
{
|
||||
consumed = buffer.Start;
|
||||
examined = buffer.Start;
|
||||
|
|
|
|||
|
|
@ -84,7 +84,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
|
||||
var buffer = _pipeWriter;
|
||||
callback(buffer, state);
|
||||
buffer.Commit();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -99,7 +98,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
|
||||
var buffer = _pipeWriter;
|
||||
callback(buffer, state);
|
||||
buffer.Commit();
|
||||
}
|
||||
|
||||
return FlushAsync();
|
||||
|
|
@ -115,14 +113,14 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
}
|
||||
|
||||
var buffer = _pipeWriter;
|
||||
var writer = OutputWriter.Create(buffer);
|
||||
var writer = new BufferWriter<PipeWriter>(buffer);
|
||||
|
||||
writer.Write(_bytesHttpVersion11);
|
||||
var statusBytes = ReasonPhrases.ToStatusBytes(statusCode, reasonPhrase);
|
||||
writer.Write(statusBytes);
|
||||
responseHeaders.CopyTo(ref writer);
|
||||
writer.Write(_bytesEndHeaders);
|
||||
buffer.Commit();
|
||||
writer.Commit();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -177,14 +175,13 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
}
|
||||
|
||||
writableBuffer = _pipeWriter;
|
||||
var writer = OutputWriter.Create(writableBuffer);
|
||||
var writer = new BufferWriter<PipeWriter>(writableBuffer);
|
||||
if (buffer.Length > 0)
|
||||
{
|
||||
writer.Write(buffer);
|
||||
bytesWritten += buffer.Length;
|
||||
}
|
||||
|
||||
writableBuffer.Commit();
|
||||
writer.Commit();
|
||||
}
|
||||
|
||||
return FlushAsync(writableBuffer, bytesWritten, cancellationToken);
|
||||
|
|
@ -203,7 +200,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
return FlushAsyncAwaited(awaitable, bytesWritten, cancellationToken);
|
||||
}
|
||||
|
||||
private async Task FlushAsyncAwaited(ValueAwaiter<FlushResult> awaitable, long count, CancellationToken cancellationToken)
|
||||
private async Task FlushAsyncAwaited(PipeAwaiter<FlushResult> awaitable, long count, CancellationToken cancellationToken)
|
||||
{
|
||||
// https://github.com/dotnet/corefxlab/issues/1334
|
||||
// Since the flush awaitable doesn't currently support multiple awaiters
|
||||
|
|
|
|||
|
|
@ -7754,7 +7754,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
return true;
|
||||
}
|
||||
|
||||
protected void CopyToFast(ref OutputWriter<PipeWriter> output)
|
||||
internal void CopyToFast(ref BufferWriter<PipeWriter> output)
|
||||
{
|
||||
var tempBits = _bits | (_contentLength.HasValue ? -9223372036854775808L : 0);
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ using System.Collections;
|
|||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using Microsoft.AspNetCore.Protocols.Abstractions;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
|
||||
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
||||
|
|
@ -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<byte> buffer, out SequencePosition consumed, out SequencePosition examined)
|
||||
public unsafe bool ParseRequestLine(TRequestHandler handler, ReadOnlySequence<byte> buffer, out SequencePosition consumed, out SequencePosition examined)
|
||||
{
|
||||
consumed = buffer.Start;
|
||||
examined = buffer.End;
|
||||
|
|
@ -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<byte> buffer, out SequencePosition consumed, out SequencePosition examined, out int consumedBytes)
|
||||
public unsafe bool ParseHeaders(TRequestHandler handler, ReadOnlySequence<byte> buffer, out SequencePosition consumed, out SequencePosition examined, out int consumedBytes)
|
||||
{
|
||||
consumed = buffer.Start;
|
||||
examined = buffer.End;
|
||||
|
|
@ -196,8 +197,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
|
||||
var bufferEnd = buffer.End;
|
||||
|
||||
var reader = BufferReader.Create(buffer);
|
||||
var start = default(BufferReader<ReadOnlyBuffer<byte>>);
|
||||
var reader = new BufferReader(buffer);
|
||||
var start = default(BufferReader);
|
||||
var done = false;
|
||||
|
||||
try
|
||||
|
|
@ -418,7 +419,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
private static bool TryGetNewLine(ref ReadOnlyBuffer<byte> buffer, out SequencePosition found)
|
||||
private static bool TryGetNewLine(ref ReadOnlySequence<byte> buffer, out SequencePosition found)
|
||||
{
|
||||
var byteLfPosition = buffer.PositionOf(ByteLF);
|
||||
if (byteLfPosition != null)
|
||||
|
|
|
|||
|
|
@ -383,7 +383,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
{
|
||||
}
|
||||
|
||||
protected virtual bool BeginRead(out ValueAwaiter<ReadResult> awaitable)
|
||||
protected virtual bool BeginRead(out PipeAwaiter<ReadResult> awaitable)
|
||||
{
|
||||
awaitable = default;
|
||||
return false;
|
||||
|
|
@ -930,12 +930,13 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
|
||||
private static void WriteChunk(PipeWriter writableBuffer, ReadOnlyMemory<byte> buffer)
|
||||
{
|
||||
var writer = OutputWriter.Create(writableBuffer);
|
||||
var writer = new BufferWriter<PipeWriter>(writableBuffer);
|
||||
if (buffer.Length > 0)
|
||||
{
|
||||
ChunkWriter.WriteBeginChunkBytes(ref writer, buffer.Length);
|
||||
writer.Write(buffer.Span);
|
||||
ChunkWriter.WriteEndChunkBytes(ref writer);
|
||||
writer.Commit();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -35,9 +35,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
return GetEnumerator();
|
||||
}
|
||||
|
||||
public void CopyTo(ref OutputWriter<PipeWriter> output)
|
||||
internal void CopyTo(ref BufferWriter<PipeWriter> buffer)
|
||||
{
|
||||
CopyToFast(ref output);
|
||||
CopyToFast(ref buffer);
|
||||
if (MaybeUnknown != null)
|
||||
{
|
||||
foreach (var kv in MaybeUnknown)
|
||||
|
|
@ -46,10 +46,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
{
|
||||
if (value != null)
|
||||
{
|
||||
output.Write(_CrLf);
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, kv.Key);
|
||||
output.Write(_colonSpace);
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
buffer.Write(_CrLf);
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref buffer, kv.Key);
|
||||
buffer.Write(_colonSpace);
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref buffer, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Collections;
|
||||
|
||||
|
|
@ -8,8 +9,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
{
|
||||
public interface IHttpParser<TRequestHandler> where TRequestHandler : IHttpHeadersHandler, IHttpRequestLineHandler
|
||||
{
|
||||
bool ParseRequestLine(TRequestHandler handler, ReadOnlyBuffer<byte> buffer, out SequencePosition consumed, out SequencePosition examined);
|
||||
bool ParseRequestLine(TRequestHandler handler, ReadOnlySequence<byte> buffer, out SequencePosition consumed, out SequencePosition examined);
|
||||
|
||||
bool ParseHeaders(TRequestHandler handler, ReadOnlyBuffer<byte> buffer, out SequencePosition consumed, out SequencePosition examined, out int consumedBytes);
|
||||
bool ParseHeaders(TRequestHandler handler, ReadOnlySequence<byte> buffer, out SequencePosition consumed, out SequencePosition examined, out int consumedBytes);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
string ConnectionId { get; set; }
|
||||
ServiceContext ServiceContext { get; set; }
|
||||
IFeatureCollection ConnectionFeatures { get; set; }
|
||||
MemoryPool MemoryPool { get; set; }
|
||||
MemoryPool<byte> MemoryPool { get; set; }
|
||||
IPEndPoint RemoteEndPoint { get; set; }
|
||||
IPEndPoint LocalEndPoint { 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;
|
||||
using System.Buffers;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
private static byte[] _numericBytesScratch;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static ReadOnlySpan<byte> ToSpan(this ReadOnlyBuffer<byte> buffer)
|
||||
public static ReadOnlySpan<byte> ToSpan(this ReadOnlySequence<byte> buffer)
|
||||
{
|
||||
if (buffer.IsSingleSegment)
|
||||
{
|
||||
|
|
@ -45,7 +45,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
return result;
|
||||
}
|
||||
|
||||
public unsafe static void WriteAsciiNoValidation(ref this OutputWriter<PipeWriter> buffer, string data)
|
||||
internal static unsafe void WriteAsciiNoValidation(ref this BufferWriter<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 OutputWriter<PipeWriter> buffer, ulong number)
|
||||
internal static unsafe void WriteNumeric(ref this BufferWriter<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 OutputWriter<PipeWriter> buffer, ulong number)
|
||||
private static void WriteNumericMultiWrite(ref this BufferWriter<PipeWriter> buffer, ulong number)
|
||||
{
|
||||
const byte AsciiDigitStart = (byte)'0';
|
||||
|
||||
|
|
@ -145,7 +145,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
private unsafe static void WriteAsciiMultiWrite(ref this OutputWriter<PipeWriter> buffer, string data)
|
||||
private unsafe static void WriteAsciiMultiWrite(ref this BufferWriter<PipeWriter> buffer, string data)
|
||||
{
|
||||
var remaining = data.Length;
|
||||
|
||||
|
|
@ -176,7 +176,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
}
|
||||
}
|
||||
|
||||
private unsafe static void EncodeAsciiCharsToBytes(char* input, byte* output, int length)
|
||||
private static unsafe void EncodeAsciiCharsToBytes(char* input, byte* output, int length)
|
||||
{
|
||||
// Note: Not BIGENDIAN or check for non-ascii
|
||||
const int Shift16Shift24 = (1 << 16) | (1 << 24);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,411 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Microsoft.AspNetCore.Protocols.Abstractions
|
||||
{
|
||||
internal class UrlDecoder
|
||||
{
|
||||
static bool[] IsAllowed = new bool[0x7F + 1];
|
||||
|
||||
/// <summary>
|
||||
/// Unescape a URL path
|
||||
/// </summary>
|
||||
/// <param name="source">The byte span represents a UTF8 encoding url path.</param>
|
||||
/// <param name="destination">The byte span where unescaped url path is copied to.</param>
|
||||
/// <returns>The length of the byte sequence of the unescaped url path.</returns>
|
||||
public static int Decode(ReadOnlySpan<byte> source, Span<byte> destination)
|
||||
{
|
||||
if (destination.Length < source.Length)
|
||||
{
|
||||
throw new ArgumentException(
|
||||
"Lenghth of the destination byte span is less then the source.",
|
||||
nameof(destination));
|
||||
}
|
||||
|
||||
// This requires the destination span to be larger or equal to source span
|
||||
source.CopyTo(destination);
|
||||
return DecodeInPlace(destination);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unescape a URL path in place.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The byte span represents a UTF8 encoding url path.</param>
|
||||
/// <returns>The number of the bytes representing the result.</returns>
|
||||
/// <remarks>
|
||||
/// The unescape is done in place, which means after decoding the result is the subset of
|
||||
/// the input span.
|
||||
/// </remarks>
|
||||
public static int DecodeInPlace(Span<byte> buffer)
|
||||
{
|
||||
// the slot to read the input
|
||||
var sourceIndex = 0;
|
||||
|
||||
// the slot to write the unescaped byte
|
||||
var destinationIndex = 0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (sourceIndex == buffer.Length)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (buffer[sourceIndex] == '%')
|
||||
{
|
||||
var decodeIndex = sourceIndex;
|
||||
|
||||
// If decoding process succeeds, the writer iterator will be moved
|
||||
// to the next write-ready location. On the other hand if the scanned
|
||||
// percent-encodings cannot be interpreted as sequence of UTF-8 octets,
|
||||
// these bytes should be copied to output as is.
|
||||
// The decodeReader iterator is always moved to the first byte not yet
|
||||
// be scanned after the process. A failed decoding means the chars
|
||||
// between the reader and decodeReader can be copied to output untouched.
|
||||
if (!DecodeCore(ref decodeIndex, ref destinationIndex, buffer))
|
||||
{
|
||||
Copy(sourceIndex, decodeIndex, ref destinationIndex, buffer);
|
||||
}
|
||||
|
||||
sourceIndex = decodeIndex;
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer[destinationIndex++] = buffer[sourceIndex++];
|
||||
}
|
||||
}
|
||||
|
||||
return destinationIndex;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unescape the percent-encodings
|
||||
/// </summary>
|
||||
/// <param name="sourceIndex">The iterator point to the first % char</param>
|
||||
/// <param name="destinationIndex">The place to write to</param>
|
||||
/// <param name="buffer">The byte array</param>
|
||||
private static bool DecodeCore(ref int sourceIndex, ref int destinationIndex, Span<byte> buffer)
|
||||
{
|
||||
// preserves the original head. if the percent-encodings cannot be interpreted as sequence of UTF-8 octets,
|
||||
// bytes from this till the last scanned one will be copied to the memory pointed by writer.
|
||||
var byte1 = UnescapePercentEncoding(ref sourceIndex, buffer);
|
||||
if (byte1 == -1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (byte1 == 0)
|
||||
{
|
||||
throw new InvalidOperationException("The path contains null characters.");
|
||||
}
|
||||
|
||||
if (byte1 <= 0x7F)
|
||||
{
|
||||
// first byte < U+007f, it is a single byte ASCII
|
||||
buffer[destinationIndex++] = (byte)byte1;
|
||||
return true;
|
||||
}
|
||||
|
||||
int byte2 = 0, byte3 = 0, byte4 = 0;
|
||||
|
||||
// anticipate more bytes
|
||||
var currentDecodeBits = 0;
|
||||
var byteCount = 1;
|
||||
var expectValueMin = 0;
|
||||
if ((byte1 & 0xE0) == 0xC0)
|
||||
{
|
||||
// 110x xxxx, expect one more byte
|
||||
currentDecodeBits = byte1 & 0x1F;
|
||||
byteCount = 2;
|
||||
expectValueMin = 0x80;
|
||||
}
|
||||
else if ((byte1 & 0xF0) == 0xE0)
|
||||
{
|
||||
// 1110 xxxx, expect two more bytes
|
||||
currentDecodeBits = byte1 & 0x0F;
|
||||
byteCount = 3;
|
||||
expectValueMin = 0x800;
|
||||
}
|
||||
else if ((byte1 & 0xF8) == 0xF0)
|
||||
{
|
||||
// 1111 0xxx, expect three more bytes
|
||||
currentDecodeBits = byte1 & 0x07;
|
||||
byteCount = 4;
|
||||
expectValueMin = 0x10000;
|
||||
}
|
||||
else
|
||||
{
|
||||
// invalid first byte
|
||||
return false;
|
||||
}
|
||||
|
||||
var remainingBytes = byteCount - 1;
|
||||
while (remainingBytes > 0)
|
||||
{
|
||||
// read following three chars
|
||||
if (sourceIndex == buffer.Length)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var nextSourceIndex = sourceIndex;
|
||||
var nextByte = UnescapePercentEncoding(ref nextSourceIndex, buffer);
|
||||
if (nextByte == -1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((nextByte & 0xC0) != 0x80)
|
||||
{
|
||||
// the follow up byte is not in form of 10xx xxxx
|
||||
return false;
|
||||
}
|
||||
|
||||
currentDecodeBits = (currentDecodeBits << 6) | (nextByte & 0x3F);
|
||||
remainingBytes--;
|
||||
|
||||
if (remainingBytes == 1 && currentDecodeBits >= 0x360 && currentDecodeBits <= 0x37F)
|
||||
{
|
||||
// this is going to end up in the range of 0xD800-0xDFFF UTF-16 surrogates that
|
||||
// are not allowed in UTF-8;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (remainingBytes == 2 && currentDecodeBits >= 0x110)
|
||||
{
|
||||
// this is going to be out of the upper Unicode bound 0x10FFFF.
|
||||
return false;
|
||||
}
|
||||
|
||||
sourceIndex = nextSourceIndex;
|
||||
if (byteCount - remainingBytes == 2)
|
||||
{
|
||||
byte2 = nextByte;
|
||||
}
|
||||
else if (byteCount - remainingBytes == 3)
|
||||
{
|
||||
byte3 = nextByte;
|
||||
}
|
||||
else if (byteCount - remainingBytes == 4)
|
||||
{
|
||||
byte4 = nextByte;
|
||||
}
|
||||
}
|
||||
|
||||
if (currentDecodeBits < expectValueMin)
|
||||
{
|
||||
// overlong encoding (e.g. using 2 bytes to encode something that only needed 1).
|
||||
return false;
|
||||
}
|
||||
|
||||
// all bytes are verified, write to the output
|
||||
// TODO: measure later to determine if the performance of following logic can be improved
|
||||
// the idea is to combine the bytes into short/int and write to span directly to avoid
|
||||
// range check cost
|
||||
if (byteCount > 0)
|
||||
{
|
||||
buffer[destinationIndex++] = (byte)byte1;
|
||||
}
|
||||
if (byteCount > 1)
|
||||
{
|
||||
buffer[destinationIndex++] = (byte)byte2;
|
||||
}
|
||||
if (byteCount > 2)
|
||||
{
|
||||
buffer[destinationIndex++] = (byte)byte3;
|
||||
}
|
||||
if (byteCount > 3)
|
||||
{
|
||||
buffer[destinationIndex++] = (byte)byte4;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void Copy(int begin, int end, ref int writer, Span<byte> buffer)
|
||||
{
|
||||
while (begin != end)
|
||||
{
|
||||
buffer[writer++] = buffer[begin++];
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read the percent-encoding and try unescape it.
|
||||
///
|
||||
/// The operation first peek at the character the <paramref name="scan"/>
|
||||
/// iterator points at. If it is % the <paramref name="scan"/> is then
|
||||
/// moved on to scan the following to characters. If the two following
|
||||
/// characters are hexadecimal literals they will be unescaped and the
|
||||
/// value will be returned.
|
||||
///
|
||||
/// If the first character is not % the <paramref name="scan"/> iterator
|
||||
/// will be removed beyond the location of % and -1 will be returned.
|
||||
///
|
||||
/// If the following two characters can't be successfully unescaped the
|
||||
/// <paramref name="scan"/> iterator will be move behind the % and -1
|
||||
/// will be returned.
|
||||
/// </summary>
|
||||
/// <param name="scan">The value to read</param>
|
||||
/// <param name="buffer">The byte array</param>
|
||||
/// <returns>The unescaped byte if success. Otherwise return -1.</returns>
|
||||
private static int UnescapePercentEncoding(ref int scan, Span<byte> buffer)
|
||||
{
|
||||
if (buffer[scan++] != '%')
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
var probe = scan;
|
||||
|
||||
var value1 = ReadHex(ref probe, buffer);
|
||||
if (value1 == -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
var value2 = ReadHex(ref probe, buffer);
|
||||
if (value2 == -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (SkipUnescape(value1, value2))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
scan = probe;
|
||||
return (value1 << 4) + value2;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Read the next char and convert it into hexadecimal value.
|
||||
///
|
||||
/// The <paramref name="scan"/> index will be moved to the next
|
||||
/// byte no matter no matter whether the operation successes.
|
||||
/// </summary>
|
||||
/// <param name="scan">The index of the byte in the buffer to read</param>
|
||||
/// <param name="buffer">The byte span from which the hex to be read</param>
|
||||
/// <returns>The hexadecimal value if successes, otherwise -1.</returns>
|
||||
private static int ReadHex(ref int scan, Span<byte> buffer)
|
||||
{
|
||||
if (scan == buffer.Length)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
var value = buffer[scan++];
|
||||
var isHead = ((value >= '0') && (value <= '9')) ||
|
||||
((value >= 'A') && (value <= 'F')) ||
|
||||
((value >= 'a') && (value <= 'f'));
|
||||
|
||||
if (!isHead)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (value <= '9')
|
||||
{
|
||||
return value - '0';
|
||||
}
|
||||
else if (value <= 'F')
|
||||
{
|
||||
return (value - 'A') + 10;
|
||||
}
|
||||
else // a - f
|
||||
{
|
||||
return (value - 'a') + 10;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool SkipUnescape(int value1, int value2)
|
||||
{
|
||||
// skip %2F - '/'
|
||||
if (value1 == 2 && value2 == 15)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static UrlDecoder()
|
||||
{
|
||||
// Unreserved
|
||||
IsAllowed['A'] = true;
|
||||
IsAllowed['B'] = true;
|
||||
IsAllowed['C'] = true;
|
||||
IsAllowed['D'] = true;
|
||||
IsAllowed['E'] = true;
|
||||
IsAllowed['F'] = true;
|
||||
IsAllowed['G'] = true;
|
||||
IsAllowed['H'] = true;
|
||||
IsAllowed['I'] = true;
|
||||
IsAllowed['J'] = true;
|
||||
IsAllowed['K'] = true;
|
||||
IsAllowed['L'] = true;
|
||||
IsAllowed['M'] = true;
|
||||
IsAllowed['N'] = true;
|
||||
IsAllowed['O'] = true;
|
||||
IsAllowed['P'] = true;
|
||||
IsAllowed['Q'] = true;
|
||||
IsAllowed['R'] = true;
|
||||
IsAllowed['S'] = true;
|
||||
IsAllowed['T'] = true;
|
||||
IsAllowed['U'] = true;
|
||||
IsAllowed['V'] = true;
|
||||
IsAllowed['W'] = true;
|
||||
IsAllowed['X'] = true;
|
||||
IsAllowed['Y'] = true;
|
||||
IsAllowed['Z'] = true;
|
||||
|
||||
IsAllowed['a'] = true;
|
||||
IsAllowed['b'] = true;
|
||||
IsAllowed['c'] = true;
|
||||
IsAllowed['d'] = true;
|
||||
IsAllowed['e'] = true;
|
||||
IsAllowed['f'] = true;
|
||||
IsAllowed['g'] = true;
|
||||
IsAllowed['h'] = true;
|
||||
IsAllowed['i'] = true;
|
||||
IsAllowed['j'] = true;
|
||||
IsAllowed['k'] = true;
|
||||
IsAllowed['l'] = true;
|
||||
IsAllowed['m'] = true;
|
||||
IsAllowed['n'] = true;
|
||||
IsAllowed['o'] = true;
|
||||
IsAllowed['p'] = true;
|
||||
IsAllowed['q'] = true;
|
||||
IsAllowed['r'] = true;
|
||||
IsAllowed['s'] = true;
|
||||
IsAllowed['t'] = true;
|
||||
IsAllowed['u'] = true;
|
||||
IsAllowed['v'] = true;
|
||||
IsAllowed['w'] = true;
|
||||
IsAllowed['x'] = true;
|
||||
IsAllowed['y'] = true;
|
||||
IsAllowed['z'] = true;
|
||||
|
||||
IsAllowed['0'] = true;
|
||||
IsAllowed['1'] = true;
|
||||
IsAllowed['2'] = true;
|
||||
IsAllowed['3'] = true;
|
||||
IsAllowed['4'] = true;
|
||||
IsAllowed['5'] = true;
|
||||
IsAllowed['6'] = true;
|
||||
IsAllowed['7'] = true;
|
||||
IsAllowed['8'] = true;
|
||||
IsAllowed['9'] = true;
|
||||
|
||||
IsAllowed['-'] = true;
|
||||
IsAllowed['_'] = true;
|
||||
IsAllowed['.'] = true;
|
||||
IsAllowed['~'] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -215,7 +215,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
|
|||
}
|
||||
}
|
||||
|
||||
private bool ParsePreface(ReadOnlyBuffer<byte> readableBuffer, out SequencePosition consumed, out SequencePosition examined)
|
||||
private bool ParsePreface(ReadOnlySequence<byte> readableBuffer, out SequencePosition consumed, out SequencePosition examined)
|
||||
{
|
||||
consumed = readableBuffer.Start;
|
||||
examined = readableBuffer.End;
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
|
|||
public string ConnectionId { get; set; }
|
||||
public ServiceContext ServiceContext { get; set; }
|
||||
public IFeatureCollection ConnectionFeatures { get; set; }
|
||||
public MemoryPool MemoryPool { get; set; }
|
||||
public MemoryPool<byte> MemoryPool { get; set; }
|
||||
public IPEndPoint LocalEndPoint { get; set; }
|
||||
public IPEndPoint RemoteEndPoint { get; set; }
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Collections;
|
||||
|
||||
|
|
@ -8,7 +9,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
|
|||
{
|
||||
public static class Http2FrameReader
|
||||
{
|
||||
public static bool ReadFrame(ReadOnlyBuffer<byte> readableBuffer, Http2Frame frame, out SequencePosition consumed, out SequencePosition examined)
|
||||
public static bool ReadFrame(ReadOnlySequence<byte> readableBuffer, Http2Frame frame, out SequencePosition consumed, out SequencePosition examined)
|
||||
{
|
||||
consumed = readableBuffer.Start;
|
||||
examined = readableBuffer.End;
|
||||
|
|
|
|||
|
|
@ -190,7 +190,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
|
|||
}
|
||||
|
||||
_outputWriter.Write(data);
|
||||
_outputWriter.Commit();
|
||||
}
|
||||
|
||||
// Must be called with _writeLock
|
||||
|
|
|
|||
|
|
@ -83,14 +83,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
|
|||
{
|
||||
if (data.Count > 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
RequestBodyPipe.Writer.Write(data);
|
||||
}
|
||||
finally
|
||||
{
|
||||
RequestBodyPipe.Writer.Commit();
|
||||
}
|
||||
RequestBodyPipe.Writer.Write(data);
|
||||
|
||||
RequestBodyStarted = true;
|
||||
await RequestBodyPipe.Writer.FlushAsync();
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
|
|||
public int StreamId { get; set; }
|
||||
public ServiceContext ServiceContext { get; set; }
|
||||
public IFeatureCollection ConnectionFeatures { get; set; }
|
||||
public MemoryPool MemoryPool { get; set; }
|
||||
public MemoryPool<byte> MemoryPool { get; set; }
|
||||
public IPEndPoint RemoteEndPoint { get; set; }
|
||||
public IPEndPoint LocalEndPoint { get; set; }
|
||||
public IHttp2StreamLifetimeHandler StreamLifetimeHandler { get; set; }
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
|
|||
public IPEndPoint LocalEndPoint => _context.LocalEndPoint;
|
||||
public IPEndPoint RemoteEndPoint => _context.RemoteEndPoint;
|
||||
|
||||
private MemoryPool MemoryPool => _context.MemoryPool;
|
||||
private MemoryPool<byte> MemoryPool => _context.MemoryPool;
|
||||
|
||||
// Internal for testing
|
||||
internal PipeOptions AdaptedInputPipeOptions => new PipeOptions
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
|
|||
public ServiceContext ServiceContext { get; set; }
|
||||
public IFeatureCollection ConnectionFeatures { get; set; }
|
||||
public IList<IConnectionAdapter> ConnectionAdapters { get; set; }
|
||||
public MemoryPool MemoryPool { get; set; }
|
||||
public MemoryPool<byte> MemoryPool { get; set; }
|
||||
public IPEndPoint LocalEndPoint { get; set; }
|
||||
public IPEndPoint RemoteEndPoint { get; set; }
|
||||
public IDuplexPipe Transport { 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;
|
||||
using System.IO.Pipelines;
|
||||
using System.Threading;
|
||||
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
<PackageReference Include="Microsoft.Extensions.Options" Version="$(MicrosoftExtensionsOptionsPackageVersion)" />
|
||||
<PackageReference Include="System.Threading.Tasks.Extensions" Version="$(SystemThreadingTasksExtensionsPackageVersion)" />
|
||||
<PackageReference Include="System.Memory" Version="$(SystemMemoryPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.Buffers.Sources" Version="$(MicrosoftExtensionsBuffersSourcesPackageVersion)" PrivateAssets="All" />
|
||||
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="$(SystemRuntimeCompilerServicesUnsafePackageVersion)" />
|
||||
<PackageReference Include="System.Security.Cryptography.Cng" Version="$(SystemSecurityCryptographyCngPackageVersion)" />
|
||||
</ItemGroup>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Buffers;
|
||||
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal
|
||||
{
|
||||
public static class KestrelMemoryPool
|
||||
{
|
||||
public static MemoryPool<byte> Create() => new SlabMemoryPool();
|
||||
}
|
||||
}
|
||||
|
|
@ -95,7 +95,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal
|
|||
set => LocalPort = value;
|
||||
}
|
||||
|
||||
MemoryPool IConnectionTransportFeature.MemoryPool => MemoryPool;
|
||||
MemoryPool<byte> IConnectionTransportFeature.MemoryPool => MemoryPool;
|
||||
|
||||
IDuplexPipe IConnectionTransportFeature.Transport
|
||||
{
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal
|
|||
|
||||
public string ConnectionId { get; set; }
|
||||
|
||||
public virtual MemoryPool MemoryPool { get; }
|
||||
public virtual MemoryPool<byte> MemoryPool { get; }
|
||||
public virtual PipeScheduler InputWriterScheduler { get; }
|
||||
public virtual PipeScheduler OutputReaderScheduler { get; }
|
||||
|
||||
|
|
|
|||
|
|
@ -15,5 +15,8 @@
|
|||
<ItemGroup>
|
||||
<ProjectReference Include="..\Protocols.Abstractions\Protocols.Abstractions.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Buffers.Sources" Version="$(MicrosoftExtensionsBuffersSourcesPackageVersion)" PrivateAssets="All" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -122,7 +122,6 @@ 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
|
||||
Input.Commit();
|
||||
}
|
||||
else if (status > 0)
|
||||
{
|
||||
|
|
@ -141,7 +140,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
|||
else
|
||||
{
|
||||
// Given a negative status, it's possible that OnAlloc wasn't called.
|
||||
Input.Commit();
|
||||
_socket.ReadStop();
|
||||
|
||||
IOException error = null;
|
||||
|
|
@ -175,7 +173,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
|||
_bufferHandle.Dispose();
|
||||
}
|
||||
|
||||
private async Task ApplyBackpressureAsync(ValueAwaiter<FlushResult> flushTask)
|
||||
private async Task ApplyBackpressureAsync(PipeAwaiter<FlushResult> flushTask)
|
||||
{
|
||||
Log.ConnectionPause(ConnectionId);
|
||||
_socket.ReadStop();
|
||||
|
|
@ -183,7 +181,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
|||
var result = await flushTask;
|
||||
|
||||
// If the reader isn't complete or cancelled then resume reading
|
||||
if (!result.IsCompleted && !result.IsCancelled)
|
||||
if (!result.IsCompleted && !result.IsCanceled)
|
||||
{
|
||||
Log.ConnectionResume(ConnectionId);
|
||||
StartReading();
|
||||
|
|
|
|||
|
|
@ -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.IO.Pipelines;
|
||||
using System.Threading;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
|
||||
|
||||
|
|
@ -16,7 +17,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
|||
|
||||
public ListenerContext ListenerContext { get; set; }
|
||||
|
||||
public override MemoryPool MemoryPool => ListenerContext.Thread.MemoryPool;
|
||||
public override MemoryPool<byte> MemoryPool => ListenerContext.Thread.MemoryPool;
|
||||
public override PipeScheduler InputWriterScheduler => ListenerContext.Thread;
|
||||
public override PipeScheduler OutputReaderScheduler => ListenerContext.Thread;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
|||
|
||||
try
|
||||
{
|
||||
if (result.IsCancelled)
|
||||
if (result.IsCanceled)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,10 +5,12 @@ using System;
|
|||
using System.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO.Pipelines;
|
||||
using System.Runtime.ExceptionServices;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networking;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
|
|
@ -55,7 +57,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
|||
#endif
|
||||
QueueCloseHandle = PostCloseHandle;
|
||||
QueueCloseAsyncHandle = EnqueueCloseHandle;
|
||||
MemoryPool = new MemoryPool();
|
||||
MemoryPool = KestrelMemoryPool.Create();
|
||||
WriteReqPool = new WriteReqPool(this, _log);
|
||||
}
|
||||
|
||||
|
|
@ -68,7 +70,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
|||
|
||||
public UvLoopHandle Loop { get { return _loop; } }
|
||||
|
||||
public MemoryPool MemoryPool { get; }
|
||||
public MemoryPool<byte> MemoryPool { get; }
|
||||
|
||||
public WriteReqPool WriteReqPool { get; }
|
||||
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networkin
|
|||
_bufs = handle + requestSize;
|
||||
}
|
||||
|
||||
public LibuvAwaitable<UvWriteReq> WriteAsync(UvStreamHandle handle, ReadOnlyBuffer<byte> buffer)
|
||||
public LibuvAwaitable<UvWriteReq> WriteAsync(UvStreamHandle handle, ReadOnlySequence<byte> buffer)
|
||||
{
|
||||
Write(handle, buffer, LibuvAwaitable<UvWriteReq>.Callback, _awaitable);
|
||||
return _awaitable;
|
||||
|
|
@ -62,7 +62,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networkin
|
|||
|
||||
private unsafe void Write(
|
||||
UvStreamHandle handle,
|
||||
ReadOnlyBuffer<byte> buffer,
|
||||
ReadOnlySequence<byte> buffer,
|
||||
Action<UvWriteReq, int, UvException, object> callback,
|
||||
object state)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ using System;
|
|||
using System.Buffers;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.IO.Pipelines;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading.Tasks;
|
||||
|
|
@ -26,7 +27,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal
|
|||
|
||||
private volatile bool _aborted;
|
||||
|
||||
internal SocketConnection(Socket socket, MemoryPool memoryPool, ISocketsTrace trace)
|
||||
internal SocketConnection(Socket socket, MemoryPool<byte> memoryPool, ISocketsTrace trace)
|
||||
{
|
||||
Debug.Assert(socket != null);
|
||||
Debug.Assert(memoryPool != null);
|
||||
|
|
@ -49,7 +50,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal
|
|||
_sender = new SocketSender(_socket);
|
||||
}
|
||||
|
||||
public override MemoryPool MemoryPool { get; }
|
||||
public override MemoryPool<byte> MemoryPool { get; }
|
||||
public override PipeScheduler InputWriterScheduler => PipeScheduler.Inline;
|
||||
public override PipeScheduler OutputReaderScheduler => PipeScheduler.ThreadPool;
|
||||
|
||||
|
|
@ -102,24 +103,18 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal
|
|||
// Ensure we have some reasonable amount of buffer space
|
||||
var buffer = Input.GetMemory(MinAllocBufferSize);
|
||||
|
||||
try
|
||||
{
|
||||
var bytesReceived = await _receiver.ReceiveAsync(buffer);
|
||||
var bytesReceived = await _receiver.ReceiveAsync(buffer);
|
||||
|
||||
if (bytesReceived == 0)
|
||||
{
|
||||
// FIN
|
||||
_trace.ConnectionReadFin(ConnectionId);
|
||||
break;
|
||||
}
|
||||
|
||||
Input.Advance(bytesReceived);
|
||||
}
|
||||
finally
|
||||
if (bytesReceived == 0)
|
||||
{
|
||||
Input.Commit();
|
||||
// FIN
|
||||
_trace.ConnectionReadFin(ConnectionId);
|
||||
break;
|
||||
}
|
||||
|
||||
Input.Advance(bytesReceived);
|
||||
|
||||
|
||||
var flushTask = Input.FlushAsync();
|
||||
|
||||
if (!flushTask.IsCompleted)
|
||||
|
|
@ -197,7 +192,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal
|
|||
var result = await Output.ReadAsync();
|
||||
var buffer = result.Buffer;
|
||||
|
||||
if (result.IsCancelled)
|
||||
if (result.IsCanceled)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal
|
|||
_eventArgs.Completed += (_, e) => ((SocketAwaitable)e.UserToken).Complete(e.BytesTransferred, e.SocketError);
|
||||
}
|
||||
|
||||
public SocketAwaitable SendAsync(ReadOnlyBuffer<byte> buffers)
|
||||
public SocketAwaitable SendAsync(ReadOnlySequence<byte> buffers)
|
||||
{
|
||||
if (buffers.IsSingleSegment)
|
||||
{
|
||||
|
|
@ -74,7 +74,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal
|
|||
return _awaitable;
|
||||
}
|
||||
|
||||
private List<ArraySegment<byte>> GetBufferList(ReadOnlyBuffer<byte> buffer)
|
||||
private List<ArraySegment<byte>> GetBufferList(ReadOnlySequence<byte> buffer)
|
||||
{
|
||||
Debug.Assert(!buffer.IsEmpty);
|
||||
Debug.Assert(!buffer.IsSingleSegment);
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets
|
|||
{
|
||||
internal sealed class SocketTransport : ITransport
|
||||
{
|
||||
private readonly MemoryPool _memoryPool = new MemoryPool();
|
||||
private readonly MemoryPool<byte> _memoryPool = KestrelMemoryPool.Create();
|
||||
private readonly IEndPointInformation _endPointInformation;
|
||||
private readonly IConnectionHandler _handler;
|
||||
private readonly IApplicationLifetime _appLifetime;
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ namespace System.IO.Pipelines
|
|||
{
|
||||
}
|
||||
|
||||
public static DuplexPipePair CreateConnectionPair(MemoryPool memoryPool)
|
||||
public static DuplexPipePair CreateConnectionPair(MemoryPool<byte> memoryPool)
|
||||
{
|
||||
return CreateConnectionPair(new PipeOptions(memoryPool), new PipeOptions(memoryPool));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ namespace Microsoft.AspNetCore.Protocols.Features
|
|||
{
|
||||
public interface IConnectionTransportFeature
|
||||
{
|
||||
MemoryPool MemoryPool { get; }
|
||||
MemoryPool<byte> MemoryPool { get; }
|
||||
|
||||
IDuplexPipe Transport { get; set; }
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@
|
|||
<PackageReference Include="System.Numerics.Vectors" Version="$(SystemNumericsVectorsPackageVersion)" />
|
||||
<PackageReference Include="System.Buffers" Version="$(SystemBuffersPackageVersion)" />
|
||||
<PackageReference Include="System.IO.Pipelines" Version="$(SystemIOPipelinesPackageVersion)" />
|
||||
<PackageReference Include="System.Text.Encodings.Web.Utf8" Version="$(SystemTextEncodingsWebUtf8PackageVersion)" />
|
||||
<PackageReference Include="System.Memory" Version="$(SystemMemoryPackageVersion)" />
|
||||
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="$(SystemRuntimeCompilerServicesUnsafePackageVersion)" />
|
||||
</ItemGroup>
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@ using System.Threading.Tasks;
|
|||
using Microsoft.AspNetCore.Http.Features;
|
||||
using Microsoft.AspNetCore.Protocols.Features;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
|
||||
using Microsoft.AspNetCore.Testing;
|
||||
using Xunit;
|
||||
|
||||
|
|
@ -51,7 +53,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
Set<IConnectionTransportFeature>(this);
|
||||
}
|
||||
|
||||
public MemoryPool MemoryPool { get; } = new MemoryPool();
|
||||
public MemoryPool<byte> MemoryPool { get; } = KestrelMemoryPool.Create();
|
||||
|
||||
public IDuplexPipe Transport { get; set; }
|
||||
public IDuplexPipe Application { get; set; }
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ using Microsoft.AspNetCore.Server.Kestrel.Core.Features;
|
|||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
|
||||
using Microsoft.AspNetCore.Testing;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
|
|
@ -32,14 +33,14 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
private readonly TestHttp1Connection _http1Connection;
|
||||
private readonly ServiceContext _serviceContext;
|
||||
private readonly Http1ConnectionContext _http1ConnectionContext;
|
||||
private readonly MemoryPool _pipelineFactory;
|
||||
private readonly MemoryPool<byte> _pipelineFactory;
|
||||
private SequencePosition _consumed;
|
||||
private SequencePosition _examined;
|
||||
private Mock<ITimeoutControl> _timeoutControl;
|
||||
|
||||
public Http1ConnectionTests()
|
||||
{
|
||||
_pipelineFactory = new MemoryPool();
|
||||
_pipelineFactory = KestrelMemoryPool.Create();
|
||||
var pair = DuplexPipe.CreateConnectionPair(_pipelineFactory);
|
||||
|
||||
_transport = pair.Transport;
|
||||
|
|
@ -803,7 +804,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
_http1Connection.NextMessageBody = mockMessageBody.Object;
|
||||
|
||||
var requestProcessingTask = _http1Connection.ProcessRequestsAsync(httpApplication);
|
||||
|
||||
|
||||
var data = Encoding.ASCII.GetBytes("POST / HTTP/1.1\r\nHost:\r\nConnection: close\r\ncontent-length: 1\r\n\r\n");
|
||||
await _application.Output.WriteAsync(data);
|
||||
await requestProcessingTask.TimeoutAfter(TestConstants.DefaultTimeout);
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
|
|||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2.HPack;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
|
||||
using Microsoft.AspNetCore.Testing;
|
||||
using Xunit;
|
||||
|
||||
|
|
@ -93,7 +94,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
private static readonly byte[] _noData = new byte[0];
|
||||
private static readonly byte[] _maxData = Encoding.ASCII.GetBytes(new string('a', Http2Frame.MinAllowedMaxFrameSize));
|
||||
|
||||
private readonly MemoryPool _memoryPool = new MemoryPool();
|
||||
private readonly MemoryPool<byte> _memoryPool = KestrelMemoryPool.Create();
|
||||
private readonly DuplexPipe.DuplexPipePair _pair;
|
||||
private readonly TestApplicationErrorLogger _logger;
|
||||
private readonly Http2ConnectionContext _connectionContext;
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ using Microsoft.AspNetCore.Http.Features;
|
|||
using Microsoft.AspNetCore.Server.Kestrel.Core.Adapter.Internal;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
|
||||
using Microsoft.AspNetCore.Testing;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
|
@ -18,13 +19,13 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
{
|
||||
public class HttpConnectionTests : IDisposable
|
||||
{
|
||||
private readonly MemoryPool _memoryPool;
|
||||
private readonly MemoryPool<byte> _memoryPool;
|
||||
private readonly HttpConnectionContext _httpConnectionContext;
|
||||
private readonly HttpConnection _httpConnection;
|
||||
|
||||
public HttpConnectionTests()
|
||||
{
|
||||
_memoryPool = new MemoryPool();
|
||||
_memoryPool = KestrelMemoryPool.Create();
|
||||
var pair = DuplexPipe.CreateConnectionPair(_memoryPool);
|
||||
|
||||
_httpConnectionContext = new HttpConnectionContext
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
string expectedVersion)
|
||||
{
|
||||
var parser = CreateParser(Mock.Of<IKestrelTrace>());
|
||||
var buffer = new ReadOnlyBuffer<byte>(Encoding.ASCII.GetBytes(requestLine));
|
||||
var buffer = new ReadOnlySequence<byte>(Encoding.ASCII.GetBytes(requestLine));
|
||||
var requestHandler = new RequestHandler();
|
||||
|
||||
Assert.True(parser.ParseRequestLine(requestHandler, buffer, out var consumed, out var examined));
|
||||
|
|
@ -53,7 +53,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
public void ParseRequestLineReturnsFalseWhenGivenIncompleteRequestLines(string requestLine)
|
||||
{
|
||||
var parser = CreateParser(Mock.Of<IKestrelTrace>());
|
||||
var buffer = new ReadOnlyBuffer<byte>(Encoding.ASCII.GetBytes(requestLine));
|
||||
var buffer = new ReadOnlySequence<byte>(Encoding.ASCII.GetBytes(requestLine));
|
||||
var requestHandler = new RequestHandler();
|
||||
|
||||
Assert.False(parser.ParseRequestLine(requestHandler, buffer, out var consumed, out var examined));
|
||||
|
|
@ -64,7 +64,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
public void ParseRequestLineDoesNotConsumeIncompleteRequestLine(string requestLine)
|
||||
{
|
||||
var parser = CreateParser(Mock.Of<IKestrelTrace>());
|
||||
var buffer = new ReadOnlyBuffer<byte>(Encoding.ASCII.GetBytes(requestLine));
|
||||
var buffer = new ReadOnlySequence<byte>(Encoding.ASCII.GetBytes(requestLine));
|
||||
var requestHandler = new RequestHandler();
|
||||
|
||||
Assert.False(parser.ParseRequestLine(requestHandler, buffer, out var consumed, out var examined));
|
||||
|
|
@ -83,7 +83,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
.Returns(true);
|
||||
|
||||
var parser = CreateParser(mockTrace.Object);
|
||||
var buffer = new ReadOnlyBuffer<byte>(Encoding.ASCII.GetBytes(requestLine));
|
||||
var buffer = new ReadOnlySequence<byte>(Encoding.ASCII.GetBytes(requestLine));
|
||||
var requestHandler = new RequestHandler();
|
||||
|
||||
var exception = Assert.Throws<BadHttpRequestException>(() =>
|
||||
|
|
@ -105,7 +105,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
.Returns(true);
|
||||
|
||||
var parser = CreateParser(mockTrace.Object);
|
||||
var buffer = new ReadOnlyBuffer<byte>(Encoding.ASCII.GetBytes(requestLine));
|
||||
var buffer = new ReadOnlySequence<byte>(Encoding.ASCII.GetBytes(requestLine));
|
||||
var requestHandler = new RequestHandler();
|
||||
|
||||
var exception = Assert.Throws<BadHttpRequestException>(() =>
|
||||
|
|
@ -127,7 +127,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
.Returns(true);
|
||||
|
||||
var parser = CreateParser(mockTrace.Object);
|
||||
var buffer = new ReadOnlyBuffer<byte>(Encoding.ASCII.GetBytes(requestLine));
|
||||
var buffer = new ReadOnlySequence<byte>(Encoding.ASCII.GetBytes(requestLine));
|
||||
var requestHandler = new RequestHandler();
|
||||
|
||||
var exception = Assert.Throws<BadHttpRequestException>(() =>
|
||||
|
|
@ -178,7 +178,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
{
|
||||
var parser = CreateParser(Mock.Of<IKestrelTrace>());
|
||||
|
||||
var buffer = new ReadOnlyBuffer<byte>(Encoding.ASCII.GetBytes(rawHeaders));
|
||||
var buffer = new ReadOnlySequence<byte>(Encoding.ASCII.GetBytes(rawHeaders));
|
||||
var requestHandler = new RequestHandler();
|
||||
Assert.False(parser.ParseHeaders(requestHandler, buffer, out var consumed, out var examined, out var consumedBytes));
|
||||
}
|
||||
|
|
@ -203,7 +203,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
{
|
||||
var parser = CreateParser(Mock.Of<IKestrelTrace>());
|
||||
|
||||
var buffer = new ReadOnlyBuffer<byte>(Encoding.ASCII.GetBytes(rawHeaders));
|
||||
var buffer = new ReadOnlySequence<byte>(Encoding.ASCII.GetBytes(rawHeaders));
|
||||
var requestHandler = new RequestHandler();
|
||||
parser.ParseHeaders(requestHandler, buffer, out var consumed, out var examined, out var consumedBytes);
|
||||
|
||||
|
|
@ -293,7 +293,7 @@ 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<byte>(Encoding.ASCII.GetBytes(headerLine));
|
||||
var buffer1 = new ReadOnlySequence<byte>(Encoding.ASCII.GetBytes(headerLine));
|
||||
var requestHandler = new RequestHandler();
|
||||
Assert.False(parser.ParseHeaders(requestHandler, buffer1, out var consumed, out var examined, out var consumedBytes));
|
||||
|
||||
|
|
@ -301,7 +301,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
Assert.Equal(buffer1.End, examined);
|
||||
Assert.Equal(headerLine.Length - 1, consumedBytes);
|
||||
|
||||
var buffer2 = new ReadOnlyBuffer<byte>(Encoding.ASCII.GetBytes("\r\n"));
|
||||
var buffer2 = new ReadOnlySequence<byte>(Encoding.ASCII.GetBytes("\r\n"));
|
||||
Assert.True(parser.ParseHeaders(requestHandler, buffer2, out consumed, out examined, out consumedBytes));
|
||||
|
||||
Assert.True(buffer2.Slice(consumed).IsEmpty);
|
||||
|
|
@ -319,7 +319,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
.Returns(true);
|
||||
|
||||
var parser = CreateParser(mockTrace.Object);
|
||||
var buffer = new ReadOnlyBuffer<byte>(Encoding.ASCII.GetBytes(rawHeaders));
|
||||
var buffer = new ReadOnlySequence<byte>(Encoding.ASCII.GetBytes(rawHeaders));
|
||||
var requestHandler = new RequestHandler();
|
||||
|
||||
var exception = Assert.Throws<BadHttpRequestException>(() =>
|
||||
|
|
@ -340,7 +340,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
var parser = CreateParser(mockTrace.Object);
|
||||
|
||||
// Invalid request line
|
||||
var buffer = new ReadOnlyBuffer<byte>(Encoding.ASCII.GetBytes("GET % HTTP/1.1\r\n"));
|
||||
var buffer = new ReadOnlySequence<byte>(Encoding.ASCII.GetBytes("GET % HTTP/1.1\r\n"));
|
||||
var requestHandler = new RequestHandler();
|
||||
|
||||
var exception = Assert.Throws<BadHttpRequestException>(() =>
|
||||
|
|
@ -350,7 +350,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
Assert.Equal(StatusCodes.Status400BadRequest, (exception as BadHttpRequestException).StatusCode);
|
||||
|
||||
// Unrecognized HTTP version
|
||||
buffer = new ReadOnlyBuffer<byte>(Encoding.ASCII.GetBytes("GET / HTTP/1.2\r\n"));
|
||||
buffer = new ReadOnlySequence<byte>(Encoding.ASCII.GetBytes("GET / HTTP/1.2\r\n"));
|
||||
|
||||
exception = Assert.Throws<BadHttpRequestException>(() =>
|
||||
parser.ParseRequestLine(requestHandler, buffer, out var consumed, out var examined));
|
||||
|
|
@ -359,7 +359,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
Assert.Equal(StatusCodes.Status505HttpVersionNotsupported, (exception as BadHttpRequestException).StatusCode);
|
||||
|
||||
// Invalid request header
|
||||
buffer = new ReadOnlyBuffer<byte>(Encoding.ASCII.GetBytes("Header: value\n\r\n"));
|
||||
buffer = new ReadOnlySequence<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));
|
||||
|
|
@ -388,7 +388,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
string expectedHeaderValue)
|
||||
{
|
||||
var parser = CreateParser(Mock.Of<IKestrelTrace>());
|
||||
var buffer = new ReadOnlyBuffer<byte>(Encoding.ASCII.GetBytes($"{headerName}:{rawHeaderValue}\r\n"));
|
||||
var buffer = new ReadOnlySequence<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);
|
||||
|
|
@ -406,7 +406,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<byte>(Encoding.ASCII.GetBytes(rawHeaders));
|
||||
var buffer = new ReadOnlySequence<byte>(Encoding.ASCII.GetBytes(rawHeaders));
|
||||
|
||||
var requestHandler = new RequestHandler();
|
||||
parser.ParseHeaders(requestHandler, buffer, out var consumed, out var examined, out var consumedBytes);
|
||||
|
|
@ -466,7 +466,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
}
|
||||
}
|
||||
|
||||
private static ReadOnlyBuffer<byte> CreateBuffer(params string[] inputs)
|
||||
private static ReadOnlySequence<byte> CreateBuffer(params string[] inputs)
|
||||
{
|
||||
var buffers = new byte[inputs.Length][];
|
||||
for (int i = 0; i < inputs.Length; i++)
|
||||
|
|
@ -477,7 +477,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
}
|
||||
|
||||
// Copied from https://github.com/dotnet/corefx/blob/master/src/System.Memory/tests/ReadOnlyBuffer/ReadOnlySequenceFactory.cs
|
||||
private static ReadOnlyBuffer<byte> CreateBuffer(params byte[][] inputs)
|
||||
private static ReadOnlySequence<byte> CreateBuffer(params byte[][] inputs)
|
||||
{
|
||||
if (inputs == null || inputs.Length == 0)
|
||||
{
|
||||
|
|
@ -516,7 +516,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
i++;
|
||||
} while (i < inputs.Length);
|
||||
|
||||
return new ReadOnlyBuffer<byte>(first, 0, last, last.Memory.Length);
|
||||
return new ReadOnlySequence<byte>(first, 0, last, last.Memory.Length);
|
||||
}
|
||||
|
||||
// Copied from https://github.com/dotnet/corefx/blob/master/src/System.Memory/tests/ReadOnlyBuffer/BufferSegment.cs
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ using Microsoft.AspNetCore.Server.Kestrel.Core.Features;
|
|||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
|
||||
using Microsoft.AspNetCore.Testing;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
|
@ -23,14 +24,14 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
private readonly TestHttp1Connection _http1Connection;
|
||||
private readonly ServiceContext _serviceContext;
|
||||
private readonly Http1ConnectionContext _http1ConnectionContext;
|
||||
private readonly MemoryPool _pipelineFactory;
|
||||
private readonly MemoryPool<byte> _pipelineFactory;
|
||||
private Mock<ITimeoutControl> _timeoutControl;
|
||||
|
||||
private readonly IFeatureCollection _collection;
|
||||
|
||||
public HttpProtocolFeatureCollectionTests()
|
||||
{
|
||||
_pipelineFactory = new MemoryPool();
|
||||
_pipelineFactory = KestrelMemoryPool.Create();
|
||||
var pair = DuplexPipe.CreateConnectionPair(_pipelineFactory);
|
||||
|
||||
_transport = pair.Transport;
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ using System.IO.Pipelines;
|
|||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
|
||||
using Microsoft.AspNetCore.Testing;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
using Xunit;
|
||||
|
|
@ -20,7 +21,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
[Fact]
|
||||
public void InitialDictionaryIsEmpty()
|
||||
{
|
||||
using (var memoryPool = new MemoryPool())
|
||||
using (var memoryPool = KestrelMemoryPool.Create())
|
||||
{
|
||||
var pair = DuplexPipe.CreateConnectionPair(memoryPool);
|
||||
var http1ConnectionContext = new Http1ConnectionContext
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ using System.IO.Pipelines;
|
|||
using System.Threading;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
|
||||
using Microsoft.AspNetCore.Testing;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
|
@ -15,11 +16,11 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
{
|
||||
public class OutputProducerTests : IDisposable
|
||||
{
|
||||
private readonly MemoryPool _memoryPool;
|
||||
private readonly MemoryPool<byte> _memoryPool;
|
||||
|
||||
public OutputProducerTests()
|
||||
{
|
||||
_memoryPool = new MemoryPool();
|
||||
_memoryPool = KestrelMemoryPool.Create();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
|
|
|||
|
|
@ -2,9 +2,11 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Buffers;
|
||||
using System.IO.Pipelines;
|
||||
using System.Threading;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
|
||||
using Microsoft.AspNetCore.Testing;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
|
@ -24,7 +26,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
serviceContext.ThreadPool = new LoggingThreadPool(null);
|
||||
|
||||
var mockScheduler = Mock.Of<PipeScheduler>();
|
||||
var outputPipeOptions = ConnectionHandler.GetOutputPipeOptions(serviceContext, new MemoryPool(), readerScheduler: mockScheduler);
|
||||
var outputPipeOptions = ConnectionHandler.GetOutputPipeOptions(serviceContext, KestrelMemoryPool.Create(), readerScheduler: mockScheduler);
|
||||
|
||||
Assert.Equal(expectedMaximumSizeLow, outputPipeOptions.ResumeWriterThreshold);
|
||||
Assert.Equal(expectedMaximumSizeHigh, outputPipeOptions.PauseWriterThreshold);
|
||||
|
|
@ -42,7 +44,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
serviceContext.ThreadPool = new LoggingThreadPool(null);
|
||||
|
||||
var mockScheduler = Mock.Of<PipeScheduler>();
|
||||
var inputPipeOptions = ConnectionHandler.GetInputPipeOptions(serviceContext, new MemoryPool(), writerScheduler: mockScheduler);
|
||||
var inputPipeOptions = ConnectionHandler.GetInputPipeOptions(serviceContext, KestrelMemoryPool.Create(), writerScheduler: mockScheduler);
|
||||
|
||||
Assert.Equal(expectedMaximumSizeLow, inputPipeOptions.ResumeWriterThreshold);
|
||||
Assert.Equal(expectedMaximumSizeHigh, inputPipeOptions.PauseWriterThreshold);
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ using System.Buffers;
|
|||
using System.IO.Pipelines;
|
||||
using System.Text;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
||||
|
|
@ -16,7 +17,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
private const int _ulongMaxValueLength = 20;
|
||||
|
||||
private readonly Pipe _pipe;
|
||||
private readonly MemoryPool _memoryPool = new MemoryPool();
|
||||
private readonly MemoryPool<byte> _memoryPool = KestrelMemoryPool.Create();
|
||||
|
||||
public PipelineExtensionTests()
|
||||
{
|
||||
|
|
@ -35,8 +36,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
public void WritesNumericToAscii(ulong number)
|
||||
{
|
||||
var writerBuffer = _pipe.Writer;
|
||||
var writer = OutputWriter.Create(writerBuffer);
|
||||
var writer = new BufferWriter<PipeWriter>(writerBuffer);
|
||||
writer.WriteNumeric(number);
|
||||
writer.Commit();
|
||||
writerBuffer.FlushAsync().GetAwaiter().GetResult();
|
||||
|
||||
var reader = _pipe.Reader.ReadAsync().GetAwaiter().GetResult();
|
||||
|
|
@ -52,7 +54,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
public void WritesNumericAcrossSpanBoundaries(int gapSize)
|
||||
{
|
||||
var writerBuffer = _pipe.Writer;
|
||||
var writer = OutputWriter.Create(writerBuffer);
|
||||
var writer = new BufferWriter<PipeWriter>(writerBuffer);
|
||||
// almost fill up the first block
|
||||
var spacer = new byte[writer.Span.Length - gapSize];
|
||||
writer.Write(spacer);
|
||||
|
|
@ -60,7 +62,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
var bufferLength = writer.Span.Length;
|
||||
writer.WriteNumeric(ulong.MaxValue);
|
||||
Assert.NotEqual(bufferLength, writer.Span.Length);
|
||||
|
||||
writer.Commit();
|
||||
writerBuffer.FlushAsync().GetAwaiter().GetResult();
|
||||
|
||||
var reader = _pipe.Reader.ReadAsync().GetAwaiter().GetResult();
|
||||
|
|
@ -83,8 +85,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
public void EncodesAsAscii(string input, byte[] expected)
|
||||
{
|
||||
var writerBuffer = _pipe.Writer;
|
||||
var writer = OutputWriter.Create(writerBuffer);
|
||||
var writer = new BufferWriter<PipeWriter>(writerBuffer);
|
||||
writer.WriteAsciiNoValidation(input);
|
||||
writer.Commit();
|
||||
writerBuffer.FlushAsync().GetAwaiter().GetResult();
|
||||
var reader = _pipe.Reader.ReadAsync().GetAwaiter().GetResult();
|
||||
|
||||
|
|
@ -110,8 +113,9 @@ 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;
|
||||
var writer = OutputWriter.Create(writerBuffer);
|
||||
var writer = new BufferWriter<PipeWriter>(writerBuffer);
|
||||
writer.WriteAsciiNoValidation(input);
|
||||
writer.Commit();
|
||||
writerBuffer.FlushAsync().GetAwaiter().GetResult();
|
||||
var reader = _pipe.Reader.ReadAsync().GetAwaiter().GetResult();
|
||||
|
||||
|
|
@ -123,11 +127,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
{
|
||||
const byte maxAscii = 0x7f;
|
||||
var writerBuffer = _pipe.Writer;
|
||||
var writer = OutputWriter.Create(writerBuffer);
|
||||
var writer = new BufferWriter<PipeWriter>(writerBuffer);
|
||||
for (var i = 0; i < maxAscii; i++)
|
||||
{
|
||||
writer.WriteAsciiNoValidation(new string((char)i, 1));
|
||||
}
|
||||
writer.Commit();
|
||||
writerBuffer.FlushAsync().GetAwaiter().GetResult();
|
||||
|
||||
var reader = _pipe.Reader.ReadAsync().GetAwaiter().GetResult();
|
||||
|
|
@ -152,7 +157,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
{
|
||||
var testString = new string(' ', stringLength);
|
||||
var writerBuffer = _pipe.Writer;
|
||||
var writer = OutputWriter.Create(writerBuffer);
|
||||
var writer = new BufferWriter<PipeWriter>(writerBuffer);
|
||||
// almost fill up the first block
|
||||
var spacer = new byte[writer.Span.Length - gapSize];
|
||||
writer.Write(spacer);
|
||||
|
|
@ -161,7 +166,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
var bufferLength = writer.Span.Length;
|
||||
writer.WriteAsciiNoValidation(testString);
|
||||
Assert.NotEqual(bufferLength, writer.Span.Length);
|
||||
|
||||
writer.Commit();
|
||||
writerBuffer.FlushAsync().GetAwaiter().GetResult();
|
||||
|
||||
var reader = _pipe.Reader.ReadAsync().GetAwaiter().GetResult();
|
||||
|
|
|
|||
|
|
@ -5,9 +5,11 @@ using System;
|
|||
using System.Buffers;
|
||||
using System.IO.Pipelines;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
|
||||
using Microsoft.AspNetCore.Testing;
|
||||
using Moq;
|
||||
|
||||
|
|
@ -15,11 +17,11 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
{
|
||||
class TestInput : IDisposable
|
||||
{
|
||||
private MemoryPool _memoryPool;
|
||||
private MemoryPool<byte> _memoryPool;
|
||||
|
||||
public TestInput()
|
||||
{
|
||||
_memoryPool = new MemoryPool();
|
||||
_memoryPool = KestrelMemoryPool.Create();
|
||||
var pair = DuplexPipe.CreateConnectionPair(_memoryPool);
|
||||
Transport = pair.Transport;
|
||||
Application = pair.Application;
|
||||
|
|
@ -49,7 +51,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
public void Add(string text)
|
||||
{
|
||||
var data = Encoding.ASCII.GetBytes(text);
|
||||
Application.Output.WriteAsync(data).Wait();
|
||||
async Task Write() => await Application.Output.WriteAsync(data);
|
||||
Write().Wait();
|
||||
}
|
||||
|
||||
public void Fin()
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ using Microsoft.AspNetCore.Http.Features;
|
|||
using Microsoft.AspNetCore.Server.Kestrel.Core;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networking;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests.TestHelpers;
|
||||
|
|
@ -22,7 +23,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
|||
{
|
||||
public class LibuvOutputConsumerTests : IDisposable
|
||||
{
|
||||
private readonly MemoryPool _memoryPool;
|
||||
private readonly MemoryPool<byte> _memoryPool;
|
||||
private readonly MockLibuv _mockLibuv;
|
||||
private readonly LibuvThread _libuvThread;
|
||||
|
||||
|
|
@ -38,7 +39,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
|||
|
||||
public LibuvOutputConsumerTests()
|
||||
{
|
||||
_memoryPool = new MemoryPool();
|
||||
_memoryPool = KestrelMemoryPool.Create();
|
||||
_mockLibuv = new MockLibuv();
|
||||
|
||||
var libuvTransport = new LibuvTransport(_mockLibuv, new TestLibuvTransportContext(), new ListenOptions((ulong)0));
|
||||
|
|
@ -340,6 +341,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
|||
(
|
||||
pool: _memoryPool,
|
||||
readerScheduler: _libuvThread,
|
||||
writerScheduler: PipeScheduler.Inline,
|
||||
pauseWriterThreshold: maxResponseBufferSize,
|
||||
resumeWriterThreshold: maxResponseBufferSize
|
||||
);
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
|||
|
||||
await writeRequest.WriteAsync(
|
||||
serverConnectionPipe,
|
||||
new ReadOnlyBuffer<byte>(new byte[] { 1, 2, 3, 4 }));
|
||||
new ReadOnlySequence<byte>(new byte[] { 1, 2, 3, 4 }));
|
||||
|
||||
writeRequest.Dispose();
|
||||
serverConnectionPipe.Dispose();
|
||||
|
|
|
|||
|
|
@ -161,7 +161,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
|||
{
|
||||
var req = new UvWriteReq(_logger);
|
||||
req.DangerousInit(loop);
|
||||
var block = new ReadOnlyBuffer<byte>(new byte[] { 65, 66, 67, 68, 69 });
|
||||
var block = new ReadOnlySequence<byte>(new byte[] { 65, 66, 67, 68, 69 });
|
||||
|
||||
await req.WriteAsync(
|
||||
tcp2,
|
||||
|
|
|
|||
|
|
@ -13,8 +13,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests.TestHelpers
|
|||
{
|
||||
public class MockConnectionHandler : IConnectionHandler
|
||||
{
|
||||
public Func<MemoryPool, PipeOptions> InputOptions { get; set; } = pool => new PipeOptions(pool);
|
||||
public Func<MemoryPool, PipeOptions> OutputOptions { get; set; } = pool => new PipeOptions(pool);
|
||||
public Func<MemoryPool<byte>, PipeOptions> InputOptions { get; set; } = pool => new PipeOptions(pool);
|
||||
public Func<MemoryPool<byte>, PipeOptions> OutputOptions { get; set; } = pool => new PipeOptions(pool);
|
||||
|
||||
public void OnConnection(IFeatureCollection features)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -523,7 +523,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
return true;
|
||||
}}
|
||||
{(loop.ClassName == "HttpResponseHeaders" ? $@"
|
||||
protected void CopyToFast(ref OutputWriter<PipeWriter> output)
|
||||
internal void CopyToFast(ref BufferWriter<PipeWriter> output)
|
||||
{{
|
||||
var tempBits = _bits | (_contentLength.HasValue ? {1L << 63}L : 0);
|
||||
{Each(loop.Headers.Where(header => header.Identifier != "ContentLength").OrderBy(h => !h.PrimaryHeader), header => $@"
|
||||
|
|
|
|||
Loading…
Reference in New Issue