Update to new corefx (#2369)
This commit is contained in:
parent
592ae79cf5
commit
fc80c15a65
|
|
@ -24,7 +24,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
|||
public void Setup()
|
||||
{
|
||||
var memoryPool = KestrelMemoryPool.Create();
|
||||
var pair = DuplexPipe.CreateConnectionPair(memoryPool);
|
||||
var options = new PipeOptions(memoryPool, readerScheduler: PipeScheduler.Inline, writerScheduler: PipeScheduler.Inline, useSynchronizationContext: false);
|
||||
var pair = DuplexPipe.CreateConnectionPair(options, options);
|
||||
|
||||
var serviceContext = new ServiceContext
|
||||
{
|
||||
|
|
|
|||
|
|
@ -96,7 +96,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
|||
|
||||
private TestHttp1Connection MakeHttp1Connection()
|
||||
{
|
||||
var pair = DuplexPipe.CreateConnectionPair(_memoryPool);
|
||||
var options = new PipeOptions(_memoryPool, readerScheduler: PipeScheduler.Inline, writerScheduler: PipeScheduler.Inline, useSynchronizationContext: false);
|
||||
var pair = DuplexPipe.CreateConnectionPair(options, options);
|
||||
_pair = pair;
|
||||
|
||||
var serviceContext = new ServiceContext
|
||||
|
|
|
|||
|
|
@ -80,7 +80,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
|||
public HttpProtocolFeatureCollection()
|
||||
{
|
||||
var memoryPool = KestrelMemoryPool.Create();
|
||||
var pair = DuplexPipe.CreateConnectionPair(memoryPool);
|
||||
var options = new PipeOptions(memoryPool, readerScheduler: PipeScheduler.Inline, writerScheduler: PipeScheduler.Inline, useSynchronizationContext: false);
|
||||
var pair = DuplexPipe.CreateConnectionPair(options, options);
|
||||
|
||||
var serviceContext = new ServiceContext
|
||||
{
|
||||
|
|
|
|||
|
|
@ -156,7 +156,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
|||
|
||||
public class InMemoryConnection : TransportConnection
|
||||
{
|
||||
public PipeAwaiter<FlushResult> SendRequestAsync(byte[] request)
|
||||
public ValueTask<FlushResult> SendRequestAsync(byte[] request)
|
||||
{
|
||||
return Input.WriteAsync(request);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
|||
public void Setup()
|
||||
{
|
||||
_memoryPool = KestrelMemoryPool.Create();
|
||||
var pair = DuplexPipe.CreateConnectionPair(_memoryPool);
|
||||
var options = new PipeOptions(_memoryPool, readerScheduler: PipeScheduler.Inline, writerScheduler: PipeScheduler.Inline, useSynchronizationContext: false);
|
||||
var pair = DuplexPipe.CreateConnectionPair(options, options);
|
||||
|
||||
var serviceContext = new ServiceContext
|
||||
{
|
||||
|
|
@ -147,7 +148,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
|||
return;
|
||||
}
|
||||
|
||||
var readableBuffer = awaitable.GetResult().Buffer;
|
||||
var readableBuffer = awaitable.GetAwaiter().GetResult().Buffer;
|
||||
do
|
||||
{
|
||||
Http1Connection.Reset();
|
||||
|
|
|
|||
|
|
@ -172,7 +172,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
|||
public void Setup()
|
||||
{
|
||||
var memoryPool = KestrelMemoryPool.Create();
|
||||
var pair = DuplexPipe.CreateConnectionPair(memoryPool);
|
||||
var options = new PipeOptions(memoryPool, readerScheduler: PipeScheduler.Inline, writerScheduler: PipeScheduler.Inline, useSynchronizationContext: false);
|
||||
var pair = DuplexPipe.CreateConnectionPair(options, options);
|
||||
|
||||
var serviceContext = new ServiceContext
|
||||
{
|
||||
|
|
|
|||
|
|
@ -114,7 +114,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
|||
public void Setup()
|
||||
{
|
||||
_memoryPool = KestrelMemoryPool.Create();
|
||||
var pair = DuplexPipe.CreateConnectionPair(_memoryPool);
|
||||
var options = new PipeOptions(_memoryPool, readerScheduler: PipeScheduler.Inline, writerScheduler: PipeScheduler.Inline, useSynchronizationContext: false);
|
||||
var pair = DuplexPipe.CreateConnectionPair(options, options);
|
||||
|
||||
var serviceContext = new ServiceContext
|
||||
{
|
||||
|
|
|
|||
|
|
@ -16,7 +16,8 @@
|
|||
<MicrosoftAspNetCoreHttpPackageVersion>2.1.0-preview2-30272</MicrosoftAspNetCoreHttpPackageVersion>
|
||||
<MicrosoftAspNetCoreTestingPackageVersion>2.1.0-preview2-30272</MicrosoftAspNetCoreTestingPackageVersion>
|
||||
<MicrosoftAspNetCoreWebUtilitiesPackageVersion>2.1.0-preview2-30272</MicrosoftAspNetCoreWebUtilitiesPackageVersion>
|
||||
<MicrosoftExtensionsBuffersSourcesPackageVersion>2.1.0-preview2-30272</MicrosoftExtensionsBuffersSourcesPackageVersion>
|
||||
<MicrosoftExtensionsBuffersSourcesPackageVersion>2.1.0-preview2-pk-corefx0-16426</MicrosoftExtensionsBuffersSourcesPackageVersion>
|
||||
<MicrosoftExtensionsBuffersSourcesTestingPackageVersion>2.1.0-preview2-pk-corefx0-16426</MicrosoftExtensionsBuffersSourcesTestingPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationBinderPackageVersion>2.1.0-preview2-30272</MicrosoftExtensionsConfigurationBinderPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationJsonPackageVersion>2.1.0-preview2-30272</MicrosoftExtensionsConfigurationJsonPackageVersion>
|
||||
<MicrosoftExtensionsDependencyInjectionPackageVersion>2.1.0-preview2-30272</MicrosoftExtensionsDependencyInjectionPackageVersion>
|
||||
|
|
@ -26,18 +27,18 @@
|
|||
<MicrosoftExtensionsLoggingTestingPackageVersion>2.1.0-preview2-30272</MicrosoftExtensionsLoggingTestingPackageVersion>
|
||||
<MicrosoftExtensionsOptionsPackageVersion>2.1.0-preview2-30272</MicrosoftExtensionsOptionsPackageVersion>
|
||||
<MicrosoftNETCoreApp20PackageVersion>2.0.0</MicrosoftNETCoreApp20PackageVersion>
|
||||
<MicrosoftNETCoreApp21PackageVersion>2.1.0-preview2-26225-03</MicrosoftNETCoreApp21PackageVersion>
|
||||
<MicrosoftNETCoreApp21PackageVersion>2.1.0-preview2-26308-01</MicrosoftNETCoreApp21PackageVersion>
|
||||
<MicrosoftNetHttpHeadersPackageVersion>2.1.0-preview2-30272</MicrosoftNetHttpHeadersPackageVersion>
|
||||
<MicrosoftNETTestSdkPackageVersion>15.6.0</MicrosoftNETTestSdkPackageVersion>
|
||||
<MoqPackageVersion>4.7.49</MoqPackageVersion>
|
||||
<NewtonsoftJsonPackageVersion>10.0.1</NewtonsoftJsonPackageVersion>
|
||||
<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>
|
||||
<SystemBuffersPackageVersion>4.5.0-preview2-26308-02</SystemBuffersPackageVersion>
|
||||
<SystemIOPipelinesPackageVersion>4.5.0-preview2-26308-02</SystemIOPipelinesPackageVersion>
|
||||
<SystemMemoryPackageVersion>4.5.0-preview2-26308-02</SystemMemoryPackageVersion>
|
||||
<SystemNumericsVectorsPackageVersion>4.5.0-preview2-26308-02</SystemNumericsVectorsPackageVersion>
|
||||
<SystemRuntimeCompilerServicesUnsafePackageVersion>4.5.0-preview2-26308-02</SystemRuntimeCompilerServicesUnsafePackageVersion>
|
||||
<SystemSecurityCryptographyCngPackageVersion>4.5.0-preview2-26308-02</SystemSecurityCryptographyCngPackageVersion>
|
||||
<SystemThreadingTasksExtensionsPackageVersion>4.5.0-preview2-26308-02</SystemThreadingTasksExtensionsPackageVersion>
|
||||
<XunitAnalyzersPackageVersion>0.8.0</XunitAnalyzersPackageVersion>
|
||||
<XunitPackageVersion>2.3.1</XunitPackageVersion>
|
||||
<XunitRunnerVisualStudioPackageVersion>2.4.0-beta.1.build3945</XunitRunnerVisualStudioPackageVersion>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
<Project>
|
||||
<Import Project="..\Directory.Build.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<DefineConstants Condition="'$(InnerLoop)' != ''">$(DefineConstants);INNER_LOOP</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Internal.AspNetCore.Sdk" PrivateAssets="All" Version="$(InternalAspNetCoreSdkPackageVersion)" />
|
||||
</ItemGroup>
|
||||
|
|
|
|||
|
|
@ -139,7 +139,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Adapter.Internal
|
|||
}
|
||||
|
||||
#if NETCOREAPP2_1
|
||||
public override Task WriteAsync(ReadOnlyMemory<byte> source, CancellationToken cancellationToken = default)
|
||||
public override ValueTask WriteAsync(ReadOnlyMemory<byte> source, CancellationToken cancellationToken = default)
|
||||
{
|
||||
Log("WriteAsync", source.Span);
|
||||
return _inner.WriteAsync(source, cancellationToken);
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Adapter.Internal
|
|||
}
|
||||
|
||||
#if NETCOREAPP2_1
|
||||
public override async Task WriteAsync(ReadOnlyMemory<byte> source, CancellationToken cancellationToken = default)
|
||||
public override async ValueTask WriteAsync(ReadOnlyMemory<byte> source, CancellationToken cancellationToken = default)
|
||||
{
|
||||
_output.Write(source.Span);
|
||||
await _output.FlushAsync(cancellationToken);
|
||||
|
|
|
|||
|
|
@ -89,7 +89,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
|
|||
readerScheduler: serviceContext.ThreadPool,
|
||||
writerScheduler: writerScheduler,
|
||||
pauseWriterThreshold: serviceContext.ServerOptions.Limits.MaxRequestBufferSize ?? 0,
|
||||
resumeWriterThreshold: serviceContext.ServerOptions.Limits.MaxRequestBufferSize ?? 0
|
||||
resumeWriterThreshold: serviceContext.ServerOptions.Limits.MaxRequestBufferSize ?? 0,
|
||||
useSynchronizationContext: false
|
||||
);
|
||||
|
||||
internal static PipeOptions GetOutputPipeOptions(ServiceContext serviceContext, MemoryPool<byte> memoryPool, PipeScheduler readerScheduler) => new PipeOptions
|
||||
|
|
@ -98,7 +99,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
|
|||
readerScheduler: readerScheduler,
|
||||
writerScheduler: serviceContext.ThreadPool,
|
||||
pauseWriterThreshold: GetOutputResponseBufferSize(serviceContext),
|
||||
resumeWriterThreshold: GetOutputResponseBufferSize(serviceContext)
|
||||
resumeWriterThreshold: GetOutputResponseBufferSize(serviceContext),
|
||||
useSynchronizationContext: false
|
||||
);
|
||||
|
||||
private static long GetOutputResponseBufferSize(ServiceContext serviceContext)
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ using System.Runtime.InteropServices;
|
|||
using System.Text;
|
||||
using System.Text.Encodings.Web;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
using Microsoft.AspNetCore.Protocols.Abstractions;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
|
||||
|
|
@ -429,7 +430,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
TimeoutControl.SetTimeout(_keepAliveTicks, TimeoutAction.StopProcessingNextRequest);
|
||||
}
|
||||
|
||||
protected override bool BeginRead(out PipeAwaiter<ReadResult> awaitable)
|
||||
protected override bool BeginRead(out ValueTask<ReadResult> awaitable)
|
||||
{
|
||||
awaitable = Input.ReadAsync();
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -93,12 +93,13 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
BadHttpRequestException.Throw(RequestRejectionReason.UnexpectedEndOfRequestContent);
|
||||
}
|
||||
|
||||
awaitable = _context.Input.ReadAsync();
|
||||
}
|
||||
finally
|
||||
{
|
||||
_context.Input.AdvanceTo(consumed, examined);
|
||||
}
|
||||
|
||||
awaitable = _context.Input.ReadAsync();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
|
@ -320,7 +321,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var actual = (int)Math.Min(readableBuffer.Length, _inputLength);
|
||||
_inputLength -= actual;
|
||||
|
||||
consumed = readableBuffer.GetPosition(readableBuffer.Start, actual);
|
||||
consumed = readableBuffer.GetPosition(actual);
|
||||
examined = consumed;
|
||||
|
||||
Copy(readableBuffer.Slice(0, actual), writableBuffer);
|
||||
|
|
@ -561,7 +562,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
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);
|
||||
consumed = buffer.GetPosition(actual);
|
||||
examined = consumed;
|
||||
|
||||
Copy(buffer.Slice(0, actual), writableBuffer);
|
||||
|
|
|
|||
|
|
@ -38,6 +38,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
private readonly object _flushLock = new object();
|
||||
private Action _flushCompleted;
|
||||
|
||||
private ValueTask<FlushResult> _flushTask;
|
||||
|
||||
public Http1OutputProducer(
|
||||
PipeReader outputPipeReader,
|
||||
PipeWriter pipeWriter,
|
||||
|
|
@ -200,7 +202,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
return FlushAsyncAwaited(awaitable, bytesWritten, cancellationToken);
|
||||
}
|
||||
|
||||
private async Task FlushAsyncAwaited(PipeAwaiter<FlushResult> awaitable, long count, CancellationToken cancellationToken)
|
||||
private async Task FlushAsyncAwaited(ValueTask<FlushResult> awaitable, long count, CancellationToken cancellationToken)
|
||||
{
|
||||
// https://github.com/dotnet/corefxlab/issues/1334
|
||||
// Since the flush awaitable doesn't currently support multiple awaiters
|
||||
|
|
@ -208,24 +210,47 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
// All awaiters get the same task
|
||||
lock (_flushLock)
|
||||
{
|
||||
_flushTask = awaitable;
|
||||
if (_flushTcs == null || _flushTcs.Task.IsCompleted)
|
||||
{
|
||||
_flushTcs = new TaskCompletionSource<object>();
|
||||
|
||||
awaitable.OnCompleted(_flushCompleted);
|
||||
_flushTask.GetAwaiter().OnCompleted(_flushCompleted);
|
||||
}
|
||||
}
|
||||
|
||||
_timeoutControl.StartTimingWrite(count);
|
||||
await _flushTcs.Task;
|
||||
_timeoutControl.StopTimingWrite();
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
try
|
||||
{
|
||||
await _flushTcs.Task;
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
_completed = true;
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_timeoutControl.StopTimingWrite();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnFlushCompleted()
|
||||
{
|
||||
_flushTcs.TrySetResult(null);
|
||||
try
|
||||
{
|
||||
_flushTask.GetAwaiter().GetResult();
|
||||
_flushTcs.TrySetResult(null);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
_flushTcs.TrySetResult(exception);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_flushTask = default;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var lineIndex = span.IndexOf(ByteLF);
|
||||
if (lineIndex >= 0)
|
||||
{
|
||||
consumed = buffer.GetPosition(consumed, lineIndex + 1);
|
||||
consumed = buffer.GetPosition(lineIndex + 1, consumed);
|
||||
span = span.Slice(0, lineIndex + 1);
|
||||
}
|
||||
else if (buffer.IsSingleSegment)
|
||||
|
|
@ -293,7 +293,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var lineEnd = lineEndPosition.Value;
|
||||
|
||||
// Make sure LF is included in lineEnd
|
||||
lineEnd = buffer.GetPosition(lineEnd, 1);
|
||||
lineEnd = buffer.GetPosition(1, lineEnd);
|
||||
var headerSpan = buffer.Slice(current, lineEnd).ToSpan();
|
||||
length = headerSpan.Length;
|
||||
|
||||
|
|
@ -425,7 +425,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
if (byteLfPosition != null)
|
||||
{
|
||||
// Move 1 byte past the \n
|
||||
found = buffer.GetPosition(byteLfPosition.Value, 1);
|
||||
found = buffer.GetPosition(1, byteLfPosition.Value);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -383,7 +383,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
{
|
||||
}
|
||||
|
||||
protected virtual bool BeginRead(out PipeAwaiter<ReadResult> awaitable)
|
||||
protected virtual bool BeginRead(out ValueTask<ReadResult> awaitable)
|
||||
{
|
||||
awaitable = default;
|
||||
return false;
|
||||
|
|
@ -1336,7 +1336,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
readerScheduler: ServiceContext.ThreadPool,
|
||||
writerScheduler: PipeScheduler.Inline,
|
||||
pauseWriterThreshold: 1,
|
||||
resumeWriterThreshold: 1
|
||||
resumeWriterThreshold: 1,
|
||||
useSynchronizationContext: false
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -112,11 +112,11 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
}
|
||||
|
||||
#if NETCOREAPP2_1
|
||||
public override Task WriteAsync(ReadOnlyMemory<byte> source, CancellationToken cancellationToken = default)
|
||||
public override ValueTask WriteAsync(ReadOnlyMemory<byte> source, CancellationToken cancellationToken = default)
|
||||
{
|
||||
ValidateState(cancellationToken);
|
||||
|
||||
return _httpResponseControl.WriteAsync(source, cancellationToken);
|
||||
return new ValueTask(_httpResponseControl.WriteAsync(source, cancellationToken));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
// buffer.Count is int
|
||||
var actual = (int) Math.Min(readableBuffer.Length, buffer.Length);
|
||||
var slice = readableBuffer.Slice(0, actual);
|
||||
consumed = readableBuffer.GetPosition(readableBuffer.Start, actual);
|
||||
consumed = readableBuffer.GetPosition(actual);
|
||||
slice.CopyTo(buffer.Span);
|
||||
return actual;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,12 +28,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
|
||||
public static ArraySegment<byte> GetArray(this Memory<byte> buffer)
|
||||
{
|
||||
ArraySegment<byte> result;
|
||||
if (!buffer.TryGetArray(out result))
|
||||
{
|
||||
throw new InvalidOperationException("Buffer backed by array was expected");
|
||||
}
|
||||
return result;
|
||||
return ((ReadOnlyMemory<byte>)buffer).GetArray();
|
||||
}
|
||||
|
||||
public static ArraySegment<byte> GetArray(this ReadOnlyMemory<byte> memory)
|
||||
|
|
|
|||
|
|
@ -237,7 +237,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
|
|||
}
|
||||
}
|
||||
|
||||
consumed = examined = readableBuffer.GetPosition(readableBuffer.Start, ClientPreface.Length);
|
||||
consumed = examined = readableBuffer.GetPosition(ClientPreface.Length);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
|
|||
}
|
||||
|
||||
readableBuffer.Slice(Http2Frame.HeaderLength, frame.Length).CopyTo(frame.Payload);
|
||||
consumed = examined = readableBuffer.GetPosition(readableBuffer.Start, Http2Frame.HeaderLength + frame.Length);
|
||||
consumed = examined = readableBuffer.GetPosition(Http2Frame.HeaderLength + frame.Length);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -77,7 +77,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
|
|||
readerScheduler: _context.ServiceContext.ThreadPool,
|
||||
writerScheduler: PipeScheduler.Inline,
|
||||
pauseWriterThreshold: _context.ServiceContext.ServerOptions.Limits.MaxRequestBufferSize ?? 0,
|
||||
resumeWriterThreshold: _context.ServiceContext.ServerOptions.Limits.MaxRequestBufferSize ?? 0
|
||||
resumeWriterThreshold: _context.ServiceContext.ServerOptions.Limits.MaxRequestBufferSize ?? 0,
|
||||
useSynchronizationContext: false
|
||||
);
|
||||
|
||||
internal PipeOptions AdaptedOutputPipeOptions => new PipeOptions
|
||||
|
|
@ -86,7 +87,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
|
|||
readerScheduler: PipeScheduler.Inline,
|
||||
writerScheduler: PipeScheduler.Inline,
|
||||
pauseWriterThreshold: _context.ServiceContext.ServerOptions.Limits.MaxResponseBufferSize ?? 0,
|
||||
resumeWriterThreshold: _context.ServiceContext.ServerOptions.Limits.MaxResponseBufferSize ?? 0
|
||||
resumeWriterThreshold: _context.ServiceContext.ServerOptions.Limits.MaxResponseBufferSize ?? 0,
|
||||
useSynchronizationContext: false
|
||||
);
|
||||
|
||||
private IKestrelTrace Log => _context.ServiceContext.Log;
|
||||
|
|
|
|||
|
|
@ -15,20 +15,27 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
|
|||
private readonly ISystemClock _systemClock;
|
||||
private readonly IDebugger _debugger;
|
||||
private readonly IKestrelTrace _trace;
|
||||
private readonly TimeSpan _interval;
|
||||
private Timer _timer;
|
||||
private int _executingOnHeartbeat;
|
||||
|
||||
public Heartbeat(IHeartbeatHandler[] callbacks, ISystemClock systemClock, IDebugger debugger, IKestrelTrace trace)
|
||||
public Heartbeat(IHeartbeatHandler[] callbacks, ISystemClock systemClock, IDebugger debugger, IKestrelTrace trace): this(callbacks, systemClock, debugger, trace, Interval)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
internal Heartbeat(IHeartbeatHandler[] callbacks, ISystemClock systemClock, IDebugger debugger, IKestrelTrace trace, TimeSpan interval)
|
||||
{
|
||||
_callbacks = callbacks;
|
||||
_systemClock = systemClock;
|
||||
_debugger = debugger;
|
||||
_trace = trace;
|
||||
_interval = interval;
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
_timer = new Timer(OnHeartbeat, state: this, dueTime: Interval, period: Interval);
|
||||
_timer = new Timer(OnHeartbeat, state: this, dueTime: _interval, period: _interval);
|
||||
}
|
||||
|
||||
private static void OnHeartbeat(object state)
|
||||
|
|
@ -63,7 +70,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
|
|||
{
|
||||
if (!_debugger.IsAttached)
|
||||
{
|
||||
_trace.HeartbeatSlow(Interval, now);
|
||||
_trace.HeartbeatSlow(_interval, now);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,12 +33,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
|
|||
action(state);
|
||||
}
|
||||
|
||||
public override void Schedule(Action action)
|
||||
{
|
||||
Run(action);
|
||||
}
|
||||
|
||||
public override void Schedule(Action<object> action, object state)
|
||||
public override void Schedule<T>(Action<T> action, T state)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
|
|
|||
|
|
@ -50,12 +50,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
|
|||
System.Threading.ThreadPool.QueueUserWorkItem(action, state);
|
||||
}
|
||||
|
||||
public override void Schedule(Action action)
|
||||
{
|
||||
Run(action);
|
||||
}
|
||||
|
||||
public override void Schedule(Action<object> action, object state)
|
||||
public override void Schedule<T>(Action<T> action, T state)
|
||||
{
|
||||
Run(() => action(state));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -173,7 +173,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
|||
_bufferHandle.Dispose();
|
||||
}
|
||||
|
||||
private async Task ApplyBackpressureAsync(PipeAwaiter<FlushResult> flushTask)
|
||||
private async Task ApplyBackpressureAsync(ValueTask<FlushResult> flushTask)
|
||||
{
|
||||
Log.ConnectionPause(ConnectionId);
|
||||
_socket.ReadStop();
|
||||
|
|
|
|||
|
|
@ -48,8 +48,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
|||
_log = transport.Log;
|
||||
_loop = new UvLoopHandle(_log);
|
||||
_post = new UvAsyncHandle(_log);
|
||||
|
||||
_thread = new Thread(ThreadStart);
|
||||
#if !INNER_LOOP
|
||||
_thread.Name = nameof(LibuvThread);
|
||||
#endif
|
||||
|
||||
#if !DEBUG
|
||||
// Mark the thread as being as unimportant to keeping the process alive.
|
||||
// Don't do this for debug builds, so we know if the thread isn't terminating.
|
||||
|
|
@ -132,7 +136,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
|||
_closeError?.Throw();
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
#if DEBUG && !INNER_LOOP
|
||||
private void CheckUvReqLeaks()
|
||||
{
|
||||
GC.Collect();
|
||||
|
|
@ -177,6 +181,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
|||
{
|
||||
CallbackAdapter = CallbackAdapter<T>.PostCallbackAdapter,
|
||||
Callback = callback,
|
||||
//TODO: This boxes
|
||||
State = state
|
||||
};
|
||||
|
||||
|
|
@ -301,7 +306,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
|||
WriteReqPool.Dispose();
|
||||
_threadTcs.SetResult(null);
|
||||
|
||||
#if DEBUG
|
||||
#if DEBUG && !INNER_LOOP
|
||||
// Check for handle leaks after disposing everything
|
||||
CheckUvReqLeaks();
|
||||
#endif
|
||||
|
|
@ -391,12 +396,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
|||
return await Task.WhenAny(task, Task.Delay(timeout)).ConfigureAwait(false) == task;
|
||||
}
|
||||
|
||||
public override void Schedule(Action action)
|
||||
{
|
||||
Post(state => state(), action);
|
||||
}
|
||||
|
||||
public override void Schedule(Action<object> action, object state)
|
||||
public override void Schedule<T>(Action<T> action, T state)
|
||||
{
|
||||
Post(action, state);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networkin
|
|||
{
|
||||
_uv = uv;
|
||||
ThreadId = threadId;
|
||||
|
||||
|
||||
handle = Marshal.AllocCoTaskMem(size);
|
||||
*(IntPtr*)handle = GCHandle.ToIntPtr(GCHandle.Alloc(this, _handleType));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv
|
|||
}
|
||||
|
||||
Threads.Clear();
|
||||
#if DEBUG
|
||||
#if DEBUG && !INNER_LOOP
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
GC.Collect();
|
||||
|
|
|
|||
|
|
@ -10,11 +10,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal
|
|||
{
|
||||
public static ArraySegment<byte> GetArray(this Memory<byte> memory)
|
||||
{
|
||||
if (!memory.TryGetArray(out var result))
|
||||
{
|
||||
throw new InvalidOperationException("Buffer backed by array was expected");
|
||||
}
|
||||
return result;
|
||||
return ((ReadOnlyMemory<byte>)memory).GetArray();
|
||||
}
|
||||
|
||||
public static ArraySegment<byte> GetArray(this ReadOnlyMemory<byte> memory)
|
||||
|
|
|
|||
|
|
@ -18,11 +18,6 @@ namespace System.IO.Pipelines
|
|||
{
|
||||
}
|
||||
|
||||
public static DuplexPipePair CreateConnectionPair(MemoryPool<byte> memoryPool)
|
||||
{
|
||||
return CreateConnectionPair(new PipeOptions(memoryPool), new PipeOptions(memoryPool));
|
||||
}
|
||||
|
||||
public static DuplexPipePair CreateConnectionPair(PipeOptions inputOptions, PipeOptions outputOptions)
|
||||
{
|
||||
var input = new Pipe(inputOptions);
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
|
||||
using Xunit;
|
||||
|
||||
|
|
@ -41,7 +42,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
[InlineData(0x80)]
|
||||
private void ExceptionThrownForZeroOrNonAscii(byte b)
|
||||
{
|
||||
for (var length = 1; length < 1024; length++)
|
||||
for (var length = 1; length < Vector<sbyte>.Count * 4; length++)
|
||||
{
|
||||
for (var position = 0; position < length; position++)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -65,11 +65,11 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
debugger.Setup(d => d.IsAttached).Returns(true);
|
||||
kestrelTrace.Setup(t => t.HeartbeatSlow(Heartbeat.Interval, systemClock.UtcNow)).Callback(() => traceMre.Set());
|
||||
|
||||
using (var heartbeat = new Heartbeat(new[] { heartbeatHandler.Object }, systemClock, debugger.Object, kestrelTrace.Object))
|
||||
using (var heartbeat = new Heartbeat(new[] { heartbeatHandler.Object }, systemClock, debugger.Object, kestrelTrace.Object, TimeSpan.FromSeconds(0.01)))
|
||||
{
|
||||
onHeartbeatTasks[0] = Task.Run(() => heartbeat.OnHeartbeat());
|
||||
onHeartbeatTasks[1] = Task.Run(() => heartbeat.OnHeartbeat());
|
||||
Assert.False(traceMre.Wait(TimeSpan.FromSeconds(10)));
|
||||
Assert.False(traceMre.Wait(TimeSpan.FromSeconds(2)));
|
||||
}
|
||||
|
||||
handlerMre.Set();
|
||||
|
|
|
|||
|
|
@ -41,7 +41,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
public Http1ConnectionTests()
|
||||
{
|
||||
_pipelineFactory = KestrelMemoryPool.Create();
|
||||
var pair = DuplexPipe.CreateConnectionPair(_pipelineFactory);
|
||||
var options = new PipeOptions(_pipelineFactory, readerScheduler: PipeScheduler.Inline, writerScheduler: PipeScheduler.Inline, useSynchronizationContext: false);
|
||||
var pair = DuplexPipe.CreateConnectionPair(options, options);
|
||||
|
||||
_transport = pair.Transport;
|
||||
_application = pair.Application;
|
||||
|
|
|
|||
|
|
@ -126,7 +126,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
var inlineSchedulingPipeOptions = new PipeOptions(
|
||||
pool: _memoryPool,
|
||||
readerScheduler: PipeScheduler.Inline,
|
||||
writerScheduler: PipeScheduler.Inline
|
||||
writerScheduler: PipeScheduler.Inline,
|
||||
useSynchronizationContext: false
|
||||
);
|
||||
|
||||
_pair = DuplexPipe.CreateConnectionPair(inlineSchedulingPipeOptions, inlineSchedulingPipeOptions);
|
||||
|
|
|
|||
|
|
@ -26,7 +26,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
public HttpConnectionTests()
|
||||
{
|
||||
_memoryPool = KestrelMemoryPool.Create();
|
||||
var pair = DuplexPipe.CreateConnectionPair(_memoryPool);
|
||||
var options = new PipeOptions(_memoryPool, readerScheduler: PipeScheduler.Inline, writerScheduler: PipeScheduler.Inline, useSynchronizationContext: false);
|
||||
var pair = DuplexPipe.CreateConnectionPair(options, options);
|
||||
|
||||
_httpConnectionContext = new HttpConnectionContext
|
||||
{
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
{
|
||||
public class HttpParserTests
|
||||
{
|
||||
private static IKestrelTrace _nullTrace = Mock.Of<IKestrelTrace>();
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RequestLineValidData))]
|
||||
public void ParsesRequestLine(
|
||||
|
|
@ -33,7 +35,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
#pragma warning restore xUnit1026
|
||||
string expectedVersion)
|
||||
{
|
||||
var parser = CreateParser(Mock.Of<IKestrelTrace>());
|
||||
var parser = CreateParser(_nullTrace);
|
||||
var buffer = new ReadOnlySequence<byte>(Encoding.ASCII.GetBytes(requestLine));
|
||||
var requestHandler = new RequestHandler();
|
||||
|
||||
|
|
@ -52,7 +54,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
[MemberData(nameof(RequestLineIncompleteData))]
|
||||
public void ParseRequestLineReturnsFalseWhenGivenIncompleteRequestLines(string requestLine)
|
||||
{
|
||||
var parser = CreateParser(Mock.Of<IKestrelTrace>());
|
||||
var parser = CreateParser(_nullTrace);
|
||||
var buffer = new ReadOnlySequence<byte>(Encoding.ASCII.GetBytes(requestLine));
|
||||
var requestHandler = new RequestHandler();
|
||||
|
||||
|
|
@ -63,7 +65,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
[MemberData(nameof(RequestLineIncompleteData))]
|
||||
public void ParseRequestLineDoesNotConsumeIncompleteRequestLine(string requestLine)
|
||||
{
|
||||
var parser = CreateParser(Mock.Of<IKestrelTrace>());
|
||||
var parser = CreateParser(_nullTrace);
|
||||
var buffer = new ReadOnlySequence<byte>(Encoding.ASCII.GetBytes(requestLine));
|
||||
var requestHandler = new RequestHandler();
|
||||
|
||||
|
|
@ -176,7 +178,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
[InlineData("Header-1: value1\r\nHeader-2: value2\r\n\r")]
|
||||
public void ParseHeadersReturnsFalseWhenGivenIncompleteHeaders(string rawHeaders)
|
||||
{
|
||||
var parser = CreateParser(Mock.Of<IKestrelTrace>());
|
||||
var parser = CreateParser(_nullTrace);
|
||||
|
||||
var buffer = new ReadOnlySequence<byte>(Encoding.ASCII.GetBytes(rawHeaders));
|
||||
var requestHandler = new RequestHandler();
|
||||
|
|
@ -201,7 +203,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
[InlineData("Header: value\r")]
|
||||
public void ParseHeadersDoesNotConsumeIncompleteHeader(string rawHeaders)
|
||||
{
|
||||
var parser = CreateParser(Mock.Of<IKestrelTrace>());
|
||||
var parser = CreateParser(_nullTrace);
|
||||
|
||||
var buffer = new ReadOnlySequence<byte>(Encoding.ASCII.GetBytes(rawHeaders));
|
||||
var requestHandler = new RequestHandler();
|
||||
|
|
@ -290,14 +292,14 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
[Fact]
|
||||
public void ParseHeadersConsumesBytesCorrectlyAtEnd()
|
||||
{
|
||||
var parser = CreateParser(Mock.Of<IKestrelTrace>());
|
||||
var parser = CreateParser(_nullTrace);
|
||||
|
||||
const string headerLine = "Header: value\r\n\r";
|
||||
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));
|
||||
|
||||
Assert.Equal(buffer1.GetPosition(buffer1.Start, headerLine.Length - 1), consumed);
|
||||
Assert.Equal(buffer1.GetPosition(headerLine.Length - 1), consumed);
|
||||
Assert.Equal(buffer1.End, examined);
|
||||
Assert.Equal(headerLine.Length - 1, consumedBytes);
|
||||
|
||||
|
|
@ -371,8 +373,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
[Fact]
|
||||
public void ParseRequestLineSplitBufferWithoutNewLineDoesNotUpdateConsumed()
|
||||
{
|
||||
var parser = CreateParser(Mock.Of<IKestrelTrace>());
|
||||
var buffer = CreateBuffer("GET ", "/");
|
||||
var parser = CreateParser(_nullTrace);
|
||||
var buffer = ReadOnlySequenceFactory.CreateSegments(
|
||||
Encoding.ASCII.GetBytes("GET "),
|
||||
Encoding.ASCII.GetBytes("/"));
|
||||
|
||||
var requestHandler = new RequestHandler();
|
||||
var result = parser.ParseRequestLine(requestHandler, buffer, out var consumed, out var examined);
|
||||
|
|
@ -387,7 +391,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
string rawHeaderValue,
|
||||
string expectedHeaderValue)
|
||||
{
|
||||
var parser = CreateParser(Mock.Of<IKestrelTrace>());
|
||||
var parser = CreateParser(_nullTrace);
|
||||
var buffer = new ReadOnlySequence<byte>(Encoding.ASCII.GetBytes($"{headerName}:{rawHeaderValue}\r\n"));
|
||||
|
||||
var requestHandler = new RequestHandler();
|
||||
|
|
@ -405,7 +409,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 parser = CreateParser(_nullTrace);
|
||||
var buffer = new ReadOnlySequence<byte>(Encoding.ASCII.GetBytes(rawHeaders));
|
||||
|
||||
var requestHandler = new RequestHandler();
|
||||
|
|
@ -465,86 +469,5 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
PathEncoded = pathEncoded;
|
||||
}
|
||||
}
|
||||
|
||||
private static ReadOnlySequence<byte> CreateBuffer(params string[] inputs)
|
||||
{
|
||||
var buffers = new byte[inputs.Length][];
|
||||
for (int i = 0; i < inputs.Length; i++)
|
||||
{
|
||||
buffers[i] = Encoding.UTF8.GetBytes(inputs[i]);
|
||||
}
|
||||
return CreateBuffer(buffers);
|
||||
}
|
||||
|
||||
// Copied from https://github.com/dotnet/corefx/blob/master/src/System.Memory/tests/ReadOnlyBuffer/ReadOnlySequenceFactory.cs
|
||||
private static ReadOnlySequence<byte> CreateBuffer(params byte[][] inputs)
|
||||
{
|
||||
if (inputs == null || inputs.Length == 0)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
|
||||
BufferSegment last = null;
|
||||
BufferSegment first = null;
|
||||
|
||||
do
|
||||
{
|
||||
byte[] s = inputs[i];
|
||||
int length = s.Length;
|
||||
int dataOffset = length;
|
||||
var chars = new byte[length * 2];
|
||||
|
||||
for (int j = 0; j < length; j++)
|
||||
{
|
||||
chars[dataOffset + j] = s[j];
|
||||
}
|
||||
|
||||
// Create a segment that has offset relative to the OwnedMemory and OwnedMemory itself has offset relative to array
|
||||
var memory = new Memory<byte>(chars).Slice(length, length);
|
||||
|
||||
if (first == null)
|
||||
{
|
||||
first = new BufferSegment(memory);
|
||||
last = first;
|
||||
}
|
||||
else
|
||||
{
|
||||
last = last.Append(memory);
|
||||
}
|
||||
i++;
|
||||
} while (i < inputs.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
|
||||
private class BufferSegment : IMemoryList<byte>
|
||||
{
|
||||
public BufferSegment(Memory<byte> memory)
|
||||
{
|
||||
Memory = memory;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Combined length of all segments before this
|
||||
/// </summary>
|
||||
public long RunningIndex { get; private set; }
|
||||
|
||||
public Memory<byte> Memory { get; set; }
|
||||
|
||||
public IMemoryList<byte> Next { get; private set; }
|
||||
|
||||
public BufferSegment Append(Memory<byte> memory)
|
||||
{
|
||||
var segment = new BufferSegment(memory)
|
||||
{
|
||||
RunningIndex = RunningIndex + Memory.Length
|
||||
};
|
||||
Next = segment;
|
||||
return segment;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,15 +24,16 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
private readonly TestHttp1Connection _http1Connection;
|
||||
private readonly ServiceContext _serviceContext;
|
||||
private readonly Http1ConnectionContext _http1ConnectionContext;
|
||||
private readonly MemoryPool<byte> _pipelineFactory;
|
||||
private readonly MemoryPool<byte> _memoryPool;
|
||||
private Mock<ITimeoutControl> _timeoutControl;
|
||||
|
||||
private readonly IFeatureCollection _collection;
|
||||
|
||||
public HttpProtocolFeatureCollectionTests()
|
||||
{
|
||||
_pipelineFactory = KestrelMemoryPool.Create();
|
||||
var pair = DuplexPipe.CreateConnectionPair(_pipelineFactory);
|
||||
_memoryPool = KestrelMemoryPool.Create();
|
||||
var options = new PipeOptions(_memoryPool, readerScheduler: PipeScheduler.Inline, writerScheduler: PipeScheduler.Inline, useSynchronizationContext: false);
|
||||
var pair = DuplexPipe.CreateConnectionPair(options, options);
|
||||
|
||||
_transport = pair.Transport;
|
||||
_application = pair.Application;
|
||||
|
|
@ -43,7 +44,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
{
|
||||
ServiceContext = _serviceContext,
|
||||
ConnectionFeatures = new FeatureCollection(),
|
||||
MemoryPool = _pipelineFactory,
|
||||
MemoryPool = _memoryPool,
|
||||
TimeoutControl = _timeoutControl.Object,
|
||||
Application = pair.Application,
|
||||
Transport = pair.Transport
|
||||
|
|
@ -62,7 +63,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
_application.Input.Complete();
|
||||
_application.Output.Complete();
|
||||
|
||||
_pipelineFactory.Dispose();
|
||||
_memoryPool.Dispose();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
|
|||
|
|
@ -23,7 +23,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
{
|
||||
using (var memoryPool = KestrelMemoryPool.Create())
|
||||
{
|
||||
var pair = DuplexPipe.CreateConnectionPair(memoryPool);
|
||||
var options = new PipeOptions(memoryPool, readerScheduler: PipeScheduler.Inline, writerScheduler: PipeScheduler.Inline, useSynchronizationContext: false);
|
||||
var pair = DuplexPipe.CreateConnectionPair(options, options);
|
||||
var http1ConnectionContext = new Http1ConnectionContext
|
||||
{
|
||||
ServiceContext = new TestServiceContext(),
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
<PackageReference Include="Microsoft.AspNetCore.Http" Version="$(MicrosoftAspNetCoreHttpPackageVersion)" />
|
||||
<PackageReference Include="System.Memory" Version="$(SystemMemoryPackageVersion)" />
|
||||
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="$(SystemRuntimeCompilerServicesUnsafePackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.Buffers.Testing.Sources" Version="$(MicrosoftExtensionsBuffersSourcesTestingPackageVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -35,7 +35,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
(
|
||||
pool: _memoryPool,
|
||||
readerScheduler: Mock.Of<PipeScheduler>(),
|
||||
writerScheduler: PipeScheduler.Inline
|
||||
writerScheduler: PipeScheduler.Inline,
|
||||
useSynchronizationContext: false
|
||||
);
|
||||
|
||||
using (var socketOutput = CreateOutputProducer(pipeOptions))
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
|
||||
public PipelineExtensionTests()
|
||||
{
|
||||
_pipe = new Pipe(new PipeOptions(_memoryPool, readerScheduler: PipeScheduler.Inline, writerScheduler: PipeScheduler.Inline));
|
||||
_pipe = new Pipe(new PipeOptions(_memoryPool, readerScheduler: PipeScheduler.Inline, writerScheduler: PipeScheduler.Inline, useSynchronizationContext: false));
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
public TestInput()
|
||||
{
|
||||
_memoryPool = KestrelMemoryPool.Create();
|
||||
var options = new PipeOptions(pool: _memoryPool, readerScheduler: PipeScheduler.Inline, writerScheduler: PipeScheduler.Inline);
|
||||
var options = new PipeOptions(pool: _memoryPool, readerScheduler: PipeScheduler.Inline, writerScheduler: PipeScheduler.Inline, useSynchronizationContext: false);
|
||||
var pair = DuplexPipe.CreateConnectionPair(options, options);
|
||||
Transport = pair.Transport;
|
||||
Application = pair.Application;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// 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.
|
||||
|
||||
#if !INNER_LOOP
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
|
|
@ -252,3 +252,4 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
@ -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.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Reflection;
|
||||
|
|
@ -11,9 +12,11 @@ using Microsoft.AspNetCore.Hosting;
|
|||
using Microsoft.AspNetCore.Hosting.Server;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
|
||||
using Microsoft.AspNetCore.Testing;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
||||
|
|
@ -68,7 +71,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
|||
}
|
||||
return new KestrelServer(sp.GetRequiredService<ITransportFactory>(), context);
|
||||
});
|
||||
|
||||
RemoveDevCert(services);
|
||||
configureServices(services);
|
||||
})
|
||||
.UseSetting(WebHostDefaults.ApplicationKey, typeof(TestServer).GetTypeInfo().Assembly.FullName)
|
||||
|
|
@ -77,6 +80,19 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
|||
_host.Start();
|
||||
}
|
||||
|
||||
public static void RemoveDevCert(IServiceCollection services)
|
||||
{
|
||||
// KestrelServerOptionsSetup would scan all system certificates on every test server creation
|
||||
// making test runs very slow
|
||||
foreach (var descriptor in services.ToArray())
|
||||
{
|
||||
if (descriptor.ImplementationType == typeof(KestrelServerOptionsSetup))
|
||||
{
|
||||
services.Remove(descriptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public IPEndPoint EndPoint => _listenOptions.IPEndPoint;
|
||||
public int Port => _listenOptions.IPEndPoint.Port;
|
||||
public AddressFamily AddressFamily => _listenOptions.IPEndPoint.AddressFamily;
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
|||
{
|
||||
public static IWebHostBuilder GetWebHostBuilder()
|
||||
{
|
||||
return new WebHostBuilder().UseLibuv();
|
||||
return new WebHostBuilder().UseLibuv().ConfigureServices(TestServer.RemoveDevCert);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,11 +64,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
|||
pool: pool,
|
||||
pauseWriterThreshold: 3,
|
||||
readerScheduler: PipeScheduler.Inline,
|
||||
writerScheduler: PipeScheduler.Inline);
|
||||
writerScheduler: PipeScheduler.Inline,
|
||||
useSynchronizationContext: false);
|
||||
|
||||
// We don't set the output writer scheduler here since we want to run the callback inline
|
||||
|
||||
mockConnectionHandler.OutputOptions = pool => new PipeOptions(pool: pool, readerScheduler: thread, writerScheduler: PipeScheduler.Inline);
|
||||
mockConnectionHandler.OutputOptions = pool => new PipeOptions(pool: pool, readerScheduler: thread, writerScheduler: PipeScheduler.Inline, useSynchronizationContext: false);
|
||||
|
||||
|
||||
Task connectionTask = null;
|
||||
|
|
@ -121,9 +122,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
|||
var thread = new LibuvThread(transport);
|
||||
var mockScheduler = new Mock<PipeScheduler>();
|
||||
Action backPressure = null;
|
||||
mockScheduler.Setup(m => m.Schedule(It.IsAny<Action>())).Callback<Action>(a =>
|
||||
mockScheduler.Setup(m => m.Schedule(It.IsAny<Action<object>>(), It.IsAny<object>())).Callback<Action<object>, object>((a, o) =>
|
||||
{
|
||||
backPressure = a;
|
||||
backPressure = () => a(o);
|
||||
});
|
||||
mockConnectionHandler.InputOptions = pool =>
|
||||
new PipeOptions(
|
||||
|
|
@ -131,9 +132,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
|||
pauseWriterThreshold: 3,
|
||||
resumeWriterThreshold: 3,
|
||||
writerScheduler: mockScheduler.Object,
|
||||
readerScheduler: PipeScheduler.Inline);
|
||||
readerScheduler: PipeScheduler.Inline,
|
||||
useSynchronizationContext: false);
|
||||
|
||||
mockConnectionHandler.OutputOptions = pool => new PipeOptions(pool: pool, readerScheduler: thread, writerScheduler: PipeScheduler.Inline);
|
||||
mockConnectionHandler.OutputOptions = pool => new PipeOptions(pool: pool, readerScheduler: thread, writerScheduler: PipeScheduler.Inline, useSynchronizationContext: false);
|
||||
|
||||
Task connectionTask = null;
|
||||
try
|
||||
|
|
|
|||
|
|
@ -69,7 +69,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
|||
readerScheduler: _libuvThread,
|
||||
writerScheduler: PipeScheduler.Inline,
|
||||
pauseWriterThreshold: maxResponseBufferSize ?? 0,
|
||||
resumeWriterThreshold: maxResponseBufferSize ?? 0
|
||||
resumeWriterThreshold: maxResponseBufferSize ?? 0,
|
||||
useSynchronizationContext: false
|
||||
);
|
||||
|
||||
using (var outputProducer = CreateOutputProducer(pipeOptions))
|
||||
|
|
@ -106,7 +107,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
|||
readerScheduler: _libuvThread,
|
||||
writerScheduler: PipeScheduler.Inline,
|
||||
pauseWriterThreshold: 0,
|
||||
resumeWriterThreshold: 0
|
||||
resumeWriterThreshold: 0,
|
||||
useSynchronizationContext: false
|
||||
);
|
||||
|
||||
using (var outputProducer = CreateOutputProducer(pipeOptions))
|
||||
|
|
@ -155,7 +157,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
|||
readerScheduler: _libuvThread,
|
||||
writerScheduler: PipeScheduler.Inline,
|
||||
pauseWriterThreshold: 1,
|
||||
resumeWriterThreshold: 1
|
||||
resumeWriterThreshold: 1,
|
||||
useSynchronizationContext: false
|
||||
);
|
||||
|
||||
using (var outputProducer = CreateOutputProducer(pipeOptions))
|
||||
|
|
@ -212,7 +215,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
|||
readerScheduler: _libuvThread,
|
||||
writerScheduler: PipeScheduler.Inline,
|
||||
pauseWriterThreshold: maxResponseBufferSize,
|
||||
resumeWriterThreshold: maxResponseBufferSize
|
||||
resumeWriterThreshold: maxResponseBufferSize,
|
||||
useSynchronizationContext: false
|
||||
);
|
||||
|
||||
using (var outputProducer = CreateOutputProducer(pipeOptions))
|
||||
|
|
@ -277,7 +281,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
|||
readerScheduler: _libuvThread,
|
||||
writerScheduler: PipeScheduler.Inline,
|
||||
pauseWriterThreshold: maxResponseBufferSize,
|
||||
resumeWriterThreshold: maxResponseBufferSize
|
||||
resumeWriterThreshold: maxResponseBufferSize,
|
||||
useSynchronizationContext: false
|
||||
);
|
||||
|
||||
using (var outputProducer = CreateOutputProducer(pipeOptions))
|
||||
|
|
@ -348,7 +353,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
|||
readerScheduler: _libuvThread,
|
||||
writerScheduler: PipeScheduler.Inline,
|
||||
pauseWriterThreshold: maxResponseBufferSize,
|
||||
resumeWriterThreshold: maxResponseBufferSize
|
||||
resumeWriterThreshold: maxResponseBufferSize,
|
||||
useSynchronizationContext: false
|
||||
);
|
||||
|
||||
using (var outputProducer = CreateOutputProducer(pipeOptions, abortedSource))
|
||||
|
|
@ -442,7 +448,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
|||
readerScheduler: _libuvThread,
|
||||
writerScheduler: PipeScheduler.Inline,
|
||||
pauseWriterThreshold: maxResponseBufferSize,
|
||||
resumeWriterThreshold: maxResponseBufferSize
|
||||
resumeWriterThreshold: maxResponseBufferSize,
|
||||
useSynchronizationContext: false
|
||||
);
|
||||
|
||||
using (var outputProducer = CreateOutputProducer(pipeOptions))
|
||||
|
|
@ -527,7 +534,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
|||
readerScheduler: _libuvThread,
|
||||
writerScheduler: PipeScheduler.Inline,
|
||||
pauseWriterThreshold: maxResponseBufferSize,
|
||||
resumeWriterThreshold: maxResponseBufferSize
|
||||
resumeWriterThreshold: maxResponseBufferSize,
|
||||
useSynchronizationContext: false
|
||||
);
|
||||
|
||||
using (var outputProducer = CreateOutputProducer(pipeOptions))
|
||||
|
|
@ -610,7 +618,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
|||
readerScheduler: _libuvThread,
|
||||
writerScheduler: PipeScheduler.Inline,
|
||||
pauseWriterThreshold: maxResponseBufferSize,
|
||||
resumeWriterThreshold: maxResponseBufferSize
|
||||
resumeWriterThreshold: maxResponseBufferSize,
|
||||
useSynchronizationContext: false
|
||||
);
|
||||
|
||||
using (var outputProducer = CreateOutputProducer(pipeOptions))
|
||||
|
|
@ -672,7 +681,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
|||
readerScheduler: _libuvThread,
|
||||
writerScheduler: PipeScheduler.Inline,
|
||||
pauseWriterThreshold: maxResponseBufferSize ?? 0,
|
||||
resumeWriterThreshold: maxResponseBufferSize ?? 0
|
||||
resumeWriterThreshold: maxResponseBufferSize ?? 0,
|
||||
useSynchronizationContext: false
|
||||
);
|
||||
|
||||
using (var outputProducer = CreateOutputProducer(pipeOptions))
|
||||
|
|
|
|||
|
|
@ -13,8 +13,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests.TestHelpers
|
|||
{
|
||||
public class MockConnectionHandler : IConnectionHandler
|
||||
{
|
||||
public Func<MemoryPool<byte>, PipeOptions> InputOptions { get; set; } = pool => new PipeOptions(pool, readerScheduler: PipeScheduler.Inline, writerScheduler: PipeScheduler.Inline);
|
||||
public Func<MemoryPool<byte>, PipeOptions> OutputOptions { get; set; } = pool => new PipeOptions(pool, readerScheduler: PipeScheduler.Inline, writerScheduler: PipeScheduler.Inline);
|
||||
public Func<MemoryPool<byte>, PipeOptions> InputOptions { get; set; } = pool => new PipeOptions(pool, readerScheduler: PipeScheduler.Inline, writerScheduler: PipeScheduler.Inline, useSynchronizationContext: false);
|
||||
public Func<MemoryPool<byte>, PipeOptions> OutputOptions { get; set; } = pool => new PipeOptions(pool, readerScheduler: PipeScheduler.Inline, writerScheduler: PipeScheduler.Inline, useSynchronizationContext: false);
|
||||
|
||||
public void OnConnection(IFeatureCollection features)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
|||
{
|
||||
public static IWebHostBuilder GetWebHostBuilder()
|
||||
{
|
||||
return new WebHostBuilder().UseSockets();
|
||||
return new WebHostBuilder().UseSockets().ConfigureServices(TestServer.RemoveDevCert);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue