Update to new corefx (#2369)

This commit is contained in:
Pavel Krymets 2018-03-08 14:23:07 -08:00 committed by GitHub
parent 592ae79cf5
commit fc80c15a65
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
51 changed files with 200 additions and 216 deletions

View File

@ -24,7 +24,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
public void Setup() public void Setup()
{ {
var memoryPool = KestrelMemoryPool.Create(); 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 var serviceContext = new ServiceContext
{ {

View File

@ -96,7 +96,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
private TestHttp1Connection MakeHttp1Connection() 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; _pair = pair;
var serviceContext = new ServiceContext var serviceContext = new ServiceContext

View File

@ -80,7 +80,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
public HttpProtocolFeatureCollection() public HttpProtocolFeatureCollection()
{ {
var memoryPool = KestrelMemoryPool.Create(); 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 var serviceContext = new ServiceContext
{ {

View File

@ -156,7 +156,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
public class InMemoryConnection : TransportConnection public class InMemoryConnection : TransportConnection
{ {
public PipeAwaiter<FlushResult> SendRequestAsync(byte[] request) public ValueTask<FlushResult> SendRequestAsync(byte[] request)
{ {
return Input.WriteAsync(request); return Input.WriteAsync(request);
} }

View File

@ -25,7 +25,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
public void Setup() public void Setup()
{ {
_memoryPool = KestrelMemoryPool.Create(); _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 var serviceContext = new ServiceContext
{ {
@ -147,7 +148,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
return; return;
} }
var readableBuffer = awaitable.GetResult().Buffer; var readableBuffer = awaitable.GetAwaiter().GetResult().Buffer;
do do
{ {
Http1Connection.Reset(); Http1Connection.Reset();

View File

@ -172,7 +172,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
public void Setup() public void Setup()
{ {
var memoryPool = KestrelMemoryPool.Create(); 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 var serviceContext = new ServiceContext
{ {

View File

@ -114,7 +114,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
public void Setup() public void Setup()
{ {
_memoryPool = KestrelMemoryPool.Create(); _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 var serviceContext = new ServiceContext
{ {

View File

@ -16,7 +16,8 @@
<MicrosoftAspNetCoreHttpPackageVersion>2.1.0-preview2-30272</MicrosoftAspNetCoreHttpPackageVersion> <MicrosoftAspNetCoreHttpPackageVersion>2.1.0-preview2-30272</MicrosoftAspNetCoreHttpPackageVersion>
<MicrosoftAspNetCoreTestingPackageVersion>2.1.0-preview2-30272</MicrosoftAspNetCoreTestingPackageVersion> <MicrosoftAspNetCoreTestingPackageVersion>2.1.0-preview2-30272</MicrosoftAspNetCoreTestingPackageVersion>
<MicrosoftAspNetCoreWebUtilitiesPackageVersion>2.1.0-preview2-30272</MicrosoftAspNetCoreWebUtilitiesPackageVersion> <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> <MicrosoftExtensionsConfigurationBinderPackageVersion>2.1.0-preview2-30272</MicrosoftExtensionsConfigurationBinderPackageVersion>
<MicrosoftExtensionsConfigurationJsonPackageVersion>2.1.0-preview2-30272</MicrosoftExtensionsConfigurationJsonPackageVersion> <MicrosoftExtensionsConfigurationJsonPackageVersion>2.1.0-preview2-30272</MicrosoftExtensionsConfigurationJsonPackageVersion>
<MicrosoftExtensionsDependencyInjectionPackageVersion>2.1.0-preview2-30272</MicrosoftExtensionsDependencyInjectionPackageVersion> <MicrosoftExtensionsDependencyInjectionPackageVersion>2.1.0-preview2-30272</MicrosoftExtensionsDependencyInjectionPackageVersion>
@ -26,18 +27,18 @@
<MicrosoftExtensionsLoggingTestingPackageVersion>2.1.0-preview2-30272</MicrosoftExtensionsLoggingTestingPackageVersion> <MicrosoftExtensionsLoggingTestingPackageVersion>2.1.0-preview2-30272</MicrosoftExtensionsLoggingTestingPackageVersion>
<MicrosoftExtensionsOptionsPackageVersion>2.1.0-preview2-30272</MicrosoftExtensionsOptionsPackageVersion> <MicrosoftExtensionsOptionsPackageVersion>2.1.0-preview2-30272</MicrosoftExtensionsOptionsPackageVersion>
<MicrosoftNETCoreApp20PackageVersion>2.0.0</MicrosoftNETCoreApp20PackageVersion> <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> <MicrosoftNetHttpHeadersPackageVersion>2.1.0-preview2-30272</MicrosoftNetHttpHeadersPackageVersion>
<MicrosoftNETTestSdkPackageVersion>15.6.0</MicrosoftNETTestSdkPackageVersion> <MicrosoftNETTestSdkPackageVersion>15.6.0</MicrosoftNETTestSdkPackageVersion>
<MoqPackageVersion>4.7.49</MoqPackageVersion> <MoqPackageVersion>4.7.49</MoqPackageVersion>
<NewtonsoftJsonPackageVersion>10.0.1</NewtonsoftJsonPackageVersion> <NewtonsoftJsonPackageVersion>10.0.1</NewtonsoftJsonPackageVersion>
<SystemBuffersPackageVersion>4.5.0-preview2-26224-02</SystemBuffersPackageVersion> <SystemBuffersPackageVersion>4.5.0-preview2-26308-02</SystemBuffersPackageVersion>
<SystemIOPipelinesPackageVersion>4.5.0-preview2-26224-02</SystemIOPipelinesPackageVersion> <SystemIOPipelinesPackageVersion>4.5.0-preview2-26308-02</SystemIOPipelinesPackageVersion>
<SystemMemoryPackageVersion>4.5.0-preview2-26224-02</SystemMemoryPackageVersion> <SystemMemoryPackageVersion>4.5.0-preview2-26308-02</SystemMemoryPackageVersion>
<SystemNumericsVectorsPackageVersion>4.5.0-preview2-26224-02</SystemNumericsVectorsPackageVersion> <SystemNumericsVectorsPackageVersion>4.5.0-preview2-26308-02</SystemNumericsVectorsPackageVersion>
<SystemRuntimeCompilerServicesUnsafePackageVersion>4.5.0-preview2-26224-02</SystemRuntimeCompilerServicesUnsafePackageVersion> <SystemRuntimeCompilerServicesUnsafePackageVersion>4.5.0-preview2-26308-02</SystemRuntimeCompilerServicesUnsafePackageVersion>
<SystemSecurityCryptographyCngPackageVersion>4.5.0-preview2-26224-02</SystemSecurityCryptographyCngPackageVersion> <SystemSecurityCryptographyCngPackageVersion>4.5.0-preview2-26308-02</SystemSecurityCryptographyCngPackageVersion>
<SystemThreadingTasksExtensionsPackageVersion>4.5.0-preview2-26224-02</SystemThreadingTasksExtensionsPackageVersion> <SystemThreadingTasksExtensionsPackageVersion>4.5.0-preview2-26308-02</SystemThreadingTasksExtensionsPackageVersion>
<XunitAnalyzersPackageVersion>0.8.0</XunitAnalyzersPackageVersion> <XunitAnalyzersPackageVersion>0.8.0</XunitAnalyzersPackageVersion>
<XunitPackageVersion>2.3.1</XunitPackageVersion> <XunitPackageVersion>2.3.1</XunitPackageVersion>
<XunitRunnerVisualStudioPackageVersion>2.4.0-beta.1.build3945</XunitRunnerVisualStudioPackageVersion> <XunitRunnerVisualStudioPackageVersion>2.4.0-beta.1.build3945</XunitRunnerVisualStudioPackageVersion>

View File

@ -1,6 +1,8 @@
<Project> <Project>
<Import Project="..\Directory.Build.props" /> <Import Project="..\Directory.Build.props" />
<PropertyGroup>
<DefineConstants Condition="'$(InnerLoop)' != ''">$(DefineConstants);INNER_LOOP</DefineConstants>
</PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Internal.AspNetCore.Sdk" PrivateAssets="All" Version="$(InternalAspNetCoreSdkPackageVersion)" /> <PackageReference Include="Internal.AspNetCore.Sdk" PrivateAssets="All" Version="$(InternalAspNetCoreSdkPackageVersion)" />
</ItemGroup> </ItemGroup>

View File

@ -139,7 +139,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Adapter.Internal
} }
#if NETCOREAPP2_1 #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); Log("WriteAsync", source.Span);
return _inner.WriteAsync(source, cancellationToken); return _inner.WriteAsync(source, cancellationToken);

View File

@ -92,7 +92,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Adapter.Internal
} }
#if NETCOREAPP2_1 #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); _output.Write(source.Span);
await _output.FlushAsync(cancellationToken); await _output.FlushAsync(cancellationToken);

View File

@ -89,7 +89,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
readerScheduler: serviceContext.ThreadPool, readerScheduler: serviceContext.ThreadPool,
writerScheduler: writerScheduler, writerScheduler: writerScheduler,
pauseWriterThreshold: serviceContext.ServerOptions.Limits.MaxRequestBufferSize ?? 0, 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 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, readerScheduler: readerScheduler,
writerScheduler: serviceContext.ThreadPool, writerScheduler: serviceContext.ThreadPool,
pauseWriterThreshold: GetOutputResponseBufferSize(serviceContext), pauseWriterThreshold: GetOutputResponseBufferSize(serviceContext),
resumeWriterThreshold: GetOutputResponseBufferSize(serviceContext) resumeWriterThreshold: GetOutputResponseBufferSize(serviceContext),
useSynchronizationContext: false
); );
private static long GetOutputResponseBufferSize(ServiceContext serviceContext) private static long GetOutputResponseBufferSize(ServiceContext serviceContext)

View File

@ -10,6 +10,7 @@ using System.Runtime.InteropServices;
using System.Text; using System.Text;
using System.Text.Encodings.Web; using System.Text.Encodings.Web;
using System.Threading; using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Protocols.Abstractions; using Microsoft.AspNetCore.Protocols.Abstractions;
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure; 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); TimeoutControl.SetTimeout(_keepAliveTicks, TimeoutAction.StopProcessingNextRequest);
} }
protected override bool BeginRead(out PipeAwaiter<ReadResult> awaitable) protected override bool BeginRead(out ValueTask<ReadResult> awaitable)
{ {
awaitable = Input.ReadAsync(); awaitable = Input.ReadAsync();
return true; return true;

View File

@ -93,12 +93,13 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
BadHttpRequestException.Throw(RequestRejectionReason.UnexpectedEndOfRequestContent); BadHttpRequestException.Throw(RequestRejectionReason.UnexpectedEndOfRequestContent);
} }
awaitable = _context.Input.ReadAsync();
} }
finally finally
{ {
_context.Input.AdvanceTo(consumed, examined); _context.Input.AdvanceTo(consumed, examined);
} }
awaitable = _context.Input.ReadAsync();
} }
} }
catch (Exception ex) catch (Exception ex)
@ -320,7 +321,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
var actual = (int)Math.Min(readableBuffer.Length, _inputLength); var actual = (int)Math.Min(readableBuffer.Length, _inputLength);
_inputLength -= actual; _inputLength -= actual;
consumed = readableBuffer.GetPosition(readableBuffer.Start, actual); consumed = readableBuffer.GetPosition(actual);
examined = consumed; examined = consumed;
Copy(readableBuffer.Slice(0, actual), writableBuffer); 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) private void ReadChunkedData(ReadOnlySequence<byte> buffer, PipeWriter writableBuffer, out SequencePosition consumed, out SequencePosition examined)
{ {
var actual = Math.Min(buffer.Length, _inputLength); var actual = Math.Min(buffer.Length, _inputLength);
consumed = buffer.GetPosition(buffer.Start, actual); consumed = buffer.GetPosition(actual);
examined = consumed; examined = consumed;
Copy(buffer.Slice(0, actual), writableBuffer); Copy(buffer.Slice(0, actual), writableBuffer);

View File

@ -38,6 +38,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
private readonly object _flushLock = new object(); private readonly object _flushLock = new object();
private Action _flushCompleted; private Action _flushCompleted;
private ValueTask<FlushResult> _flushTask;
public Http1OutputProducer( public Http1OutputProducer(
PipeReader outputPipeReader, PipeReader outputPipeReader,
PipeWriter pipeWriter, PipeWriter pipeWriter,
@ -200,7 +202,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
return FlushAsyncAwaited(awaitable, bytesWritten, cancellationToken); 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 // https://github.com/dotnet/corefxlab/issues/1334
// Since the flush awaitable doesn't currently support multiple awaiters // 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 // All awaiters get the same task
lock (_flushLock) lock (_flushLock)
{ {
_flushTask = awaitable;
if (_flushTcs == null || _flushTcs.Task.IsCompleted) if (_flushTcs == null || _flushTcs.Task.IsCompleted)
{ {
_flushTcs = new TaskCompletionSource<object>(); _flushTcs = new TaskCompletionSource<object>();
awaitable.OnCompleted(_flushCompleted); _flushTask.GetAwaiter().OnCompleted(_flushCompleted);
} }
} }
_timeoutControl.StartTimingWrite(count); _timeoutControl.StartTimingWrite(count);
await _flushTcs.Task; try
_timeoutControl.StopTimingWrite(); {
await _flushTcs.Task;
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();
}
catch (OperationCanceledException)
{
_completed = true;
throw;
}
finally
{
_timeoutControl.StopTimingWrite();
}
} }
private void OnFlushCompleted() private void OnFlushCompleted()
{ {
_flushTcs.TrySetResult(null); try
{
_flushTask.GetAwaiter().GetResult();
_flushTcs.TrySetResult(null);
}
catch (Exception exception)
{
_flushTcs.TrySetResult(exception);
}
finally
{
_flushTask = default;
}
} }
} }
} }

View File

@ -44,7 +44,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
var lineIndex = span.IndexOf(ByteLF); var lineIndex = span.IndexOf(ByteLF);
if (lineIndex >= 0) if (lineIndex >= 0)
{ {
consumed = buffer.GetPosition(consumed, lineIndex + 1); consumed = buffer.GetPosition(lineIndex + 1, consumed);
span = span.Slice(0, lineIndex + 1); span = span.Slice(0, lineIndex + 1);
} }
else if (buffer.IsSingleSegment) else if (buffer.IsSingleSegment)
@ -293,7 +293,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
var lineEnd = lineEndPosition.Value; var lineEnd = lineEndPosition.Value;
// Make sure LF is included in lineEnd // Make sure LF is included in lineEnd
lineEnd = buffer.GetPosition(lineEnd, 1); lineEnd = buffer.GetPosition(1, lineEnd);
var headerSpan = buffer.Slice(current, lineEnd).ToSpan(); var headerSpan = buffer.Slice(current, lineEnd).ToSpan();
length = headerSpan.Length; length = headerSpan.Length;
@ -425,7 +425,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if (byteLfPosition != null) if (byteLfPosition != null)
{ {
// Move 1 byte past the \n // Move 1 byte past the \n
found = buffer.GetPosition(byteLfPosition.Value, 1); found = buffer.GetPosition(1, byteLfPosition.Value);
return true; return true;
} }

View File

@ -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; awaitable = default;
return false; return false;
@ -1336,7 +1336,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
readerScheduler: ServiceContext.ThreadPool, readerScheduler: ServiceContext.ThreadPool,
writerScheduler: PipeScheduler.Inline, writerScheduler: PipeScheduler.Inline,
pauseWriterThreshold: 1, pauseWriterThreshold: 1,
resumeWriterThreshold: 1 resumeWriterThreshold: 1,
useSynchronizationContext: false
)); ));
} }
} }

View File

@ -112,11 +112,11 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
} }
#if NETCOREAPP2_1 #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); ValidateState(cancellationToken);
return _httpResponseControl.WriteAsync(source, cancellationToken); return new ValueTask(_httpResponseControl.WriteAsync(source, cancellationToken));
} }
#endif #endif

View File

@ -53,7 +53,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
// buffer.Count is int // buffer.Count is int
var actual = (int) Math.Min(readableBuffer.Length, buffer.Length); var actual = (int) Math.Min(readableBuffer.Length, buffer.Length);
var slice = readableBuffer.Slice(0, actual); var slice = readableBuffer.Slice(0, actual);
consumed = readableBuffer.GetPosition(readableBuffer.Start, actual); consumed = readableBuffer.GetPosition(actual);
slice.CopyTo(buffer.Span); slice.CopyTo(buffer.Span);
return actual; return actual;
} }

View File

@ -28,12 +28,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
public static ArraySegment<byte> GetArray(this Memory<byte> buffer) public static ArraySegment<byte> GetArray(this Memory<byte> buffer)
{ {
ArraySegment<byte> result; return ((ReadOnlyMemory<byte>)buffer).GetArray();
if (!buffer.TryGetArray(out result))
{
throw new InvalidOperationException("Buffer backed by array was expected");
}
return result;
} }
public static ArraySegment<byte> GetArray(this ReadOnlyMemory<byte> memory) public static ArraySegment<byte> GetArray(this ReadOnlyMemory<byte> memory)

View File

@ -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; return true;
} }

View File

@ -28,7 +28,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
} }
readableBuffer.Slice(Http2Frame.HeaderLength, frame.Length).CopyTo(frame.Payload); 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; return true;
} }

View File

@ -77,7 +77,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
readerScheduler: _context.ServiceContext.ThreadPool, readerScheduler: _context.ServiceContext.ThreadPool,
writerScheduler: PipeScheduler.Inline, writerScheduler: PipeScheduler.Inline,
pauseWriterThreshold: _context.ServiceContext.ServerOptions.Limits.MaxRequestBufferSize ?? 0, 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 internal PipeOptions AdaptedOutputPipeOptions => new PipeOptions
@ -86,7 +87,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
readerScheduler: PipeScheduler.Inline, readerScheduler: PipeScheduler.Inline,
writerScheduler: PipeScheduler.Inline, writerScheduler: PipeScheduler.Inline,
pauseWriterThreshold: _context.ServiceContext.ServerOptions.Limits.MaxResponseBufferSize ?? 0, 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; private IKestrelTrace Log => _context.ServiceContext.Log;

View File

@ -15,20 +15,27 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
private readonly ISystemClock _systemClock; private readonly ISystemClock _systemClock;
private readonly IDebugger _debugger; private readonly IDebugger _debugger;
private readonly IKestrelTrace _trace; private readonly IKestrelTrace _trace;
private readonly TimeSpan _interval;
private Timer _timer; private Timer _timer;
private int _executingOnHeartbeat; 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; _callbacks = callbacks;
_systemClock = systemClock; _systemClock = systemClock;
_debugger = debugger; _debugger = debugger;
_trace = trace; _trace = trace;
_interval = interval;
} }
public void Start() 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) private static void OnHeartbeat(object state)
@ -63,7 +70,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
{ {
if (!_debugger.IsAttached) if (!_debugger.IsAttached)
{ {
_trace.HeartbeatSlow(Interval, now); _trace.HeartbeatSlow(_interval, now);
} }
} }
} }

View File

@ -33,12 +33,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
action(state); action(state);
} }
public override void Schedule(Action action) public override void Schedule<T>(Action<T> action, T state)
{
Run(action);
}
public override void Schedule(Action<object> action, object state)
{ {
try try
{ {

View File

@ -50,12 +50,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
System.Threading.ThreadPool.QueueUserWorkItem(action, state); System.Threading.ThreadPool.QueueUserWorkItem(action, state);
} }
public override void Schedule(Action action) public override void Schedule<T>(Action<T> action, T state)
{
Run(action);
}
public override void Schedule(Action<object> action, object state)
{ {
Run(() => action(state)); Run(() => action(state));
} }

View File

@ -173,7 +173,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
_bufferHandle.Dispose(); _bufferHandle.Dispose();
} }
private async Task ApplyBackpressureAsync(PipeAwaiter<FlushResult> flushTask) private async Task ApplyBackpressureAsync(ValueTask<FlushResult> flushTask)
{ {
Log.ConnectionPause(ConnectionId); Log.ConnectionPause(ConnectionId);
_socket.ReadStop(); _socket.ReadStop();

View File

@ -48,8 +48,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
_log = transport.Log; _log = transport.Log;
_loop = new UvLoopHandle(_log); _loop = new UvLoopHandle(_log);
_post = new UvAsyncHandle(_log); _post = new UvAsyncHandle(_log);
_thread = new Thread(ThreadStart); _thread = new Thread(ThreadStart);
#if !INNER_LOOP
_thread.Name = nameof(LibuvThread); _thread.Name = nameof(LibuvThread);
#endif
#if !DEBUG #if !DEBUG
// Mark the thread as being as unimportant to keeping the process alive. // 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. // 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(); _closeError?.Throw();
} }
#if DEBUG #if DEBUG && !INNER_LOOP
private void CheckUvReqLeaks() private void CheckUvReqLeaks()
{ {
GC.Collect(); GC.Collect();
@ -177,6 +181,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
{ {
CallbackAdapter = CallbackAdapter<T>.PostCallbackAdapter, CallbackAdapter = CallbackAdapter<T>.PostCallbackAdapter,
Callback = callback, Callback = callback,
//TODO: This boxes
State = state State = state
}; };
@ -301,7 +306,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
WriteReqPool.Dispose(); WriteReqPool.Dispose();
_threadTcs.SetResult(null); _threadTcs.SetResult(null);
#if DEBUG #if DEBUG && !INNER_LOOP
// Check for handle leaks after disposing everything // Check for handle leaks after disposing everything
CheckUvReqLeaks(); CheckUvReqLeaks();
#endif #endif
@ -391,12 +396,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
return await Task.WhenAny(task, Task.Delay(timeout)).ConfigureAwait(false) == task; return await Task.WhenAny(task, Task.Delay(timeout)).ConfigureAwait(false) == task;
} }
public override void Schedule(Action action) public override void Schedule<T>(Action<T> action, T state)
{
Post(state => state(), action);
}
public override void Schedule(Action<object> action, object state)
{ {
Post(action, state); Post(action, state);
} }

View File

@ -51,7 +51,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networkin
{ {
_uv = uv; _uv = uv;
ThreadId = threadId; ThreadId = threadId;
handle = Marshal.AllocCoTaskMem(size); handle = Marshal.AllocCoTaskMem(size);
*(IntPtr*)handle = GCHandle.ToIntPtr(GCHandle.Alloc(this, _handleType)); *(IntPtr*)handle = GCHandle.ToIntPtr(GCHandle.Alloc(this, _handleType));
} }

View File

@ -62,7 +62,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv
} }
Threads.Clear(); Threads.Clear();
#if DEBUG #if DEBUG && !INNER_LOOP
GC.Collect(); GC.Collect();
GC.WaitForPendingFinalizers(); GC.WaitForPendingFinalizers();
GC.Collect(); GC.Collect();

View File

@ -10,11 +10,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal
{ {
public static ArraySegment<byte> GetArray(this Memory<byte> memory) public static ArraySegment<byte> GetArray(this Memory<byte> memory)
{ {
if (!memory.TryGetArray(out var result)) return ((ReadOnlyMemory<byte>)memory).GetArray();
{
throw new InvalidOperationException("Buffer backed by array was expected");
}
return result;
} }
public static ArraySegment<byte> GetArray(this ReadOnlyMemory<byte> memory) public static ArraySegment<byte> GetArray(this ReadOnlyMemory<byte> memory)

View File

@ -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) public static DuplexPipePair CreateConnectionPair(PipeOptions inputOptions, PipeOptions outputOptions)
{ {
var input = new Pipe(inputOptions); var input = new Pipe(inputOptions);

View File

@ -3,6 +3,7 @@
using System; using System;
using System.Linq; using System.Linq;
using System.Numerics;
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure; using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
using Xunit; using Xunit;
@ -41,7 +42,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
[InlineData(0x80)] [InlineData(0x80)]
private void ExceptionThrownForZeroOrNonAscii(byte b) 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++) for (var position = 0; position < length; position++)
{ {

View File

@ -65,11 +65,11 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
debugger.Setup(d => d.IsAttached).Returns(true); debugger.Setup(d => d.IsAttached).Returns(true);
kestrelTrace.Setup(t => t.HeartbeatSlow(Heartbeat.Interval, systemClock.UtcNow)).Callback(() => traceMre.Set()); 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[0] = Task.Run(() => heartbeat.OnHeartbeat());
onHeartbeatTasks[1] = 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(); handlerMre.Set();

View File

@ -41,7 +41,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
public Http1ConnectionTests() public Http1ConnectionTests()
{ {
_pipelineFactory = KestrelMemoryPool.Create(); _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; _transport = pair.Transport;
_application = pair.Application; _application = pair.Application;

View File

@ -126,7 +126,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
var inlineSchedulingPipeOptions = new PipeOptions( var inlineSchedulingPipeOptions = new PipeOptions(
pool: _memoryPool, pool: _memoryPool,
readerScheduler: PipeScheduler.Inline, readerScheduler: PipeScheduler.Inline,
writerScheduler: PipeScheduler.Inline writerScheduler: PipeScheduler.Inline,
useSynchronizationContext: false
); );
_pair = DuplexPipe.CreateConnectionPair(inlineSchedulingPipeOptions, inlineSchedulingPipeOptions); _pair = DuplexPipe.CreateConnectionPair(inlineSchedulingPipeOptions, inlineSchedulingPipeOptions);

View File

@ -26,7 +26,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
public HttpConnectionTests() public HttpConnectionTests()
{ {
_memoryPool = KestrelMemoryPool.Create(); _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 _httpConnectionContext = new HttpConnectionContext
{ {

View File

@ -18,6 +18,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
{ {
public class HttpParserTests public class HttpParserTests
{ {
private static IKestrelTrace _nullTrace = Mock.Of<IKestrelTrace>();
[Theory] [Theory]
[MemberData(nameof(RequestLineValidData))] [MemberData(nameof(RequestLineValidData))]
public void ParsesRequestLine( public void ParsesRequestLine(
@ -33,7 +35,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
#pragma warning restore xUnit1026 #pragma warning restore xUnit1026
string expectedVersion) string expectedVersion)
{ {
var parser = CreateParser(Mock.Of<IKestrelTrace>()); var parser = CreateParser(_nullTrace);
var buffer = new ReadOnlySequence<byte>(Encoding.ASCII.GetBytes(requestLine)); var buffer = new ReadOnlySequence<byte>(Encoding.ASCII.GetBytes(requestLine));
var requestHandler = new RequestHandler(); var requestHandler = new RequestHandler();
@ -52,7 +54,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
[MemberData(nameof(RequestLineIncompleteData))] [MemberData(nameof(RequestLineIncompleteData))]
public void ParseRequestLineReturnsFalseWhenGivenIncompleteRequestLines(string requestLine) 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 buffer = new ReadOnlySequence<byte>(Encoding.ASCII.GetBytes(requestLine));
var requestHandler = new RequestHandler(); var requestHandler = new RequestHandler();
@ -63,7 +65,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
[MemberData(nameof(RequestLineIncompleteData))] [MemberData(nameof(RequestLineIncompleteData))]
public void ParseRequestLineDoesNotConsumeIncompleteRequestLine(string requestLine) 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 buffer = new ReadOnlySequence<byte>(Encoding.ASCII.GetBytes(requestLine));
var requestHandler = new RequestHandler(); 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")] [InlineData("Header-1: value1\r\nHeader-2: value2\r\n\r")]
public void ParseHeadersReturnsFalseWhenGivenIncompleteHeaders(string rawHeaders) 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 buffer = new ReadOnlySequence<byte>(Encoding.ASCII.GetBytes(rawHeaders));
var requestHandler = new RequestHandler(); var requestHandler = new RequestHandler();
@ -201,7 +203,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
[InlineData("Header: value\r")] [InlineData("Header: value\r")]
public void ParseHeadersDoesNotConsumeIncompleteHeader(string rawHeaders) 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 buffer = new ReadOnlySequence<byte>(Encoding.ASCII.GetBytes(rawHeaders));
var requestHandler = new RequestHandler(); var requestHandler = new RequestHandler();
@ -290,14 +292,14 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
[Fact] [Fact]
public void ParseHeadersConsumesBytesCorrectlyAtEnd() public void ParseHeadersConsumesBytesCorrectlyAtEnd()
{ {
var parser = CreateParser(Mock.Of<IKestrelTrace>()); var parser = CreateParser(_nullTrace);
const string headerLine = "Header: value\r\n\r"; const string headerLine = "Header: value\r\n\r";
var buffer1 = new ReadOnlySequence<byte>(Encoding.ASCII.GetBytes(headerLine)); var buffer1 = new ReadOnlySequence<byte>(Encoding.ASCII.GetBytes(headerLine));
var requestHandler = new RequestHandler(); var requestHandler = new RequestHandler();
Assert.False(parser.ParseHeaders(requestHandler, buffer1, out var consumed, out var examined, out var consumedBytes)); 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(buffer1.End, examined);
Assert.Equal(headerLine.Length - 1, consumedBytes); Assert.Equal(headerLine.Length - 1, consumedBytes);
@ -371,8 +373,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
[Fact] [Fact]
public void ParseRequestLineSplitBufferWithoutNewLineDoesNotUpdateConsumed() public void ParseRequestLineSplitBufferWithoutNewLineDoesNotUpdateConsumed()
{ {
var parser = CreateParser(Mock.Of<IKestrelTrace>()); var parser = CreateParser(_nullTrace);
var buffer = CreateBuffer("GET ", "/"); var buffer = ReadOnlySequenceFactory.CreateSegments(
Encoding.ASCII.GetBytes("GET "),
Encoding.ASCII.GetBytes("/"));
var requestHandler = new RequestHandler(); var requestHandler = new RequestHandler();
var result = parser.ParseRequestLine(requestHandler, buffer, out var consumed, out var examined); 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 rawHeaderValue,
string expectedHeaderValue) 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 buffer = new ReadOnlySequence<byte>(Encoding.ASCII.GetBytes($"{headerName}:{rawHeaderValue}\r\n"));
var requestHandler = new RequestHandler(); 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"); 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 buffer = new ReadOnlySequence<byte>(Encoding.ASCII.GetBytes(rawHeaders));
var requestHandler = new RequestHandler(); var requestHandler = new RequestHandler();
@ -465,86 +469,5 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
PathEncoded = pathEncoded; 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;
}
}
} }
} }

View File

@ -24,15 +24,16 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
private readonly TestHttp1Connection _http1Connection; private readonly TestHttp1Connection _http1Connection;
private readonly ServiceContext _serviceContext; private readonly ServiceContext _serviceContext;
private readonly Http1ConnectionContext _http1ConnectionContext; private readonly Http1ConnectionContext _http1ConnectionContext;
private readonly MemoryPool<byte> _pipelineFactory; private readonly MemoryPool<byte> _memoryPool;
private Mock<ITimeoutControl> _timeoutControl; private Mock<ITimeoutControl> _timeoutControl;
private readonly IFeatureCollection _collection; private readonly IFeatureCollection _collection;
public HttpProtocolFeatureCollectionTests() public HttpProtocolFeatureCollectionTests()
{ {
_pipelineFactory = KestrelMemoryPool.Create(); _memoryPool = KestrelMemoryPool.Create();
var pair = DuplexPipe.CreateConnectionPair(_pipelineFactory); var options = new PipeOptions(_memoryPool, readerScheduler: PipeScheduler.Inline, writerScheduler: PipeScheduler.Inline, useSynchronizationContext: false);
var pair = DuplexPipe.CreateConnectionPair(options, options);
_transport = pair.Transport; _transport = pair.Transport;
_application = pair.Application; _application = pair.Application;
@ -43,7 +44,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
{ {
ServiceContext = _serviceContext, ServiceContext = _serviceContext,
ConnectionFeatures = new FeatureCollection(), ConnectionFeatures = new FeatureCollection(),
MemoryPool = _pipelineFactory, MemoryPool = _memoryPool,
TimeoutControl = _timeoutControl.Object, TimeoutControl = _timeoutControl.Object,
Application = pair.Application, Application = pair.Application,
Transport = pair.Transport Transport = pair.Transport
@ -62,7 +63,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
_application.Input.Complete(); _application.Input.Complete();
_application.Output.Complete(); _application.Output.Complete();
_pipelineFactory.Dispose(); _memoryPool.Dispose();
} }
[Fact] [Fact]

View File

@ -23,7 +23,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
{ {
using (var memoryPool = KestrelMemoryPool.Create()) 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 var http1ConnectionContext = new Http1ConnectionContext
{ {
ServiceContext = new TestServiceContext(), ServiceContext = new TestServiceContext(),

View File

@ -23,6 +23,7 @@
<PackageReference Include="Microsoft.AspNetCore.Http" Version="$(MicrosoftAspNetCoreHttpPackageVersion)" /> <PackageReference Include="Microsoft.AspNetCore.Http" Version="$(MicrosoftAspNetCoreHttpPackageVersion)" />
<PackageReference Include="System.Memory" Version="$(SystemMemoryPackageVersion)" /> <PackageReference Include="System.Memory" Version="$(SystemMemoryPackageVersion)" />
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="$(SystemRuntimeCompilerServicesUnsafePackageVersion)" /> <PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="$(SystemRuntimeCompilerServicesUnsafePackageVersion)" />
<PackageReference Include="Microsoft.Extensions.Buffers.Testing.Sources" Version="$(MicrosoftExtensionsBuffersSourcesTestingPackageVersion)" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -35,7 +35,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
( (
pool: _memoryPool, pool: _memoryPool,
readerScheduler: Mock.Of<PipeScheduler>(), readerScheduler: Mock.Of<PipeScheduler>(),
writerScheduler: PipeScheduler.Inline writerScheduler: PipeScheduler.Inline,
useSynchronizationContext: false
); );
using (var socketOutput = CreateOutputProducer(pipeOptions)) using (var socketOutput = CreateOutputProducer(pipeOptions))

View File

@ -21,7 +21,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
public PipelineExtensionTests() 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() public void Dispose()

View File

@ -22,7 +22,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
public TestInput() public TestInput()
{ {
_memoryPool = KestrelMemoryPool.Create(); _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); var pair = DuplexPipe.CreateConnectionPair(options, options);
Transport = pair.Transport; Transport = pair.Transport;
Application = pair.Application; Application = pair.Application;

View File

@ -1,6 +1,6 @@
// Copyright (c) .NET Foundation. All rights reserved. // 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. // 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;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
@ -252,3 +252,4 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
} }
} }
} }
#endif

View File

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System; using System;
using System.Linq;
using System.Net; using System.Net;
using System.Net.Sockets; using System.Net.Sockets;
using System.Reflection; using System.Reflection;
@ -11,9 +12,11 @@ using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Hosting.Server; using Microsoft.AspNetCore.Hosting.Server;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Server.Kestrel.Core; using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal;
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal; using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
using Microsoft.AspNetCore.Testing; using Microsoft.AspNetCore.Testing;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
@ -68,7 +71,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
} }
return new KestrelServer(sp.GetRequiredService<ITransportFactory>(), context); return new KestrelServer(sp.GetRequiredService<ITransportFactory>(), context);
}); });
RemoveDevCert(services);
configureServices(services); configureServices(services);
}) })
.UseSetting(WebHostDefaults.ApplicationKey, typeof(TestServer).GetTypeInfo().Assembly.FullName) .UseSetting(WebHostDefaults.ApplicationKey, typeof(TestServer).GetTypeInfo().Assembly.FullName)
@ -77,6 +80,19 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
_host.Start(); _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 IPEndPoint EndPoint => _listenOptions.IPEndPoint;
public int Port => _listenOptions.IPEndPoint.Port; public int Port => _listenOptions.IPEndPoint.Port;
public AddressFamily AddressFamily => _listenOptions.IPEndPoint.AddressFamily; public AddressFamily AddressFamily => _listenOptions.IPEndPoint.AddressFamily;

View File

@ -9,7 +9,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
{ {
public static IWebHostBuilder GetWebHostBuilder() public static IWebHostBuilder GetWebHostBuilder()
{ {
return new WebHostBuilder().UseLibuv(); return new WebHostBuilder().UseLibuv().ConfigureServices(TestServer.RemoveDevCert);
} }
} }
} }

View File

@ -64,11 +64,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
pool: pool, pool: pool,
pauseWriterThreshold: 3, pauseWriterThreshold: 3,
readerScheduler: PipeScheduler.Inline, 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 // 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; Task connectionTask = null;
@ -121,9 +122,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
var thread = new LibuvThread(transport); var thread = new LibuvThread(transport);
var mockScheduler = new Mock<PipeScheduler>(); var mockScheduler = new Mock<PipeScheduler>();
Action backPressure = null; 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 => mockConnectionHandler.InputOptions = pool =>
new PipeOptions( new PipeOptions(
@ -131,9 +132,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
pauseWriterThreshold: 3, pauseWriterThreshold: 3,
resumeWriterThreshold: 3, resumeWriterThreshold: 3,
writerScheduler: mockScheduler.Object, 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; Task connectionTask = null;
try try

View File

@ -69,7 +69,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
readerScheduler: _libuvThread, readerScheduler: _libuvThread,
writerScheduler: PipeScheduler.Inline, writerScheduler: PipeScheduler.Inline,
pauseWriterThreshold: maxResponseBufferSize ?? 0, pauseWriterThreshold: maxResponseBufferSize ?? 0,
resumeWriterThreshold: maxResponseBufferSize ?? 0 resumeWriterThreshold: maxResponseBufferSize ?? 0,
useSynchronizationContext: false
); );
using (var outputProducer = CreateOutputProducer(pipeOptions)) using (var outputProducer = CreateOutputProducer(pipeOptions))
@ -106,7 +107,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
readerScheduler: _libuvThread, readerScheduler: _libuvThread,
writerScheduler: PipeScheduler.Inline, writerScheduler: PipeScheduler.Inline,
pauseWriterThreshold: 0, pauseWriterThreshold: 0,
resumeWriterThreshold: 0 resumeWriterThreshold: 0,
useSynchronizationContext: false
); );
using (var outputProducer = CreateOutputProducer(pipeOptions)) using (var outputProducer = CreateOutputProducer(pipeOptions))
@ -155,7 +157,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
readerScheduler: _libuvThread, readerScheduler: _libuvThread,
writerScheduler: PipeScheduler.Inline, writerScheduler: PipeScheduler.Inline,
pauseWriterThreshold: 1, pauseWriterThreshold: 1,
resumeWriterThreshold: 1 resumeWriterThreshold: 1,
useSynchronizationContext: false
); );
using (var outputProducer = CreateOutputProducer(pipeOptions)) using (var outputProducer = CreateOutputProducer(pipeOptions))
@ -212,7 +215,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
readerScheduler: _libuvThread, readerScheduler: _libuvThread,
writerScheduler: PipeScheduler.Inline, writerScheduler: PipeScheduler.Inline,
pauseWriterThreshold: maxResponseBufferSize, pauseWriterThreshold: maxResponseBufferSize,
resumeWriterThreshold: maxResponseBufferSize resumeWriterThreshold: maxResponseBufferSize,
useSynchronizationContext: false
); );
using (var outputProducer = CreateOutputProducer(pipeOptions)) using (var outputProducer = CreateOutputProducer(pipeOptions))
@ -277,7 +281,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
readerScheduler: _libuvThread, readerScheduler: _libuvThread,
writerScheduler: PipeScheduler.Inline, writerScheduler: PipeScheduler.Inline,
pauseWriterThreshold: maxResponseBufferSize, pauseWriterThreshold: maxResponseBufferSize,
resumeWriterThreshold: maxResponseBufferSize resumeWriterThreshold: maxResponseBufferSize,
useSynchronizationContext: false
); );
using (var outputProducer = CreateOutputProducer(pipeOptions)) using (var outputProducer = CreateOutputProducer(pipeOptions))
@ -348,7 +353,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
readerScheduler: _libuvThread, readerScheduler: _libuvThread,
writerScheduler: PipeScheduler.Inline, writerScheduler: PipeScheduler.Inline,
pauseWriterThreshold: maxResponseBufferSize, pauseWriterThreshold: maxResponseBufferSize,
resumeWriterThreshold: maxResponseBufferSize resumeWriterThreshold: maxResponseBufferSize,
useSynchronizationContext: false
); );
using (var outputProducer = CreateOutputProducer(pipeOptions, abortedSource)) using (var outputProducer = CreateOutputProducer(pipeOptions, abortedSource))
@ -442,7 +448,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
readerScheduler: _libuvThread, readerScheduler: _libuvThread,
writerScheduler: PipeScheduler.Inline, writerScheduler: PipeScheduler.Inline,
pauseWriterThreshold: maxResponseBufferSize, pauseWriterThreshold: maxResponseBufferSize,
resumeWriterThreshold: maxResponseBufferSize resumeWriterThreshold: maxResponseBufferSize,
useSynchronizationContext: false
); );
using (var outputProducer = CreateOutputProducer(pipeOptions)) using (var outputProducer = CreateOutputProducer(pipeOptions))
@ -527,7 +534,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
readerScheduler: _libuvThread, readerScheduler: _libuvThread,
writerScheduler: PipeScheduler.Inline, writerScheduler: PipeScheduler.Inline,
pauseWriterThreshold: maxResponseBufferSize, pauseWriterThreshold: maxResponseBufferSize,
resumeWriterThreshold: maxResponseBufferSize resumeWriterThreshold: maxResponseBufferSize,
useSynchronizationContext: false
); );
using (var outputProducer = CreateOutputProducer(pipeOptions)) using (var outputProducer = CreateOutputProducer(pipeOptions))
@ -610,7 +618,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
readerScheduler: _libuvThread, readerScheduler: _libuvThread,
writerScheduler: PipeScheduler.Inline, writerScheduler: PipeScheduler.Inline,
pauseWriterThreshold: maxResponseBufferSize, pauseWriterThreshold: maxResponseBufferSize,
resumeWriterThreshold: maxResponseBufferSize resumeWriterThreshold: maxResponseBufferSize,
useSynchronizationContext: false
); );
using (var outputProducer = CreateOutputProducer(pipeOptions)) using (var outputProducer = CreateOutputProducer(pipeOptions))
@ -672,7 +681,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
readerScheduler: _libuvThread, readerScheduler: _libuvThread,
writerScheduler: PipeScheduler.Inline, writerScheduler: PipeScheduler.Inline,
pauseWriterThreshold: maxResponseBufferSize ?? 0, pauseWriterThreshold: maxResponseBufferSize ?? 0,
resumeWriterThreshold: maxResponseBufferSize ?? 0 resumeWriterThreshold: maxResponseBufferSize ?? 0,
useSynchronizationContext: false
); );
using (var outputProducer = CreateOutputProducer(pipeOptions)) using (var outputProducer = CreateOutputProducer(pipeOptions))

View File

@ -13,8 +13,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests.TestHelpers
{ {
public class MockConnectionHandler : IConnectionHandler 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> 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); 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) public void OnConnection(IFeatureCollection features)
{ {

View File

@ -9,7 +9,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
{ {
public static IWebHostBuilder GetWebHostBuilder() public static IWebHostBuilder GetWebHostBuilder()
{ {
return new WebHostBuilder().UseSockets(); return new WebHostBuilder().UseSockets().ConfigureServices(TestServer.RemoveDevCert);
} }
} }
} }